PROTON-1350 PROTON-1351: Introduce proton-c core library
- Created new core proton library qpid-proton-core which only contains
  protocol processsing and no IO.
- Rearranged source tree to separate core protocol code and io/reactor/extra code
- Rearranged code so that compiler dependent code is isolated and platform (OS)
  dependent code is isolated

This is a large change, but the majority is moving files around and fixing up the header
includes. There is a small amount of internal API changing so support the core searation.
diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt
index cba043a..3cf01cd 100644
--- a/proton-c/CMakeLists.txt
+++ b/proton-c/CMakeLists.txt
@@ -81,8 +81,8 @@
 
 add_custom_command (
   OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/encodings.h
-  COMMAND ${env_py} PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/codec/encodings.h.py > ${CMAKE_CURRENT_BINARY_DIR}/src/encodings.h
-  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/codec/encodings.h.py
+  COMMAND ${env_py} PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/encodings.h.py > ${CMAKE_CURRENT_BINARY_DIR}/src/encodings.h
+  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/encodings.h.py
   )
 
 add_custom_command (
@@ -93,11 +93,11 @@
 
 # Select IO impl
 if(PN_WINAPI)
-  set (pn_io_impl src/windows/io.c src/windows/iocp.c src/windows/write_pipeline.c)
-  set (pn_selector_impl src/windows/selector.c)
+  set (pn_io_impl src/reactor/io/windows/io.c src/reactor/io/windows/iocp.c src/reactor/io/windows/write_pipeline.c)
+  set (pn_selector_impl src/reactor/io/windows/selector.c)
 else(PN_WINAPI)
-  set (pn_io_impl src/posix/io.c)
-  set (pn_selector_impl src/posix/selector.c)
+  set (pn_io_impl src/reactor/io/posix/io.c)
+  set (pn_selector_impl src/reactor/io/posix/selector.c)
 endif(PN_WINAPI)
 
 # Link in SASL if present
@@ -124,7 +124,7 @@
   include_directories (${OPENSSL_INCLUDE_DIR})
   set (SSL_LIB ${OPENSSL_LIBRARIES})
 elseif (SSL_IMPL STREQUAL schannel)
-  set (pn_ssl_impl src/windows/schannel.c)
+  set (pn_ssl_impl src/ssl/schannel.c)
   set (SSL_LIB Crypt32.lib Secur32.lib)
 else ()
   set (pn_ssl_impl src/ssl/ssl_stub.c)
@@ -281,6 +281,7 @@
         /wd4800
         /wd4996
     )
+    set (qpid-proton-platform src/compiler/msvc/snprintf.c)
 endif (MSVC)
 
 macro (pn_absolute_install_dir NAME VALUE PREFIX)
@@ -303,49 +304,61 @@
 add_subdirectory(docs/api)
 add_subdirectory(../tests/tools/apps/c ../tests/tools/apps/c)
 
-set (qpid-proton-platform
+set (qpid-proton-platform-io
+  src/platform/platform.c
   ${pn_io_impl}
   ${pn_selector_impl}
-  src/platform.c
+  )
+
+set (qpid-proton-layers
   ${pn_sasl_impl}
   ${pn_ssl_impl}
   )
 
 set (qpid-proton-core
-  src/object/object.c
-  src/object/list.c
-  src/object/map.c
-  src/object/string.c
-  src/object/iterator.c
-  src/object/record.c
+  src/core/object/object.c
+  src/core/object/list.c
+  src/core/object/map.c
+  src/core/object/string.c
+  src/core/object/iterator.c
+  src/core/object/record.c
 
-  src/log.c
-  src/util.c
-  src/url.c
-  src/error.c
-  src/buffer.c
-  src/parser.c
-  src/scanner.c
-  src/types.c
+  src/core/log.c
+  src/core/util.c
+  src/core/error.c
+  src/core/buffer.c
+  src/core/types.c
 
-  src/framing/framing.c
+  src/core/framing.c
 
-  src/codec/codec.c
-  src/codec/decoder.c
-  src/codec/encoder.c
+  src/core/codec.c
+  src/core/decoder.c
+  src/core/encoder.c
 
-  src/dispatcher/dispatcher.c
-  src/engine/connection_engine.c
-  src/engine/engine.c
-  src/events/event.c
-  src/transport/autodetect.c
-  src/transport/transport.c
-  src/message/message.c
+  src/core/dispatcher.c
+  src/core/connection_engine.c
+  src/core/engine.c
+  src/core/event.c
+  src/core/autodetect.c
+  src/core/transport.c
+  src/core/message.c
+  )
+
+set (qpid-proton-include-generated
+  ${CMAKE_CURRENT_BINARY_DIR}/src/encodings.h
+  ${CMAKE_CURRENT_BINARY_DIR}/src/protocol.h
+  )
+
+set (qpid-proton-extra
+  src/extra/parser.c
+  src/extra/scanner.c
+  src/extra/url.c
 
   src/reactor/reactor.c
   src/reactor/handler.c
   src/reactor/connection.c
   src/reactor/acceptor.c
+  src/reactor/selectable.c
   src/reactor/timer.c
 
   src/handlers/handshaker.c
@@ -356,12 +369,6 @@
   src/messenger/subscription.c
   src/messenger/store.c
   src/messenger/transform.c
-  src/selectable.c
-  )
-
-set (qpid-proton-extra-deps
-  ${CMAKE_CURRENT_BINARY_DIR}/src/encodings.h
-  ${CMAKE_CURRENT_BINARY_DIR}/src/protocol.h
   )
 
 set (qpid-proton-include
@@ -374,39 +381,42 @@
   include/proton/engine.h
   include/proton/error.h
   include/proton/event.h
-  include/proton/handlers.h
   include/proton/import_export.h
-  include/proton/io.h
   include/proton/link.h
   include/proton/log.h
   include/proton/message.h
-  include/proton/messenger.h
   include/proton/object.h
-  include/proton/parser.h
-  include/proton/reactor.h
   include/proton/sasl.h
-  include/proton/scanner.h
-  include/proton/selectable.h
-  include/proton/selector.h
   include/proton/session.h
   include/proton/ssl.h
   include/proton/terminus.h
   include/proton/transport.h
   include/proton/type_compat.h
   include/proton/types.h
+)
+
+set (qpid-proton-include-extra
+  include/proton/handlers.h
+  include/proton/messenger.h
+  include/proton/parser.h
+  include/proton/reactor.h
+  include/proton/selectable.h
   include/proton/url.h
 )
 
-source_group("API Header Files" FILES ${qpid-proton-include})
+source_group("API Header Files" FILES ${qpid-proton-include} ${qpid-proton-include-extra})
 
 set_source_files_properties (
   ${qpid-proton-core}
+  ${qpid-proton-layers}
+  ${qpid-proton-extra}
   PROPERTIES
   COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS} ${LTO}"
   )
 
 set_source_files_properties (
   ${qpid-proton-platform}
+  ${qpid-proton-platform-io}
   PROPERTIES
   COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_PLATFORM_FLAGS} ${LTO}"
   COMPILE_DEFINITIONS "${PLATFORM_DEFINITIONS}"
@@ -414,18 +424,47 @@
 
 if (BUILD_WITH_CXX)
   set_source_files_properties (
-    ${qpid-proton-core} ${qpid-proton-platform}
+    ${qpid-proton-core}
+    ${qpid-proton-layers}
+    ${qpid-proton-extra}
+    ${qpid-proton-platform}
+    ${qpid-proton-platform-io}
     PROPERTIES LANGUAGE CXX
     )
 endif (BUILD_WITH_CXX)
 
 add_library (
-  qpid-proton SHARED
-
+  qpid-proton-core SHARED
   ${qpid-proton-core}
+  ${qpid-proton-layers}
   ${qpid-proton-platform}
   ${qpid-proton-include}
-  ${qpid-proton-extra-deps}
+  ${qpid-proton-include-generated}
+  )
+
+target_link_libraries (qpid-proton-core ${UUID_LIB} ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS})
+
+set_target_properties (
+  qpid-proton-core
+  PROPERTIES
+  VERSION   "${PN_LIB_SOMAJOR}.${PN_LIB_SOMINOR}"
+  SOVERSION "${PN_LIB_SOMAJOR}"
+  LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}"
+  )
+
+add_library(
+  qpid-proton SHARED
+  # Proton Core
+  ${qpid-proton-core}
+  ${qpid-proton-layers}
+  ${qpid-proton-platform}
+  ${qpid-proton-include}
+  ${qpid-proton-include-generated}
+
+  # Proton Reactor/Messenger
+  ${qpid-proton-extra}
+  ${qpid-proton-platform-io}
+  ${qpid-proton-include-extra}
   )
 
 target_link_libraries (qpid-proton ${UUID_LIB} ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS})
@@ -471,13 +510,24 @@
 install (FILES
   ${CMAKE_CURRENT_BINARY_DIR}/libqpid-proton.pc
   DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+configure_file(
+  ${CMAKE_CURRENT_SOURCE_DIR}/src/libqpid-proton-core.pc.in
+  ${CMAKE_CURRENT_BINARY_DIR}/libqpid-proton-core.pc @ONLY)
+install (FILES
+  ${CMAKE_CURRENT_BINARY_DIR}/libqpid-proton-core.pc
+  DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
 
 if (DEFINED CMAKE_IMPORT_LIBRARY_PREFIX)
 set(PROTONLIB ${CMAKE_IMPORT_LIBRARY_PREFIX}qpid-proton${CMAKE_IMPORT_LIBRARY_SUFFIX})
 set(PROTONLIBDEBUG ${CMAKE_IMPORT_LIBRARY_PREFIX}qpid-proton${CMAKE_DEBUG_POSTFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX})
+set(PROTONCORELIB ${CMAKE_IMPORT_LIBRARY_PREFIX}qpid-proton-core${CMAKE_IMPORT_LIBRARY_SUFFIX})
+set(PROTONCORELIBDEBUG ${CMAKE_IMPORT_LIBRARY_PREFIX}qpid-proton-core${CMAKE_DEBUG_POSTFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX})
 else ()
 set(PROTONLIB ${CMAKE_SHARED_LIBRARY_PREFIX}qpid-proton${CMAKE_SHARED_LIBRARY_SUFFIX})
 set(PROTONLIBDEBUG ${CMAKE_SHARED_LIBRARY_PREFIX}qpid-proton${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
+set(PROTONCORELIB ${CMAKE_SHARED_LIBRARY_PREFIX}qpid-proton-core${CMAKE_SHARED_LIBRARY_SUFFIX})
+set(PROTONCORELIBDEBUG ${CMAKE_SHARED_LIBRARY_PREFIX}qpid-proton-core${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
 endif ()
 
 include(WriteBasicConfigVersionFile)
diff --git a/proton-c/bindings/python/proton/reactor.py b/proton-c/bindings/python/proton/reactor.py
index ee9cfde..1a85bd3 100644
--- a/proton-c/bindings/python/proton/reactor.py
+++ b/proton-c/bindings/python/proton/reactor.py
@@ -138,7 +138,7 @@
 
     def wakeup(self):
         n = pn_reactor_wakeup(self._impl)
-        if n: raise IOError(pn_error_text(pn_io_error(pn_reactor_io(self._impl))))
+        if n: raise IOError(pn_error_text(pn_reactor_error(self._impl)))
 
     def start(self):
         pn_reactor_start(self._impl)
@@ -176,7 +176,7 @@
         if aimpl:
             return Acceptor(aimpl)
         else:
-            raise IOError("%s (%s:%s)" % (pn_error_text(pn_io_error(pn_reactor_io(self._impl))), host, port))
+            raise IOError("%s (%s:%s)" % pn_error_text(pn_reactor_error(self._impl)), host, port)
 
     def connection(self, handler=None):
         """Deprecated: use connection_to_host() instead
diff --git a/proton-c/bindings/python/setup.py b/proton-c/bindings/python/setup.py
index 1a74f0f..3606bed 100755
--- a/proton-c/bindings/python/setup.py
+++ b/proton-c/bindings/python/setup.py
@@ -194,8 +194,7 @@
         # Generate `encodings.h` by calling the python
         # script found in the source dir.
         with open(os.path.join(build_include, 'encodings.h'), 'wb') as header:
-            subprocess.Popen([sys.executable,
-                              os.path.join(proton_src, 'codec', 'encodings.h.py')],
+            subprocess.Popen([sys.executable, os.path.join(proton_src, 'encodings.h.py')],
                               env=proton_envs, stdout=header)
 
         # Create a custom, temporary, version.h file mapping the
@@ -219,10 +218,9 @@
         # we don't need.
 
         sources = []
-        for subdir in ['object', 'framing', 'codec', 'dispatcher',
-                       'engine', 'events', 'transport',
-                       'message', 'reactor', 'messenger',
-                       'handlers', 'posix']:
+        for subdir in ['core', 'core/object', 'compiler',
+                       'extra', 'message', 'reactor', 'messenger', 'handlers',
+                       'platform', 'reactor/io/posix']:
 
             sources.extend(glob.glob(os.path.join(proton_src, subdir, '*.c')))
 
diff --git a/proton-c/bindings/ruby/lib/reactor/reactor.rb b/proton-c/bindings/ruby/lib/reactor/reactor.rb
index 1cf4f6c..a0ff7e0 100644
--- a/proton-c/bindings/ruby/lib/reactor/reactor.rb
+++ b/proton-c/bindings/ruby/lib/reactor/reactor.rb
@@ -128,8 +128,7 @@
     def wakeup
       n = Cproton.pn_reactor_wakeup(@impl)
       unless n.zero?
-        io = Cproton.pn_reactor_io(@impl)
-        raise IOError.new(Cproton.pn_io_error(io))
+        raise IOError.new(Cproton.pn_reactor_error(@impl))
       end
     end
 
@@ -159,8 +158,7 @@
       if !aimpl.nil?
         return Acceptor.new(aimpl)
       else
-        io = Cproton.pn_reactor_io(@impl)
-        io_error = Cproton.pn_io_error(io)
+        io_error = Cproton.pn_reactor_error(@impl)
         error_text = Cproton.pn_error_text(io_error)
         text = "(#{Cproton.pn_error_text(io_error)} (#{host}:#{port}))"
         raise IOError.new(text)
diff --git a/proton-c/include/proton/cproton.i b/proton-c/include/proton/cproton.i
index 6129037..ffcf830 100644
--- a/proton-c/include/proton/cproton.i
+++ b/proton-c/include/proton/cproton.i
@@ -1014,8 +1014,6 @@
 
 %include "proton/messenger.h"
 
-%include "proton/io.h"
-
 %include "proton/selectable.h"
 
 %include "proton/ssl.h"
diff --git a/proton-c/include/proton/event.h b/proton-c/include/proton/event.h
index 16d2bda..d10927b 100644
--- a/proton-c/include/proton/event.h
+++ b/proton-c/include/proton/event.h
@@ -415,11 +415,6 @@
 PN_EXTERN void *pn_event_context(pn_event_t *event);
 
 /**
- * Get the root handler the current event was dispatched to.
- */
-PN_EXTERN pn_handler_t *pn_event_root(pn_event_t *event);
-
-/**
  * Get the connection associated with an event.
  *
  * @param[in] event an event object
diff --git a/proton-c/include/proton/handlers.h b/proton-c/include/proton/handlers.h
index f61e04c..a8a6f77 100644
--- a/proton-c/include/proton/handlers.h
+++ b/proton-c/include/proton/handlers.h
@@ -43,9 +43,9 @@
 typedef pn_handler_t pn_iohandler_t;
 typedef pn_handler_t pn_flowcontroller_t;
 
-PN_EXTERN pn_handshaker_t *pn_handshaker(void);
-PN_EXTERN pn_iohandler_t *pn_iohandler(void);
-PN_EXTERN pn_flowcontroller_t *pn_flowcontroller(int window);
+PNX_EXTERN pn_handshaker_t *pn_handshaker(void);
+PNX_EXTERN pn_iohandler_t *pn_iohandler(void);
+PNX_EXTERN pn_flowcontroller_t *pn_flowcontroller(int window);
 
 /** @}
  */
diff --git a/proton-c/include/proton/import_export.h b/proton-c/include/proton/import_export.h
index 4534d68..0010126 100644
--- a/proton-c/include/proton/import_export.h
+++ b/proton-c/include/proton/import_export.h
@@ -46,12 +46,18 @@
 
 
 // For core proton library symbols
-
-#ifdef qpid_proton_EXPORTS
+#if defined(qpid_proton_core_EXPORTS) || defined(qpid_proton_EXPORTS)
 #  define PN_EXTERN PN_EXPORT
 #else
 #  define PN_EXTERN PN_IMPORT
 #endif
 
+// For extra proton symbols
+#if defined(qpid_proton_EXPORTS)
+#  define PNX_EXTERN PN_EXPORT
+#else
+#  define PNX_EXTERN PN_IMPORT
+#endif
+
 
 #endif /* import_export.h */
diff --git a/proton-c/include/proton/io.h b/proton-c/include/proton/io.h
deleted file mode 100644
index 19dfe53..0000000
--- a/proton-c/include/proton/io.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef PROTON_IO_H
-#define PROTON_IO_H 1
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <proton/import_export.h>
-#include <proton/error.h>
-#include <proton/type_compat.h>
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * A ::pn_socket_t provides an abstract handle to an IO stream.  The
- * pipe version is uni-directional.  The network socket version is
- * bi-directional.  Both are non-blocking.
- *
- * pn_socket_t handles from ::pn_pipe() may only be used with
- * ::pn_read(), ::pn_write(), ::pn_close() and pn_selector_select().
- *
- * pn_socket_t handles from ::pn_listen(), ::pn_accept() and
- * ::pn_connect() must perform further IO using Proton functions.
- * Mixing Proton io.h functions with native IO functions on the same
- * handles will result in undefined behavior.
- *
- * pn_socket_t handles may only be used with a single pn_io_t during
- * their lifetime.
- */
-#if defined(_WIN32) && ! defined(__CYGWIN__)
-#ifdef _WIN64
-typedef unsigned __int64 pn_socket_t;
-#else
-typedef unsigned int pn_socket_t;
-#endif
-#define PN_INVALID_SOCKET (pn_socket_t)(~0)
-#else
-typedef int pn_socket_t;
-#define PN_INVALID_SOCKET (-1)
-#endif
-
-/**
- * A ::pn_io_t manages IO for a group of pn_socket_t handles.  A
- * pn_io_t object may have zero or one pn_selector_t selectors
- * associated with it (see ::pn_io_selector()).  If one is associated,
- * all the pn_socket_t handles managed by a pn_io_t must use that
- * pn_selector_t instance.
- *
- * The pn_io_t interface is single-threaded. All methods are intended
- * to be used by one thread at a time, except that multiple threads
- * may use:
- *
- *   ::pn_write()
- *   ::pn_send()
- *   ::pn_recv()
- *   ::pn_close()
- *   ::pn_selector_select()
- *
- * provided at most one thread is calling ::pn_selector_select() and
- * the other threads are operating on separate pn_socket_t handles.
- */
-typedef struct pn_io_t pn_io_t;
-
-/**
- * A ::pn_selector_t provides a selection mechanism that allows
- * efficient monitoring of a large number of Proton connections and
- * listeners.
- *
- * External (non-Proton) sockets may also be monitored, either solely
- * for event notification (read, write, and timer) or event
- * notification and use with pn_io_t interfaces.
- */
-typedef struct pn_selector_t pn_selector_t;
-
-PN_EXTERN pn_io_t *pn_io(void);
-PN_EXTERN void pn_io_free(pn_io_t *io);
-PN_EXTERN pn_error_t *pn_io_error(pn_io_t *io);
-PN_EXTERN pn_socket_t pn_connect(pn_io_t *io, const char *host, const char *port);
-PN_EXTERN pn_socket_t pn_listen(pn_io_t *io, const char *host, const char *port);
-PN_EXTERN pn_socket_t pn_accept(pn_io_t *io, pn_socket_t socket, char *name, size_t size);
-PN_EXTERN void pn_close(pn_io_t *io, pn_socket_t socket);
-PN_EXTERN ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size);
-PN_EXTERN ssize_t pn_recv(pn_io_t *io, pn_socket_t socket, void *buf, size_t size);
-PN_EXTERN int pn_pipe(pn_io_t *io, pn_socket_t *dest);
-PN_EXTERN ssize_t pn_read(pn_io_t *io, pn_socket_t socket, void *buf, size_t size);
-PN_EXTERN ssize_t pn_write(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size);
-PN_EXTERN bool pn_wouldblock(pn_io_t *io);
-PN_EXTERN pn_selector_t *pn_io_selector(pn_io_t *io);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* io.h */
diff --git a/proton-c/include/proton/messenger.h b/proton-c/include/proton/messenger.h
index 6d0f58b..8cba51d 100644
--- a/proton-c/include/proton/messenger.h
+++ b/proton-c/include/proton/messenger.h
@@ -195,7 +195,7 @@
  *
  * @return pointer to a new ::pn_messenger_t
  */
-PN_EXTERN pn_messenger_t *pn_messenger(const char *name);
+PNX_EXTERN pn_messenger_t *pn_messenger(const char *name);
 
 /**
  * Get the name of a messenger.
@@ -203,7 +203,7 @@
  * @param[in] messenger a messenger object
  * @return the name of the messenger
  */
-PN_EXTERN const char *pn_messenger_name(pn_messenger_t *messenger);
+PNX_EXTERN const char *pn_messenger_name(pn_messenger_t *messenger);
 
 /**
  * Sets the path that will be used to get the certificate that will be
@@ -214,7 +214,7 @@
  * @param[in] certificate a path to a certificate file
  * @return an error code of zero if there is no error
  */
-PN_EXTERN int pn_messenger_set_certificate(pn_messenger_t *messenger, const char *certificate);
+PNX_EXTERN int pn_messenger_set_certificate(pn_messenger_t *messenger, const char *certificate);
 
 /**
  * Get the certificate path. This value may be set by
@@ -223,7 +223,7 @@
  * @param[in] messenger the messenger
  * @return the certificate file path
  */
-PN_EXTERN const char *pn_messenger_get_certificate(pn_messenger_t *messenger);
+PNX_EXTERN const char *pn_messenger_get_certificate(pn_messenger_t *messenger);
 
 /**
  * Set path to the private key that was used to sign the certificate.
@@ -233,7 +233,7 @@
  * @param[in] private_key a path to a private key file
  * @return an error code of zero if there is no error
  */
-PN_EXTERN int pn_messenger_set_private_key(pn_messenger_t *messenger, const char *private_key);
+PNX_EXTERN int pn_messenger_set_private_key(pn_messenger_t *messenger, const char *private_key);
 
 /**
  * Gets the private key file for a messenger.
@@ -241,7 +241,7 @@
  * @param[in] messenger a messenger object
  * @return the messenger's private key file path
  */
-PN_EXTERN const char *pn_messenger_get_private_key(pn_messenger_t *messenger);
+PNX_EXTERN const char *pn_messenger_get_private_key(pn_messenger_t *messenger);
 
 /**
  * Sets the private key password for a messenger.
@@ -251,7 +251,7 @@
  *
  * @return an error code of zero if there is no error
  */
-PN_EXTERN int pn_messenger_set_password(pn_messenger_t *messenger, const char *password);
+PNX_EXTERN int pn_messenger_set_password(pn_messenger_t *messenger, const char *password);
 
 /**
  * Gets the private key file password for a messenger.
@@ -259,7 +259,7 @@
  * @param[in] messenger a messenger object
  * @return password for the private key file
  */
-PN_EXTERN const char *pn_messenger_get_password(pn_messenger_t *messenger);
+PNX_EXTERN const char *pn_messenger_get_password(pn_messenger_t *messenger);
 
 /**
  * Sets the trusted certificates database for a messenger.
@@ -272,7 +272,7 @@
  *
  * @return an error code of zero if there is no error
  */
-PN_EXTERN int pn_messenger_set_trusted_certificates(pn_messenger_t *messenger, const char *cert_db);
+PNX_EXTERN int pn_messenger_set_trusted_certificates(pn_messenger_t *messenger, const char *cert_db);
 
 /**
  * Gets the trusted certificates database for a messenger.
@@ -280,7 +280,7 @@
  * @param[in] messenger a messenger object
  * @return path to the trusted certificates database
  */
-PN_EXTERN const char *pn_messenger_get_trusted_certificates(pn_messenger_t *messenger);
+PNX_EXTERN const char *pn_messenger_get_trusted_certificates(pn_messenger_t *messenger);
 
 /**
  * Set the default timeout for a messenger.
@@ -294,7 +294,7 @@
  * @param[in] timeout a new timeout for the messenger, in milliseconds
  * @return an error code or zero if there is no error
  */
-PN_EXTERN int pn_messenger_set_timeout(pn_messenger_t *messenger, int timeout);
+PNX_EXTERN int pn_messenger_set_timeout(pn_messenger_t *messenger, int timeout);
 
 /**
  * Gets the timeout for a messenger object.
@@ -304,7 +304,7 @@
  * @param[in] messenger a messenger object
  * @return the timeout for the messenger, in milliseconds
  */
-PN_EXTERN int pn_messenger_get_timeout(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_get_timeout(pn_messenger_t *messenger);
 
 /**
  * Check if a messenger is in blocking mode.
@@ -312,7 +312,7 @@
  * @param[in] messenger a messenger object
  * @return true if blocking has been enabled, false otherwise
  */
-PN_EXTERN bool pn_messenger_is_blocking(pn_messenger_t *messenger);
+PNX_EXTERN bool pn_messenger_is_blocking(pn_messenger_t *messenger);
 
 /**
  * Enable or disable blocking behavior for a messenger during calls to
@@ -322,7 +322,7 @@
  * @param[in] blocking the value of the blocking flag
  * @return an error code or zero if there is no error
  */
-PN_EXTERN int pn_messenger_set_blocking(pn_messenger_t *messenger, bool blocking);
+PNX_EXTERN int pn_messenger_set_blocking(pn_messenger_t *messenger, bool blocking);
 
 /**
  * Check if a messenger is in passive mode.
@@ -336,7 +336,7 @@
  * @param[in] messenger a messenger object
  * @return true if the messenger is in passive mode, false otherwise
  */
-PN_EXTERN bool pn_messenger_is_passive(pn_messenger_t *messenger);
+PNX_EXTERN bool pn_messenger_is_passive(pn_messenger_t *messenger);
 
 /**
  * Set the passive mode for a messenger.
@@ -348,14 +348,14 @@
  * passive mode
  * @return an error code or zero on success
  */
-PN_EXTERN int pn_messenger_set_passive(pn_messenger_t *messenger, bool passive);
+PNX_EXTERN int pn_messenger_set_passive(pn_messenger_t *messenger, bool passive);
 
 /** Frees a Messenger.
  *
  * @param[in] messenger the messenger to free (or NULL), no longer
  *                      valid on return
  */
-PN_EXTERN void pn_messenger_free(pn_messenger_t *messenger);
+PNX_EXTERN void pn_messenger_free(pn_messenger_t *messenger);
 
 /**
  * Get the code for a messenger's most recent error.
@@ -370,7 +370,7 @@
  * @return an error code or zero if there is no error
  * @see error.h
  */
-PN_EXTERN int pn_messenger_errno(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_errno(pn_messenger_t *messenger);
 
 /**
  * Get a messenger's error object.
@@ -383,7 +383,7 @@
  * @return a pointer to the messenger's error descriptor
  * @see error.h
  */
-PN_EXTERN pn_error_t *pn_messenger_error(pn_messenger_t *messenger);
+PNX_EXTERN pn_error_t *pn_messenger_error(pn_messenger_t *messenger);
 
 /**
  * Get the size of a messenger's outgoing window.
@@ -400,7 +400,7 @@
  * @param[in] messenger a messenger object
  * @return the outgoing window for the messenger
  */
-PN_EXTERN int pn_messenger_get_outgoing_window(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_get_outgoing_window(pn_messenger_t *messenger);
 
 /**
  * Set the size of a messenger's outgoing window.
@@ -412,7 +412,7 @@
  * @return an error or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_set_outgoing_window(pn_messenger_t *messenger, int window);
+PNX_EXTERN int pn_messenger_set_outgoing_window(pn_messenger_t *messenger, int window);
 
 /**
  * Get the size of a messenger's incoming window.
@@ -432,7 +432,7 @@
  * @param[in] messenger a messenger object
  * @return the incoming window for the messenger
  */
-PN_EXTERN int pn_messenger_get_incoming_window(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_get_incoming_window(pn_messenger_t *messenger);
 
 /**
  * Set the size of a messenger's incoming window.
@@ -444,7 +444,7 @@
  * @return an error or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_set_incoming_window(pn_messenger_t *messenger,
+PNX_EXTERN int pn_messenger_set_incoming_window(pn_messenger_t *messenger,
                                                int window);
 
 /**
@@ -455,7 +455,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_start(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_start(pn_messenger_t *messenger);
 
 /**
  * Stops a messenger.
@@ -471,7 +471,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_stop(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_stop(pn_messenger_t *messenger);
 
 /**
  * Returns true if a messenger is in the stopped state. This function
@@ -480,7 +480,7 @@
  * @param[in] messenger the messenger to stop
  *
  */
-PN_EXTERN bool pn_messenger_stopped(pn_messenger_t *messenger);
+PNX_EXTERN bool pn_messenger_stopped(pn_messenger_t *messenger);
 
 /**
  * Subscribes a messenger to messages from the specified source.
@@ -489,7 +489,7 @@
  * @param[in] source
  * @return a subscription
  */
-PN_EXTERN pn_subscription_t *pn_messenger_subscribe(pn_messenger_t *messenger, const char *source);
+PNX_EXTERN pn_subscription_t *pn_messenger_subscribe(pn_messenger_t *messenger, const char *source);
 
 /**
  * Subscribes a messenger to messages from the specified source with the given
@@ -501,7 +501,7 @@
  *            link is closed.
  * @return a subscription
  */
-PN_EXTERN pn_subscription_t *
+PNX_EXTERN pn_subscription_t *
 pn_messenger_subscribe_ttl(pn_messenger_t *messenger, const char *source,
                            pn_seconds_t timeout);
 
@@ -514,7 +514,7 @@
  *            receiver
  * @return a link, or NULL if no link matches the address / sender parameters
  */
-PN_EXTERN pn_link_t *pn_messenger_get_link(pn_messenger_t *messenger,
+PNX_EXTERN pn_link_t *pn_messenger_get_link(pn_messenger_t *messenger,
                                            const char *address, bool sender);
 
 /**
@@ -525,7 +525,7 @@
  * @param[in] sub a subscription object
  * @return the subscription's application context
  */
-PN_EXTERN void *pn_subscription_get_context(pn_subscription_t *sub);
+PNX_EXTERN void *pn_subscription_get_context(pn_subscription_t *sub);
 
 /**
  * Set an application context for a subscription.
@@ -533,7 +533,7 @@
  * @param[in] sub a subscription object
  * @param[in] context the application context for the subscription
  */
-PN_EXTERN void pn_subscription_set_context(pn_subscription_t *sub, void *context);
+PNX_EXTERN void pn_subscription_set_context(pn_subscription_t *sub, void *context);
 
 /**
  * Get the source address of a subscription.
@@ -541,7 +541,7 @@
  * @param[in] sub a subscription object
  * @return the subscription's source address
  */
-PN_EXTERN const char *pn_subscription_address(pn_subscription_t *sub);
+PNX_EXTERN const char *pn_subscription_address(pn_subscription_t *sub);
 
 /**
  * Puts a message onto the messenger's outgoing queue. The message may
@@ -553,7 +553,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_put(pn_messenger_t *messenger, pn_message_t *msg);
+PNX_EXTERN int pn_messenger_put(pn_messenger_t *messenger, pn_message_t *msg);
 
 /**
  * Track the status of a delivery.
@@ -566,7 +566,7 @@
  * @param[in] tracker the tracker identifying the delivery
  * @return a status code for the delivery
  */
-PN_EXTERN pn_status_t pn_messenger_status(pn_messenger_t *messenger, pn_tracker_t tracker);
+PNX_EXTERN pn_status_t pn_messenger_status(pn_messenger_t *messenger, pn_tracker_t tracker);
 
 /**
  * Get delivery information about a delivery.
@@ -579,7 +579,7 @@
  * @param[in] tracker the tracker identifying the delivery
  * @return a pn_delivery_t representing the delivery.
  */
-PN_EXTERN pn_delivery_t *pn_messenger_delivery(pn_messenger_t *messenger,
+PNX_EXTERN pn_delivery_t *pn_messenger_delivery(pn_messenger_t *messenger,
                                                pn_tracker_t tracker);
 
 /**
@@ -594,7 +594,7 @@
  *
  * @return true if the delivery is still buffered
  */
-PN_EXTERN bool pn_messenger_buffered(pn_messenger_t *messenger, pn_tracker_t tracker);
+PNX_EXTERN bool pn_messenger_buffered(pn_messenger_t *messenger, pn_tracker_t tracker);
 
 /**
  * Frees a Messenger from tracking the status associated with a given
@@ -608,7 +608,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_settle(pn_messenger_t *messenger, pn_tracker_t tracker, int flags);
+PNX_EXTERN int pn_messenger_settle(pn_messenger_t *messenger, pn_tracker_t tracker, int flags);
 
 /**
  * Get a tracker for the outgoing message most recently given to
@@ -623,7 +623,7 @@
  * @return a pn_tracker_t or an undefined value if pn_messenger_get
  *         has never been called for the given messenger
  */
-PN_EXTERN pn_tracker_t pn_messenger_outgoing_tracker(pn_messenger_t *messenger);
+PNX_EXTERN pn_tracker_t pn_messenger_outgoing_tracker(pn_messenger_t *messenger);
 
 /**
  * Sends or receives any outstanding messages queued for a messenger.
@@ -635,7 +635,7 @@
  *
  * @return 0 if no work to do, < 0 if error, or 1 if work was done.
  */
-PN_EXTERN int pn_messenger_work(pn_messenger_t *messenger, int timeout);
+PNX_EXTERN int pn_messenger_work(pn_messenger_t *messenger, int timeout);
 
 /**
  * Interrupt a messenger object that may be blocking in another
@@ -648,7 +648,7 @@
  *
  * @param[in] messenger the Messenger to interrupt
  */
-PN_EXTERN int pn_messenger_interrupt(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_interrupt(pn_messenger_t *messenger);
 
 /**
  * Send messages from a messenger's outgoing queue.
@@ -682,7 +682,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_send(pn_messenger_t *messenger, int n);
+PNX_EXTERN int pn_messenger_send(pn_messenger_t *messenger, int n);
 
 /**
  * Retrieve messages into a messenger's incoming queue.
@@ -708,7 +708,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_recv(pn_messenger_t *messenger, int limit);
+PNX_EXTERN int pn_messenger_recv(pn_messenger_t *messenger, int limit);
 
 /**
  * Get the capacity of the incoming message queue of a messenger.
@@ -720,7 +720,7 @@
  *
  * @param[in] messenger the messenger
  */
-PN_EXTERN int pn_messenger_receiving(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_receiving(pn_messenger_t *messenger);
 
 /**
  * Get the next message from the head of a messenger's incoming queue.
@@ -736,7 +736,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_get(pn_messenger_t *messenger, pn_message_t *message);
+PNX_EXTERN int pn_messenger_get(pn_messenger_t *messenger, pn_message_t *message);
 
 /**
  * Get a tracker for the message most recently retrieved by
@@ -751,7 +751,7 @@
  * @return a pn_tracker_t or an undefined value if pn_messenger_get
  *         has never been called for the given messenger
  */
-PN_EXTERN pn_tracker_t pn_messenger_incoming_tracker(pn_messenger_t *messenger);
+PNX_EXTERN pn_tracker_t pn_messenger_incoming_tracker(pn_messenger_t *messenger);
 
 /**
  * Get the subscription of the message most recently retrieved by ::pn_messenger_get().
@@ -762,7 +762,7 @@
  * @param[in] messenger a messenger object
  * @return a pn_subscription_t or NULL
  */
-PN_EXTERN pn_subscription_t *pn_messenger_incoming_subscription(pn_messenger_t *messenger);
+PNX_EXTERN pn_subscription_t *pn_messenger_incoming_subscription(pn_messenger_t *messenger);
 
 /**
  * Indicates that an accept or reject should operate cumulatively.
@@ -790,7 +790,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_accept(pn_messenger_t *messenger, pn_tracker_t tracker, int flags);
+PNX_EXTERN int pn_messenger_accept(pn_messenger_t *messenger, pn_tracker_t tracker, int flags);
 
 /**
  * Signal unsuccessful processing of message(s).
@@ -813,7 +813,7 @@
  * @return an error code or zero on success
  * @see error.h
  */
-PN_EXTERN int pn_messenger_reject(pn_messenger_t *messenger, pn_tracker_t tracker, int flags);
+PNX_EXTERN int pn_messenger_reject(pn_messenger_t *messenger, pn_tracker_t tracker, int flags);
 
 /**
  * Get  link for the message referenced by the given tracker.
@@ -822,7 +822,7 @@
  * @param[in] tracker a tracker object
  * @return a pn_link_t or NULL if the link could not be determined.
  */
-PN_EXTERN pn_link_t *pn_messenger_tracker_link(pn_messenger_t *messenger,
+PNX_EXTERN pn_link_t *pn_messenger_tracker_link(pn_messenger_t *messenger,
                                                pn_tracker_t tracker);
 
 /**
@@ -832,7 +832,7 @@
  * @param[in] messenger a messenger object
  * @return the outgoing queue depth
  */
-PN_EXTERN int pn_messenger_outgoing(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_outgoing(pn_messenger_t *messenger);
 
 /**
  * Get the number of messages in the incoming message queue of a messenger.
@@ -840,7 +840,7 @@
  * @param[in] messenger a messenger object
  * @return the incoming queue depth
  */
-PN_EXTERN int pn_messenger_incoming(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_incoming(pn_messenger_t *messenger);
 
 //! Adds a routing rule to a Messenger's internal routing table.
 //!
@@ -904,7 +904,7 @@
 //!
 //! @return an error code or zero on success
 //! @see error.h
-PN_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const char *pattern,
+PNX_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const char *pattern,
                                  const char *address);
 
 /**
@@ -929,7 +929,7 @@
  * @param[in] address an address indicating outgoing address rewrite
  * @return an error code or zero on success
  */
-PN_EXTERN int pn_messenger_rewrite(pn_messenger_t *messenger, const char *pattern,
+PNX_EXTERN int pn_messenger_rewrite(pn_messenger_t *messenger, const char *pattern,
                                    const char *address);
 
 /**
@@ -960,7 +960,7 @@
  * @param[in] messenger a messenger object
  * @return the next selectable, or NULL if there are none left
  */
-PN_EXTERN pn_selectable_t *pn_messenger_selectable(pn_messenger_t *messenger);
+PNX_EXTERN pn_selectable_t *pn_messenger_selectable(pn_messenger_t *messenger);
 
 /**
  * Get the nearest deadline for selectables associated with a messenger.
@@ -968,7 +968,7 @@
  * @param[in] messenger a messenger object
  * @return the nearest deadline
  */
-PN_EXTERN pn_timestamp_t pn_messenger_deadline(pn_messenger_t *messenger);
+PNX_EXTERN pn_timestamp_t pn_messenger_deadline(pn_messenger_t *messenger);
 
 /**
  * @}
@@ -991,7 +991,7 @@
  *
  * @return an error code of zero if there is no error
  */
-PN_EXTERN int pn_messenger_set_flags(pn_messenger_t *messenger,
+PNX_EXTERN int pn_messenger_set_flags(pn_messenger_t *messenger,
                                      const int flags);
 
 /** Gets the flags for a Messenger.
@@ -999,7 +999,7 @@
  * @param[in] messenger the messenger
  * @return The flags set for the messenger
  */
-PN_EXTERN int pn_messenger_get_flags(pn_messenger_t *messenger);
+PNX_EXTERN int pn_messenger_get_flags(pn_messenger_t *messenger);
 
 /**
  * Set the local sender settle mode for the underlying link.
@@ -1007,7 +1007,7 @@
  * @param[in] messenger the messenger
  * @param[in] mode the sender settle mode
  */
-PN_EXTERN int pn_messenger_set_snd_settle_mode(pn_messenger_t *messenger,
+PNX_EXTERN int pn_messenger_set_snd_settle_mode(pn_messenger_t *messenger,
                                                const pn_snd_settle_mode_t mode);
 
 /**
@@ -1016,7 +1016,7 @@
  * @param[in] messenger the messenger
  * @param[in] mode the receiver settle mode
  */
-PN_EXTERN int pn_messenger_set_rcv_settle_mode(pn_messenger_t *messenger,
+PNX_EXTERN int pn_messenger_set_rcv_settle_mode(pn_messenger_t *messenger,
                                                const pn_rcv_settle_mode_t mode);
 
 /**
@@ -1025,7 +1025,7 @@
  * @param[in] messenger a messenger object
  * @param[in] tracer the tracer callback
  */
-PN_EXTERN void pn_messenger_set_tracer(pn_messenger_t *messenger,
+PNX_EXTERN void pn_messenger_set_tracer(pn_messenger_t *messenger,
                                        pn_tracer_t tracer);
 
 /**
@@ -1035,7 +1035,7 @@
  * @param[in] address of remote service whose idle timeout is required
  * @return the timeout in milliseconds or -1 if an error occurs
  */
-PN_EXTERN pn_millis_t
+PNX_EXTERN pn_millis_t
     pn_messenger_get_remote_idle_timeout(pn_messenger_t *messenger,
                                          const char *address);
 
@@ -1048,7 +1048,7 @@
  *             enum for valid values)
  * @return 0 if successful or -1 if an error occurs
  */
-PN_EXTERN int
+PNX_EXTERN int
 pn_messenger_set_ssl_peer_authentication_mode(pn_messenger_t *messenger,
                                               const pn_ssl_verify_mode_t mode);
 
diff --git a/proton-c/include/proton/reactor.h b/proton-c/include/proton/reactor.h
index 78fe57b..bfd6de5 100644
--- a/proton-c/include/proton/reactor.h
+++ b/proton-c/include/proton/reactor.h
@@ -1,3 +1,4 @@
+
 #ifndef PROTON_REACTOR_H
 #define PROTON_REACTOR_H 1
 
@@ -24,6 +25,7 @@
 
 #include <proton/import_export.h>
 #include <proton/type_compat.h>
+#include <proton/error.h>
 #include <proton/event.h>
 #include <proton/selectable.h>
 #include <proton/ssl.h>
@@ -46,35 +48,34 @@
 typedef struct pn_timer_t pn_timer_t;
 typedef struct pn_task_t pn_task_t;
 
-PN_EXTERN pn_handler_t *pn_handler(void (*dispatch)(pn_handler_t *, pn_event_t *, pn_event_type_t));
-PN_EXTERN pn_handler_t *pn_handler_new(void (*dispatch)(pn_handler_t *, pn_event_t *, pn_event_type_t), size_t size,
+PNX_EXTERN pn_handler_t *pn_handler(void (*dispatch)(pn_handler_t *, pn_event_t *, pn_event_type_t));
+PNX_EXTERN pn_handler_t *pn_handler_new(void (*dispatch)(pn_handler_t *, pn_event_t *, pn_event_type_t), size_t size,
                                        void (*finalize)(pn_handler_t *));
-PN_EXTERN void pn_handler_free(pn_handler_t *handler);
-PN_EXTERN void *pn_handler_mem(pn_handler_t *handler);
-PN_EXTERN void pn_handler_add(pn_handler_t *handler, pn_handler_t *child);
-PN_EXTERN void pn_handler_clear(pn_handler_t *handler);
-PN_EXTERN void pn_handler_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type);
+PNX_EXTERN void pn_handler_free(pn_handler_t *handler);
+PNX_EXTERN void *pn_handler_mem(pn_handler_t *handler);
+PNX_EXTERN void pn_handler_add(pn_handler_t *handler, pn_handler_t *child);
+PNX_EXTERN void pn_handler_clear(pn_handler_t *handler);
+PNX_EXTERN void pn_handler_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type);
 
-PN_EXTERN pn_reactor_t *pn_reactor(void);
-PN_EXTERN pn_record_t *pn_reactor_attachments(pn_reactor_t *reactor);
-PN_EXTERN pn_millis_t pn_reactor_get_timeout(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_set_timeout(pn_reactor_t *reactor, pn_millis_t timeout);
-PN_EXTERN pn_timestamp_t pn_reactor_mark(pn_reactor_t *reactor);
-PN_EXTERN pn_timestamp_t pn_reactor_now(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_yield(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_free(pn_reactor_t *reactor);
-PN_EXTERN pn_collector_t *pn_reactor_collector(pn_reactor_t *reactor);
-PN_EXTERN pn_handler_t *pn_reactor_get_global_handler(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_set_global_handler(pn_reactor_t *reactor, pn_handler_t *handler);
-PN_EXTERN pn_handler_t *pn_reactor_get_handler(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_set_handler(pn_reactor_t *reactor, pn_handler_t *handler);
-PN_EXTERN pn_io_t *pn_reactor_io(pn_reactor_t *reactor);
-PN_EXTERN pn_list_t *pn_reactor_children(pn_reactor_t *reactor);
-PN_EXTERN pn_selectable_t *pn_reactor_selectable(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_update(pn_reactor_t *reactor, pn_selectable_t *selectable);
-PN_EXTERN pn_acceptor_t *pn_reactor_acceptor(pn_reactor_t *reactor, const char *host, const char *port,
+PNX_EXTERN pn_reactor_t *pn_reactor(void);
+PNX_EXTERN pn_record_t *pn_reactor_attachments(pn_reactor_t *reactor);
+PNX_EXTERN pn_millis_t pn_reactor_get_timeout(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_set_timeout(pn_reactor_t *reactor, pn_millis_t timeout);
+PNX_EXTERN pn_timestamp_t pn_reactor_mark(pn_reactor_t *reactor);
+PNX_EXTERN pn_timestamp_t pn_reactor_now(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_yield(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_free(pn_reactor_t *reactor);
+PNX_EXTERN pn_collector_t *pn_reactor_collector(pn_reactor_t *reactor);
+PNX_EXTERN pn_handler_t *pn_reactor_get_global_handler(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_set_global_handler(pn_reactor_t *reactor, pn_handler_t *handler);
+PNX_EXTERN pn_handler_t *pn_reactor_get_handler(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_set_handler(pn_reactor_t *reactor, pn_handler_t *handler);
+PNX_EXTERN pn_list_t *pn_reactor_children(pn_reactor_t *reactor);
+PNX_EXTERN pn_selectable_t *pn_reactor_selectable(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_update(pn_reactor_t *reactor, pn_selectable_t *selectable);
+PNX_EXTERN pn_acceptor_t *pn_reactor_acceptor(pn_reactor_t *reactor, const char *host, const char *port,
                                              pn_handler_t *handler);
-PN_EXTERN pn_error_t *pn_reactor_error(pn_reactor_t *reactor);
+PNX_EXTERN pn_error_t *pn_reactor_error(pn_reactor_t *reactor);
 
 /**
  * Create an outgoing connection that will be managed by the reactor.
@@ -89,7 +90,7 @@
  * this connection.
  * @return a connection object
  */
-PN_EXTERN pn_connection_t *pn_reactor_connection_to_host(pn_reactor_t *reactor,
+PNX_EXTERN pn_connection_t *pn_reactor_connection_to_host(pn_reactor_t *reactor,
                                                          const char *host,
                                                          const char *port,
                                                          pn_handler_t *handler);
@@ -108,7 +109,7 @@
  * @return a connection object
  * @deprecated Use ::pn_reactor_connection_to_host() instead.
  */
-PN_EXTERN pn_connection_t *pn_reactor_connection(pn_reactor_t *reactor,
+PNX_EXTERN pn_connection_t *pn_reactor_connection(pn_reactor_t *reactor,
                                                  pn_handler_t *handler);
 
 /**
@@ -122,7 +123,7 @@
  * @param[in] host the network address or DNS name of the host to connect to.
  * @param[in] port the network port to use. Optional - default is "5672"
  */
-PN_EXTERN void pn_reactor_set_connection_host(pn_reactor_t *reactor,
+PNX_EXTERN void pn_reactor_set_connection_host(pn_reactor_t *reactor,
                                               pn_connection_t *connection,
                                               const char *host,
                                               const char *port);
@@ -145,37 +146,42 @@
  * address available.  ::pn_url_parse() may be used to create a Proton pn_url_t
  * instance from the returned value.
  */
-PN_EXTERN const char *pn_reactor_get_connection_address(pn_reactor_t *reactor,
+PNX_EXTERN const char *pn_reactor_get_connection_address(pn_reactor_t *reactor,
                                                         pn_connection_t *connection);
 
-PN_EXTERN int pn_reactor_wakeup(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_start(pn_reactor_t *reactor);
-PN_EXTERN bool pn_reactor_quiesced(pn_reactor_t *reactor);
-PN_EXTERN bool pn_reactor_process(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_stop(pn_reactor_t *reactor);
-PN_EXTERN void pn_reactor_run(pn_reactor_t *reactor);
-PN_EXTERN pn_task_t *pn_reactor_schedule(pn_reactor_t *reactor, int delay, pn_handler_t *handler);
+PNX_EXTERN int pn_reactor_wakeup(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_start(pn_reactor_t *reactor);
+PNX_EXTERN bool pn_reactor_quiesced(pn_reactor_t *reactor);
+PNX_EXTERN bool pn_reactor_process(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_stop(pn_reactor_t *reactor);
+PNX_EXTERN void pn_reactor_run(pn_reactor_t *reactor);
+PNX_EXTERN pn_task_t *pn_reactor_schedule(pn_reactor_t *reactor, int delay, pn_handler_t *handler);
 
 
-PN_EXTERN void pn_acceptor_set_ssl_domain(pn_acceptor_t *acceptor, pn_ssl_domain_t *domain);
-PN_EXTERN void pn_acceptor_close(pn_acceptor_t *acceptor);
-PN_EXTERN pn_acceptor_t *pn_connection_acceptor(pn_connection_t *connection);
+PNX_EXTERN void pn_acceptor_set_ssl_domain(pn_acceptor_t *acceptor, pn_ssl_domain_t *domain);
+PNX_EXTERN void pn_acceptor_close(pn_acceptor_t *acceptor);
+PNX_EXTERN pn_acceptor_t *pn_connection_acceptor(pn_connection_t *connection);
 
-PN_EXTERN pn_timer_t *pn_timer(pn_collector_t *collector);
-PN_EXTERN pn_timestamp_t pn_timer_deadline(pn_timer_t *timer);
-PN_EXTERN void pn_timer_tick(pn_timer_t *timer, pn_timestamp_t now);
-PN_EXTERN pn_task_t *pn_timer_schedule(pn_timer_t *timer, pn_timestamp_t deadline);
-PN_EXTERN int pn_timer_tasks(pn_timer_t *timer);
+PNX_EXTERN pn_timer_t *pn_timer(pn_collector_t *collector);
+PNX_EXTERN pn_timestamp_t pn_timer_deadline(pn_timer_t *timer);
+PNX_EXTERN void pn_timer_tick(pn_timer_t *timer, pn_timestamp_t now);
+PNX_EXTERN pn_task_t *pn_timer_schedule(pn_timer_t *timer, pn_timestamp_t deadline);
+PNX_EXTERN int pn_timer_tasks(pn_timer_t *timer);
 
-PN_EXTERN pn_record_t *pn_task_attachments(pn_task_t *task);
-PN_EXTERN void pn_task_cancel(pn_task_t *task);
+PNX_EXTERN pn_record_t *pn_task_attachments(pn_task_t *task);
+PNX_EXTERN void pn_task_cancel(pn_task_t *task);
 
-PN_EXTERN pn_reactor_t *pn_class_reactor(const pn_class_t *clazz, void *object);
-PN_EXTERN pn_reactor_t *pn_object_reactor(void *object);
-PN_EXTERN pn_reactor_t *pn_event_reactor(pn_event_t *event);
+PNX_EXTERN pn_reactor_t *pn_class_reactor(const pn_class_t *clazz, void *object);
+PNX_EXTERN pn_reactor_t *pn_object_reactor(void *object);
+PNX_EXTERN pn_reactor_t *pn_event_reactor(pn_event_t *event);
 
-PN_EXTERN pn_handler_t *pn_record_get_handler(pn_record_t *record);
-PN_EXTERN void pn_record_set_handler(pn_record_t *record, pn_handler_t *handler);
+PNX_EXTERN pn_handler_t *pn_record_get_handler(pn_record_t *record);
+PNX_EXTERN void pn_record_set_handler(pn_record_t *record, pn_handler_t *handler);
+
+/**
+ * Get the root handler the current event was dispatched to.
+ */
+PNX_EXTERN pn_handler_t *pn_event_root(pn_event_t *event);
 
 /** @}
  */
diff --git a/proton-c/include/proton/selectable.h b/proton-c/include/proton/selectable.h
index 7b0fa02..fbf3823 100644
--- a/proton-c/include/proton/selectable.h
+++ b/proton-c/include/proton/selectable.h
@@ -25,7 +25,6 @@
 #include <proton/import_export.h>
 #include <proton/object.h>
 #include <proton/event.h>
-#include <proton/io.h>
 #include <proton/type_compat.h>
 
 #ifdef __cplusplus
@@ -48,6 +47,34 @@
 typedef pn_iterator_t pn_selectables_t;
 
 /**
+ * A ::pn_socket_t provides an abstract handle to an IO stream.  The
+ * pipe version is uni-directional.  The network socket version is
+ * bi-directional.  Both are non-blocking.
+ *
+ * pn_socket_t handles from ::pn_pipe() may only be used with
+ * ::pn_read(), ::pn_write(), ::pn_close() and pn_selector_select().
+ *
+ * pn_socket_t handles from ::pn_listen(), ::pn_accept() and
+ * ::pn_connect() must perform further IO using Proton functions.
+ * Mixing Proton io.h functions with native IO functions on the same
+ * handles will result in undefined behavior.
+ *
+ * pn_socket_t handles may only be used with a single pn_io_t during
+ * their lifetime.
+ */
+#if defined(_WIN32) && ! defined(__CYGWIN__)
+#ifdef _WIN64
+typedef unsigned __int64 pn_socket_t;
+#else
+typedef unsigned int pn_socket_t;
+#endif
+#define PN_INVALID_SOCKET (pn_socket_t)(~0)
+#else
+typedef int pn_socket_t;
+#define PN_INVALID_SOCKET (-1)
+#endif
+
+/**
  * A selectable object provides an interface that can be used to
  * incorporate proton's I/O into third party event loops.
  *
@@ -72,7 +99,7 @@
  *
  * @return a pointer to a new selectables iterator
  */
-PN_EXTERN pn_selectables_t *pn_selectables(void);
+PNX_EXTERN pn_selectables_t *pn_selectables(void);
 
 /**
  * Get the next selectable from an iterator.
@@ -80,25 +107,25 @@
  * @param[in] selectables a selectable iterator
  * @return the next selectable from the iterator
  */
-PN_EXTERN pn_selectable_t *pn_selectables_next(pn_selectables_t *selectables);
+PNX_EXTERN pn_selectable_t *pn_selectables_next(pn_selectables_t *selectables);
 
 /**
  * Free a selectables iterator.
  *
  * @param[in] selectables a selectables iterator (or NULL)
  */
-PN_EXTERN void pn_selectables_free(pn_selectables_t *selectables);
+PNX_EXTERN void pn_selectables_free(pn_selectables_t *selectables);
 
-PN_EXTERN pn_selectable_t *pn_selectable(void);
+PNX_EXTERN pn_selectable_t *pn_selectable(void);
 
-PN_EXTERN void pn_selectable_on_readable(pn_selectable_t *sel, void (*readable)(pn_selectable_t *));
-PN_EXTERN void pn_selectable_on_writable(pn_selectable_t *sel, void (*writable)(pn_selectable_t *));
-PN_EXTERN void pn_selectable_on_expired(pn_selectable_t *sel, void (*expired)(pn_selectable_t *));
-PN_EXTERN void pn_selectable_on_error(pn_selectable_t *sel, void (*error)(pn_selectable_t *));
-PN_EXTERN void pn_selectable_on_release(pn_selectable_t *sel, void (*release)(pn_selectable_t *));
-PN_EXTERN void pn_selectable_on_finalize(pn_selectable_t *sel, void (*finalize)(pn_selectable_t *));
+PNX_EXTERN void pn_selectable_on_readable(pn_selectable_t *sel, void (*readable)(pn_selectable_t *));
+PNX_EXTERN void pn_selectable_on_writable(pn_selectable_t *sel, void (*writable)(pn_selectable_t *));
+PNX_EXTERN void pn_selectable_on_expired(pn_selectable_t *sel, void (*expired)(pn_selectable_t *));
+PNX_EXTERN void pn_selectable_on_error(pn_selectable_t *sel, void (*error)(pn_selectable_t *));
+PNX_EXTERN void pn_selectable_on_release(pn_selectable_t *sel, void (*release)(pn_selectable_t *));
+PNX_EXTERN void pn_selectable_on_finalize(pn_selectable_t *sel, void (*finalize)(pn_selectable_t *));
 
-PN_EXTERN pn_record_t *pn_selectable_attachments(pn_selectable_t *sel);
+PNX_EXTERN pn_record_t *pn_selectable_attachments(pn_selectable_t *sel);
 
 /**
  * Get the file descriptor associated with a selectable.
@@ -106,7 +133,7 @@
  * @param[in] selectable a selectable object
  * @return the file descriptor associated with the selectable
  */
-PN_EXTERN pn_socket_t pn_selectable_get_fd(pn_selectable_t *selectable);
+PNX_EXTERN pn_socket_t pn_selectable_get_fd(pn_selectable_t *selectable);
 
 /**
  * Set the file descriptor associated with a selectable.
@@ -114,7 +141,7 @@
  * @param[in] selectable a selectable object
  * @param[in] fd the file descriptor
  */
-PN_EXTERN void pn_selectable_set_fd(pn_selectable_t *selectable, pn_socket_t fd);
+PNX_EXTERN void pn_selectable_set_fd(pn_selectable_t *selectable, pn_socket_t fd);
 
 /**
  * Check if a selectable is interested in readable events.
@@ -122,9 +149,9 @@
  * @param[in] selectable a selectable object
  * @return true iff the selectable is interested in read events
  */
-PN_EXTERN bool pn_selectable_is_reading(pn_selectable_t *selectable);
+PNX_EXTERN bool pn_selectable_is_reading(pn_selectable_t *selectable);
 
-PN_EXTERN void pn_selectable_set_reading(pn_selectable_t *sel, bool reading);
+PNX_EXTERN void pn_selectable_set_reading(pn_selectable_t *sel, bool reading);
 
 /**
  * Check if a selectable is interested in writable events.
@@ -132,9 +159,9 @@
  * @param[in] selectable a selectable object
  * @return true iff the selectable is interested in writable events
  */
-PN_EXTERN bool pn_selectable_is_writing(pn_selectable_t *selectable);
+PNX_EXTERN bool pn_selectable_is_writing(pn_selectable_t *selectable);
 
-  PN_EXTERN void pn_selectable_set_writing(pn_selectable_t *sel, bool writing);
+  PNX_EXTERN void pn_selectable_set_writing(pn_selectable_t *sel, bool writing);
 
 /**
  * Get the next deadline for a selectable.
@@ -146,37 +173,37 @@
  * @param[in] selectable a selectable object
  * @return the next deadline or zero
  */
-PN_EXTERN pn_timestamp_t pn_selectable_get_deadline(pn_selectable_t *selectable);
+PNX_EXTERN pn_timestamp_t pn_selectable_get_deadline(pn_selectable_t *selectable);
 
-PN_EXTERN void pn_selectable_set_deadline(pn_selectable_t *sel, pn_timestamp_t deadline);
+PNX_EXTERN void pn_selectable_set_deadline(pn_selectable_t *sel, pn_timestamp_t deadline);
 
 /**
  * Notify a selectable that the file descriptor is readable.
  *
  * @param[in] selectable a selectable object
  */
-PN_EXTERN void pn_selectable_readable(pn_selectable_t *selectable);
+PNX_EXTERN void pn_selectable_readable(pn_selectable_t *selectable);
 
 /**
  * Notify a selectable that the file descriptor is writable.
  *
  * @param[in] selectable a selectable object
  */
-PN_EXTERN void pn_selectable_writable(pn_selectable_t *selectable);
+PNX_EXTERN void pn_selectable_writable(pn_selectable_t *selectable);
 
 /**
  * Notify a selectable that there is an error on the file descriptor.
  *
  * @param[in] selectable a selectable object
  */
-PN_EXTERN void pn_selectable_error(pn_selectable_t *selectable);
+PNX_EXTERN void pn_selectable_error(pn_selectable_t *selectable);
 
 /**
  * Notify a selectable that its deadline has expired.
  *
  * @param[in] selectable a selectable object
  */
-PN_EXTERN void pn_selectable_expired(pn_selectable_t *selectable);
+PNX_EXTERN void pn_selectable_expired(pn_selectable_t *selectable);
 
 /**
  * Check if a selectable is registered.
@@ -188,7 +215,7 @@
  * @param[in] selectable
  * @return true if the selectable is registered
  */
-PN_EXTERN bool pn_selectable_is_registered(pn_selectable_t *selectable);
+PNX_EXTERN bool pn_selectable_is_registered(pn_selectable_t *selectable);
 
 /**
  * Set the registered flag for a selectable.
@@ -198,7 +225,7 @@
  * @param[in] selectable a selectable object
  * @param[in] registered the registered flag
  */
-PN_EXTERN void pn_selectable_set_registered(pn_selectable_t *selectable, bool registered);
+PNX_EXTERN void pn_selectable_set_registered(pn_selectable_t *selectable, bool registered);
 
 /**
  * Check if a selectable is in the terminal state.
@@ -212,23 +239,23 @@
  * @param[in] selectable a selectable object
  * @return true if the selectable is in the terminal state, false otherwise
  */
-PN_EXTERN bool pn_selectable_is_terminal(pn_selectable_t *selectable);
+PNX_EXTERN bool pn_selectable_is_terminal(pn_selectable_t *selectable);
 
 /**
  * Terminate a selectable.
  *
  * @param[in] selectable a selectable object
  */
-PN_EXTERN void pn_selectable_terminate(pn_selectable_t *selectable);
+PNX_EXTERN void pn_selectable_terminate(pn_selectable_t *selectable);
 
-PN_EXTERN void pn_selectable_release(pn_selectable_t *selectable);
+PNX_EXTERN void pn_selectable_release(pn_selectable_t *selectable);
 
 /**
  * Free a selectable object.
  *
  * @param[in] selectable a selectable object (or NULL)
  */
-PN_EXTERN void pn_selectable_free(pn_selectable_t *selectable);
+PNX_EXTERN void pn_selectable_free(pn_selectable_t *selectable);
 
 /**
  * Configure a selectable with a set of callbacks that emit readable,
@@ -237,7 +264,7 @@
  * @param[in] selectable a selectable objet
  * @param[in] collector a collector object
  */
-PN_EXTERN void pn_selectable_collect(pn_selectable_t *selectable, pn_collector_t *collector);
+PNX_EXTERN void pn_selectable_collect(pn_selectable_t *selectable, pn_collector_t *collector);
 
 /**
  * @}
diff --git a/proton-c/include/proton/selector.h b/proton-c/include/proton/selector.h
deleted file mode 100644
index c942393..0000000
--- a/proton-c/include/proton/selector.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef PROTON_SELECTOR_H
-#define PROTON_SELECTOR_H 1
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <proton/import_export.h>
-#include <proton/selectable.h>
-#include <proton/type_compat.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PN_READABLE (1)
-#define PN_WRITABLE (2)
-#define PN_EXPIRED (4)
-#define PN_ERROR (8)
-
-pn_selector_t *pni_selector(void);
-PN_EXTERN void pn_selector_free(pn_selector_t *selector);
-PN_EXTERN void pn_selector_add(pn_selector_t *selector, pn_selectable_t *selectable);
-PN_EXTERN void pn_selector_update(pn_selector_t *selector, pn_selectable_t *selectable);
-PN_EXTERN void pn_selector_remove(pn_selector_t *selector, pn_selectable_t *selectable);
-PN_EXTERN size_t pn_selector_size(pn_selector_t *selector);
-PN_EXTERN int pn_selector_select(pn_selector_t *select, int timeout);
-PN_EXTERN pn_selectable_t *pn_selector_next(pn_selector_t *select, int *events);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* selector.h */
diff --git a/proton-c/include/proton/types.h b/proton-c/include/proton/types.h
index 72db6f8..176af47 100644
--- a/proton-c/include/proton/types.h
+++ b/proton-c/include/proton/types.h
@@ -50,10 +50,6 @@
 
 typedef int64_t  pn_timestamp_t;
 
-/** Return a timestamp for the time now. */
-PN_EXTERN pn_timestamp_t pn_timestamp_now(void);
-
-
 typedef uint32_t pn_char_t;
 typedef uint32_t pn_decimal32_t;
 typedef uint64_t pn_decimal64_t;
diff --git a/proton-c/include/proton/url.h b/proton-c/include/proton/url.h
index 80634c1..2a68bc2 100644
--- a/proton-c/include/proton/url.h
+++ b/proton-c/include/proton/url.h
@@ -37,7 +37,7 @@
 typedef struct pn_url_t pn_url_t;
 
 /** Create an empty URL */
-PN_EXTERN pn_url_t *pn_url(void);
+PNX_EXTERN pn_url_t *pn_url(void);
 
 /** Parse a string URL as a pn_url_t.
  *
@@ -56,13 +56,13 @@
  *@param[in] url A URL string.
  *@return The parsed pn_url_t or NULL if url is not a valid URL string.
  */
-PN_EXTERN pn_url_t *pn_url_parse(const char *url);
+PNX_EXTERN pn_url_t *pn_url_parse(const char *url);
 
 /** Free a URL */
-PN_EXTERN void pn_url_free(pn_url_t *url);
+PNX_EXTERN void pn_url_free(pn_url_t *url);
 
 /** Clear the contents of the URL. */
-PN_EXTERN void pn_url_clear(pn_url_t *url);
+PNX_EXTERN void pn_url_clear(pn_url_t *url);
 
 /**
  * Return the string form of a URL.
@@ -70,7 +70,7 @@
  *  The returned string is owned by the pn_url_t and will become invalid if it
  *  is modified.
  */
-PN_EXTERN const char *pn_url_str(pn_url_t *url);
+PNX_EXTERN const char *pn_url_str(pn_url_t *url);
 
 /**
  *@name Getters for parts of the URL.
@@ -79,12 +79,12 @@
  *
  *@{
  */
-PN_EXTERN const char *pn_url_get_scheme(pn_url_t *url);
-PN_EXTERN const char *pn_url_get_username(pn_url_t *url);
-PN_EXTERN const char *pn_url_get_password(pn_url_t *url);
-PN_EXTERN const char *pn_url_get_host(pn_url_t *url);
-PN_EXTERN const char *pn_url_get_port(pn_url_t *url);
-PN_EXTERN const char *pn_url_get_path(pn_url_t *url);
+PNX_EXTERN const char *pn_url_get_scheme(pn_url_t *url);
+PNX_EXTERN const char *pn_url_get_username(pn_url_t *url);
+PNX_EXTERN const char *pn_url_get_password(pn_url_t *url);
+PNX_EXTERN const char *pn_url_get_host(pn_url_t *url);
+PNX_EXTERN const char *pn_url_get_port(pn_url_t *url);
+PNX_EXTERN const char *pn_url_get_path(pn_url_t *url);
 ///@}
 
 /**
@@ -94,12 +94,12 @@
  *
  *@{
  */
-PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
-PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username);
-PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password);
-PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
-PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
-PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
+PNX_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
+PNX_EXTERN void pn_url_set_username(pn_url_t *url, const char *username);
+PNX_EXTERN void pn_url_set_password(pn_url_t *url, const char *password);
+PNX_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
+PNX_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
+PNX_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
 ///@}
 
 ///@}
diff --git a/proton-c/src/ProtonConfig.cmake.in b/proton-c/src/ProtonConfig.cmake.in
index fce1a3a..5e50d7c 100644
--- a/proton-c/src/ProtonConfig.cmake.in
+++ b/proton-c/src/ProtonConfig.cmake.in
@@ -27,4 +27,7 @@
 set (Proton_INCLUDE_DIRS  @INCLUDEDIR@)
 set (Proton_LIBRARIES     optimized @LIBDIR@/@PROTONLIB@ debug @LIBDIR@/@PROTONLIBDEBUG@)
 
+set (ProtonCore_INCLUDE_DIRS  @INCLUDEDIR@)
+set (ProtonCore_LIBRARIES     optimized @LIBDIR@/@PROTONCORELIB@ debug @LIBDIR@/@PROTONCORELIBDEBUG@)
+
 set (Proton_FOUND True)
diff --git a/proton-c/src/compiler/msvc/snprintf.c b/proton-c/src/compiler/msvc/snprintf.c
new file mode 100644
index 0000000..f9c14eb
--- /dev/null
+++ b/proton-c/src/compiler/msvc/snprintf.c
@@ -0,0 +1,52 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "platform/platform.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+// [v]snprintf on Windows only matches C99 when no errors or overflow.
+int pni_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap) {
+  if (fmt == NULL)
+    return -1;
+  if ((buf == NULL) && (count > 0))
+    return -1;
+  if (count > 0) {
+    int n = vsnprintf_s(buf, count, _TRUNCATE, fmt, ap);
+    if (n >= 0)  // no overflow
+      return n;  // same as C99
+    buf[count-1] = '\0';
+  }
+  // separate call to get needed buffer size on overflow
+  int n = _vscprintf(fmt, ap);
+  if (n >= (int) count)
+    return n;
+  return -1;
+}
+
+int pni_snprintf(char *buf, size_t count, const char *fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  int n = pni_vsnprintf(buf, count, fmt, ap);
+  va_end(ap);
+  return n;
+}
diff --git a/proton-c/src/transport/autodetect.c b/proton-c/src/core/autodetect.c
similarity index 100%
rename from proton-c/src/transport/autodetect.c
rename to proton-c/src/core/autodetect.c
diff --git a/proton-c/src/transport/autodetect.h b/proton-c/src/core/autodetect.h
similarity index 100%
rename from proton-c/src/transport/autodetect.h
rename to proton-c/src/core/autodetect.h
diff --git a/proton-c/src/buffer.c b/proton-c/src/core/buffer.c
similarity index 100%
rename from proton-c/src/buffer.c
rename to proton-c/src/core/buffer.c
diff --git a/proton-c/src/buffer.h b/proton-c/src/core/buffer.h
similarity index 100%
rename from proton-c/src/buffer.h
rename to proton-c/src/core/buffer.h
diff --git a/proton-c/src/codec/codec.c b/proton-c/src/core/codec.c
similarity index 99%
rename from proton-c/src/codec/codec.c
rename to proton-c/src/core/codec.c
index 2a4532c..67769ad 100644
--- a/proton-c/src/codec/codec.c
+++ b/proton-c/src/core/codec.c
@@ -31,8 +31,7 @@
 #include "encodings.h"
 #define DEFINE_FIELDS
 #include "protocol.h"
-#include "platform.h"
-#include "platform_fmt.h"
+#include "platform/platform_fmt.h"
 #include "util.h"
 #include "decoder.h"
 #include "encoder.h"
diff --git a/proton-c/src/config.h b/proton-c/src/core/config.h
similarity index 100%
rename from proton-c/src/config.h
rename to proton-c/src/core/config.h
diff --git a/proton-c/src/engine/connection_engine.c b/proton-c/src/core/connection_engine.c
similarity index 100%
rename from proton-c/src/engine/connection_engine.c
rename to proton-c/src/core/connection_engine.c
diff --git a/proton-c/src/codec/data.h b/proton-c/src/core/data.h
similarity index 100%
rename from proton-c/src/codec/data.h
rename to proton-c/src/core/data.h
diff --git a/proton-c/src/codec/decoder.c b/proton-c/src/core/decoder.c
similarity index 100%
rename from proton-c/src/codec/decoder.c
rename to proton-c/src/core/decoder.c
diff --git a/proton-c/src/codec/decoder.h b/proton-c/src/core/decoder.h
similarity index 100%
rename from proton-c/src/codec/decoder.h
rename to proton-c/src/core/decoder.h
diff --git a/proton-c/src/dispatch_actions.h b/proton-c/src/core/dispatch_actions.h
similarity index 98%
rename from proton-c/src/dispatch_actions.h
rename to proton-c/src/core/dispatch_actions.h
index bae8438..ea2d8b2 100644
--- a/proton-c/src/dispatch_actions.h
+++ b/proton-c/src/core/dispatch_actions.h
@@ -22,7 +22,7 @@
  *
  */
 
-#include "dispatcher/dispatcher.h"
+#include "dispatcher.h"
 
 #define AMQP_FRAME_TYPE (0)
 #define SASL_FRAME_TYPE (1)
diff --git a/proton-c/src/dispatcher/dispatcher.c b/proton-c/src/core/dispatcher.c
similarity index 98%
rename from proton-c/src/dispatcher/dispatcher.c
rename to proton-c/src/core/dispatcher.c
index 0bd3f7b..36f8cc9 100644
--- a/proton-c/src/dispatcher/dispatcher.c
+++ b/proton-c/src/core/dispatcher.c
@@ -21,9 +21,9 @@
 
 #include "dispatcher.h"
 
-#include "framing/framing.h"
+#include "framing.h"
 #include "protocol.h"
-#include "engine/engine-internal.h"
+#include "engine-internal.h"
 
 #include "dispatch_actions.h"
 
diff --git a/proton-c/src/dispatcher/dispatcher.h b/proton-c/src/core/dispatcher.h
similarity index 100%
rename from proton-c/src/dispatcher/dispatcher.h
rename to proton-c/src/core/dispatcher.h
diff --git a/proton-c/src/codec/encoder.c b/proton-c/src/core/encoder.c
similarity index 100%
rename from proton-c/src/codec/encoder.c
rename to proton-c/src/core/encoder.c
diff --git a/proton-c/src/codec/encoder.h b/proton-c/src/core/encoder.h
similarity index 100%
rename from proton-c/src/codec/encoder.h
rename to proton-c/src/core/encoder.h
diff --git a/proton-c/src/engine/engine-internal.h b/proton-c/src/core/engine-internal.h
similarity index 99%
rename from proton-c/src/engine/engine-internal.h
rename to proton-c/src/core/engine-internal.h
index 761a840..fdaf272 100644
--- a/proton-c/src/engine/engine-internal.h
+++ b/proton-c/src/core/engine-internal.h
@@ -25,8 +25,9 @@
 #include <proton/object.h>
 #include <proton/engine.h>
 #include <proton/types.h>
+
 #include "buffer.h"
-#include "dispatcher/dispatcher.h"
+#include "dispatcher.h"
 #include "util.h"
 
 typedef enum pn_endpoint_type_t {CONNECTION, SESSION, SENDER, RECEIVER} pn_endpoint_type_t;
diff --git a/proton-c/src/engine/engine.c b/proton-c/src/core/engine.c
similarity index 99%
rename from proton-c/src/engine/engine.c
rename to proton-c/src/core/engine.c
index cb1f479..e238d5c 100644
--- a/proton-c/src/engine/engine.c
+++ b/proton-c/src/core/engine.c
@@ -28,9 +28,9 @@
 #include <stdarg.h>
 #include <stdio.h>
 
-#include "platform.h"
-#include "platform_fmt.h"
-#include "transport/transport.h"
+#include "platform/platform.h"
+#include "platform/platform_fmt.h"
+#include "transport.h"
 
 
 static void pni_session_bound(pn_session_t *ssn);
@@ -2102,7 +2102,7 @@
       return err;
 
   char text[1024];
-  size_t n = vsnprintf(text, 1024, fmt, ap);
+  size_t n = pni_vsnprintf(text, 1024, fmt, ap);
   if (n >= sizeof(text))
       text[sizeof(text)-1] = '\0';
   err = pn_condition_set_description(condition, text);
diff --git a/proton-c/src/error.c b/proton-c/src/core/error.c
similarity index 97%
rename from proton-c/src/error.c
rename to proton-c/src/core/error.c
index 9bef0fc..70d36fa 100644
--- a/proton-c/src/error.c
+++ b/proton-c/src/core/error.c
@@ -19,12 +19,13 @@
  *
  */
 
+#include "platform/platform.h"
+#include "util.h"
+
 #include <proton/error.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-#include "util.h"
-#include "platform.h"
 
 struct pn_error_t {
   char *text;
@@ -76,7 +77,7 @@
 {
   assert(error);
   char text[1024];
-  int n = vsnprintf(text, 1024, fmt, ap);
+  int n = pni_vsnprintf(text, 1024, fmt, ap);
   if (n >= 1024) {
     text[1023] = '\0';
   }
diff --git a/proton-c/src/events/event.c b/proton-c/src/core/event.c
similarity index 96%
rename from proton-c/src/events/event.c
rename to proton-c/src/core/event.c
index 5ad718e..c13f287 100644
--- a/proton-c/src/events/event.c
+++ b/proton-c/src/core/event.c
@@ -284,17 +284,6 @@
   return event->attachments;
 }
 
-pn_handler_t *pn_event_root(pn_event_t *event)
-{
-  assert(event);
-  pn_handler_t *h = pn_record_get_handler(event->attachments);
-  return h;
-}
-
-void pni_event_set_root(pn_event_t *event, pn_handler_t *handler) {
-  pn_record_set_handler(event->attachments, handler);
-}
-
 const char *pn_event_type_name(pn_event_type_t type)
 {
   switch (type) {
diff --git a/proton-c/src/framing/framing.c b/proton-c/src/core/framing.c
similarity index 100%
rename from proton-c/src/framing/framing.c
rename to proton-c/src/core/framing.c
diff --git a/proton-c/src/framing/framing.h b/proton-c/src/core/framing.h
similarity index 95%
rename from proton-c/src/framing/framing.h
rename to proton-c/src/core/framing.h
index 6033867..ecb88a4 100644
--- a/proton-c/src/framing/framing.h
+++ b/proton-c/src/core/framing.h
@@ -26,10 +26,6 @@
 #include <proton/type_compat.h>
 #include <proton/error.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define AMQP_HEADER_SIZE (8)
 #define AMQP_MIN_MAX_FRAME_SIZE ((uint32_t)512) // minimum allowable max-frame
 
@@ -45,8 +41,4 @@
 ssize_t pn_read_frame(pn_frame_t *frame, const char *bytes, size_t available, uint32_t max);
 size_t pn_write_frame(char *bytes, size_t size, pn_frame_t frame);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* framing.h */
diff --git a/proton-c/src/log.c b/proton-c/src/core/log.c
similarity index 98%
rename from proton-c/src/log.c
rename to proton-c/src/core/log.c
index b92a99a..ff96ff0 100644
--- a/proton-c/src/log.c
+++ b/proton-c/src/core/log.c
@@ -20,6 +20,7 @@
 #include <proton/log.h>
 #include <proton/object.h>
 #include <stdio.h>
+#include "log_private.h"
 #include "util.h"
 
 
diff --git a/proton-c/src/log_private.h b/proton-c/src/core/log_private.h
similarity index 100%
rename from proton-c/src/log_private.h
rename to proton-c/src/core/log_private.h
diff --git a/proton-c/src/message/message.c b/proton-c/src/core/message.c
similarity index 99%
rename from proton-c/src/message/message.c
rename to proton-c/src/core/message.c
index 15d9c6c..f2fb20e 100644
--- a/proton-c/src/message/message.c
+++ b/proton-c/src/core/message.c
@@ -19,6 +19,10 @@
  *
  */
 
+#include "platform/platform_fmt.h"
+#include "protocol.h"
+#include "util.h"
+
 #include <proton/message.h>
 #include <proton/object.h>
 #include <proton/codec.h>
@@ -28,9 +32,6 @@
 #include <string.h>
 #include <stdio.h>
 #include <assert.h>
-#include "protocol.h"
-#include "util.h"
-#include "platform_fmt.h"
 
 // message
 
diff --git a/proton-c/src/object/iterator.c b/proton-c/src/core/object/iterator.c
similarity index 100%
rename from proton-c/src/object/iterator.c
rename to proton-c/src/core/object/iterator.c
diff --git a/proton-c/src/object/list.c b/proton-c/src/core/object/list.c
similarity index 100%
rename from proton-c/src/object/list.c
rename to proton-c/src/core/object/list.c
diff --git a/proton-c/src/object/map.c b/proton-c/src/core/object/map.c
similarity index 100%
rename from proton-c/src/object/map.c
rename to proton-c/src/core/object/map.c
diff --git a/proton-c/src/object/object.c b/proton-c/src/core/object/object.c
similarity index 100%
rename from proton-c/src/object/object.c
rename to proton-c/src/core/object/object.c
diff --git a/proton-c/src/object/record.c b/proton-c/src/core/object/record.c
similarity index 100%
rename from proton-c/src/object/record.c
rename to proton-c/src/core/object/record.c
diff --git a/proton-c/src/object/string.c b/proton-c/src/core/object/string.c
similarity index 97%
rename from proton-c/src/object/string.c
rename to proton-c/src/core/object/string.c
index 7b900ca..13d0739 100644
--- a/proton-c/src/object/string.c
+++ b/proton-c/src/core/object/string.c
@@ -18,8 +18,7 @@
  * under the License.
  *
  */
-
-#include "platform.h"
+#include "platform/platform.h"
 
 #include <proton/error.h>
 #include <proton/object.h>
@@ -228,7 +227,7 @@
 
   while (true) {
     va_copy(copy, ap);
-    int err = vsnprintf(string->bytes + string->size, string->capacity - string->size, format, copy);
+    int err = pni_vsnprintf(string->bytes + string->size, string->capacity - string->size, format, copy);
     va_end(copy);
     if (err < 0) {
       return err;
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/core/transport.c
similarity index 99%
rename from proton-c/src/transport/transport.c
rename to proton-c/src/core/transport.c
index cdecfd2..e3b88b1 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/core/transport.c
@@ -19,20 +19,21 @@
  *
  */
 
-#include "engine/engine-internal.h"
-#include "framing/framing.h"
+#include "engine-internal.h"
+#include "framing.h"
+#include "platform/platform.h"
+#include "platform/platform_fmt.h"
 #include "sasl/sasl-internal.h"
 #include "ssl/ssl-internal.h"
 
 #include "autodetect.h"
 #include "protocol.h"
 #include "dispatch_actions.h"
-#include "proton/event.h"
-#include "platform.h"
-#include "platform_fmt.h"
 #include "config.h"
 #include "log_private.h"
 
+#include "proton/event.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
@@ -1112,7 +1113,7 @@
   char buf[1024];
   if (fmt) {
     // XXX: result
-    vsnprintf(buf, 1024, fmt, ap);
+    pni_vsnprintf(buf, 1024, fmt, ap);
   } else {
     buf[0] = '\0';
   }
@@ -1127,7 +1128,7 @@
     const char *first = pn_condition_get_description(cond);
     if (first && fmt) {
       char extended[2048];
-      snprintf(extended, 2048, "%s (%s)", first, buf);
+      pni_snprintf(extended, 2048, "%s (%s)", first, buf);
       pn_condition_set_description(cond, extended);
     } else if (fmt) {
       pn_condition_set_description(cond, buf);
diff --git a/proton-c/src/transport/transport.h b/proton-c/src/core/transport.h
similarity index 100%
rename from proton-c/src/transport/transport.h
rename to proton-c/src/core/transport.h
diff --git a/proton-c/src/types.c b/proton-c/src/core/types.c
similarity index 89%
rename from proton-c/src/types.c
rename to proton-c/src/core/types.c
index 4f8048d..dbd18d0 100644
--- a/proton-c/src/types.c
+++ b/proton-c/src/core/types.c
@@ -19,10 +19,7 @@
  *
  */
 
-#include "platform.h"
 #include <proton/types.h>
-#include <stdlib.h>
-#include <string.h>
 
 pn_bytes_t pn_bytes(size_t size, const char *start)
 {
@@ -35,7 +32,3 @@
   pn_rwbytes_t bytes = {size, start};
   return bytes;
 }
-
-pn_timestamp_t pn_timestamp_now() {
-  return pn_i_now();
-}
diff --git a/proton-c/src/util.c b/proton-c/src/core/util.c
similarity index 65%
rename from proton-c/src/util.c
rename to proton-c/src/core/util.c
index 47fbc34..62eec9a 100644
--- a/proton-c/src/util.c
+++ b/proton-c/src/core/util.c
@@ -99,112 +99,6 @@
   pn_fprint_data(stdout, bytes, size);
 }
 
-void pni_urldecode(const char *src, char *dst)
-{
-  const char *in = src;
-  char *out = dst;
-  while (*in != '\0')
-  {
-    if ('%' == *in)
-    {
-      if ((in[1] != '\0') && (in[2] != '\0'))
-      {
-        char esc[3];
-        esc[0] = in[1];
-        esc[1] = in[2];
-        esc[2] = '\0';
-        unsigned long d = strtoul(esc, NULL, 16);
-        *out = (char)d;
-        in += 3;
-        out++;
-      }
-      else
-      {
-        *out = *in;
-        in++;
-        out++;
-      }
-    }
-    else
-    {
-      *out = *in;
-      in++;
-      out++;
-    }
-  }
-  *out = '\0';
-}
-
-void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **host, char **port, char **path)
-{
-  if (!url) return;
-
-  char *slash = strchr(url, '/');
-
-  if (slash && slash>url) {
-    char *scheme_end = strstr(slash-1, "://");
-
-    if (scheme_end && scheme_end<slash) {
-      *scheme_end = '\0';
-      *scheme = url;
-      url = scheme_end + 3;
-      slash = strchr(url, '/');
-    }
-  }
-
-  if (slash) {
-    *slash = '\0';
-    *path = slash + 1;
-  }
-
-  char *at = strchr(url, '@');
-  if (at) {
-    *at = '\0';
-    char *up = url;
-    *user = up;
-    url = at + 1;
-    char *colon = strchr(up, ':');
-    if (colon) {
-      *colon = '\0';
-      *pass = colon + 1;
-    }
-  }
-
-  *host = url;
-  char *open = (*url == '[') ? url : 0;
-  if (open) {
-    char *close = strchr(open, ']');
-    if (close) {
-        *host = open + 1;
-        *close = '\0';
-        url = close + 1;
-    }
-  }
-
-  char *colon = strchr(url, ':');
-  if (colon) {
-    *colon = '\0';
-    *port = colon + 1;
-  }
-
-  if (*user) pni_urldecode(*user, *user);
-  if (*pass) pni_urldecode(*pass, *pass);
-}
-
-void pni_vfatal(const char *fmt, va_list ap)
-{
-  vfprintf(stderr, fmt, ap);
-  abort();
-}
-
-void pni_fatal(const char *fmt, ...)
-{
-  va_list ap;
-  va_start(ap, fmt);
-  pni_vfatal(fmt, ap);
-  va_end(ap);
-}
-
 int pn_strcasecmp(const char *a, const char *b)
 {
   int diff;
@@ -237,13 +131,10 @@
 
 char *pn_strdup(const char *src)
 {
-  if (src) {
-    char *dest = (char *) malloc((strlen(src)+1)*sizeof(char));
-    if (!dest) return NULL;
-    return strcpy(dest, src);
-  } else {
-    return NULL;
-  }
+  if (!src) return NULL;
+  char *dest = (char *) malloc(strlen(src)+1);
+  if (!dest) return NULL;
+  return strcpy(dest, src);
 }
 
 char *pn_strndup(const char *src, size_t n)
diff --git a/proton-c/src/util.h b/proton-c/src/core/util.h
similarity index 96%
rename from proton-c/src/util.h
rename to proton-c/src/core/util.h
index ec59a07..b54f689 100644
--- a/proton-c/src/util.h
+++ b/proton-c/src/core/util.h
@@ -32,9 +32,6 @@
 #include <proton/types.h>
 #include <proton/object.h>
 
-void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **host, char **port, char **path);
-void pni_fatal(const char *fmt, ...);
-void pni_vfatal(const char *fmt, va_list ap);
 ssize_t pn_quote_data(char *dst, size_t capacity, const char *src, size_t size);
 int pn_quote(pn_string_t *dst, const char *src, size_t size);
 void pn_fprint_data(FILE *stream, const char *bytes, size_t size);
diff --git a/proton-c/src/codec/encodings.h.py b/proton-c/src/encodings.h.py
old mode 100755
new mode 100644
similarity index 100%
rename from proton-c/src/codec/encodings.h.py
rename to proton-c/src/encodings.h.py
diff --git a/proton-c/src/parser.c b/proton-c/src/extra/parser.c
similarity index 99%
rename from proton-c/src/parser.c
rename to proton-c/src/extra/parser.c
index 87cb758..36fb4fb 100644
--- a/proton-c/src/parser.c
+++ b/proton-c/src/extra/parser.c
@@ -20,12 +20,15 @@
  */
 
 #include <proton/parser.h>
-#include <proton/scanner.h>
+
+#include "platform/platform.h"
+#include "scanner.h"
+
 #include <proton/error.h>
+
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include "platform.h"
 
 struct pn_parser_t {
   pn_scanner_t *scanner;
diff --git a/proton-c/src/scanner.c b/proton-c/src/extra/scanner.c
similarity index 98%
rename from proton-c/src/scanner.c
rename to proton-c/src/extra/scanner.c
index 9a058e9..beb7322 100644
--- a/proton-c/src/scanner.c
+++ b/proton-c/src/extra/scanner.c
@@ -19,7 +19,10 @@
  *
  */
 
-#include <proton/scanner.h>
+#include "scanner.h"
+
+#include "platform/platform.h"
+
 #include <proton/error.h>
 #ifndef __cplusplus
 #include <stdbool.h>
@@ -27,7 +30,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include "platform.h"
 
 #define ERROR_SIZE (1024)
 
@@ -130,7 +132,7 @@
   int line, col;
   pn_scanner_line_info(scanner, &line, &col);
   int size = scanner->token.size;
-  int ln = snprintf(error, ERROR_SIZE,
+  int ln = pni_snprintf(error, ERROR_SIZE,
                     "input line %i column %i %s:'%.*s': ", line, col,
                     pni_token_type(scanner->token.type),
                     size, scanner->token.start);
@@ -140,7 +142,7 @@
     error[0] = '\0';
   }
 
-  int n = snprintf(error + ln, ERROR_SIZE - ln, fmt, ap);
+  int n = pni_snprintf(error + ln, ERROR_SIZE - ln, fmt, ap);
 
   if (n >= ERROR_SIZE - ln) {
     return pn_scanner_err(scanner, code, "error info truncated");
diff --git a/proton-c/include/proton/scanner.h b/proton-c/src/extra/scanner.h
similarity index 96%
rename from proton-c/include/proton/scanner.h
rename to proton-c/src/extra/scanner.h
index 10d7d32..218babe 100644
--- a/proton-c/include/proton/scanner.h
+++ b/proton-c/src/extra/scanner.h
@@ -26,10 +26,6 @@
 #include <stddef.h>
 #include <stdarg.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef enum {
   PN_TOK_LBRACE,
   PN_TOK_RBRACE,
@@ -75,8 +71,4 @@
 PN_EXTERN int pn_scanner_scan(pn_scanner_t *scanner);
 PN_EXTERN int pn_scanner_shift(pn_scanner_t *scanner);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* scanner.h */
diff --git a/proton-c/src/url.c b/proton-c/src/extra/url.c
similarity index 71%
rename from proton-c/src/url.c
rename to proton-c/src/extra/url.c
index 566e91e..c1ce628 100644
--- a/proton-c/src/url.c
+++ b/proton-c/src/extra/url.c
@@ -21,18 +21,121 @@
 
 #include "proton/url.h"
 #include "proton/object.h"
-#include "util.h"
-#include "platform.h"
+
+#include "core/util.h"
 
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 
-static char* copy(const char* str) {
-    if (str ==  NULL) return NULL;
-    char *str2 = (char*)malloc(strlen(str)+1);
-    if (str2) strcpy(str2, str);
-    return str2;
+
+/** URL-encode src and append to dst. */
+static void pni_urlencode(pn_string_t *dst, const char* src) {
+    static const char *bad = "@:/";
+
+    if (!src) return;
+    const char *i = src;
+    const char *j = strpbrk(i, bad);
+    while (j) {
+        pn_string_addf(dst, "%.*s", (int)(j-i), i);
+        pn_string_addf(dst, "%%%02X", (int)*j);
+        i = j + 1;
+        j = strpbrk(i, bad);
+    }
+    pn_string_addf(dst, "%s", i);
+}
+
+// Low level url parser
+static void pni_urldecode(const char *src, char *dst)
+{
+  const char *in = src;
+  char *out = dst;
+  while (*in != '\0')
+  {
+    if ('%' == *in)
+    {
+      if ((in[1] != '\0') && (in[2] != '\0'))
+      {
+        char esc[3];
+        esc[0] = in[1];
+        esc[1] = in[2];
+        esc[2] = '\0';
+        unsigned long d = strtoul(esc, NULL, 16);
+        *out = (char)d;
+        in += 3;
+        out++;
+      }
+      else
+      {
+        *out = *in;
+        in++;
+        out++;
+      }
+    }
+    else
+    {
+      *out = *in;
+      in++;
+      out++;
+    }
+  }
+  *out = '\0';
+}
+
+void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **host, char **port, char **path)
+{
+  if (!url) return;
+
+  char *slash = strchr(url, '/');
+
+  if (slash && slash>url) {
+    char *scheme_end = strstr(slash-1, "://");
+
+    if (scheme_end && scheme_end<slash) {
+      *scheme_end = '\0';
+      *scheme = url;
+      url = scheme_end + 3;
+      slash = strchr(url, '/');
+    }
+  }
+
+  if (slash) {
+    *slash = '\0';
+    *path = slash + 1;
+  }
+
+  char *at = strchr(url, '@');
+  if (at) {
+    *at = '\0';
+    char *up = url;
+    *user = up;
+    url = at + 1;
+    char *colon = strchr(up, ':');
+    if (colon) {
+      *colon = '\0';
+      *pass = colon + 1;
+    }
+  }
+
+  *host = url;
+  char *open = (*url == '[') ? url : 0;
+  if (open) {
+    char *close = strchr(open, ']');
+    if (close) {
+        *host = open + 1;
+        *close = '\0';
+        url = close + 1;
+    }
+  }
+
+  char *colon = strchr(url, ':');
+  if (colon) {
+    *colon = '\0';
+    *port = colon + 1;
+  }
+
+  if (*user) pni_urldecode(*user, *user);
+  if (*pass) pni_urldecode(*pass, *pass);
 }
 
 struct pn_url_t {
@@ -103,14 +206,14 @@
         return NULL;
 
     pn_url_t *url = pn_url();
-    char *str2 = copy(str);
+    char *str2 = pn_strdup(str);
     pni_parse_url(str2, &url->scheme, &url->username, &url->password, &url->host, &url->port, &url->path);
-    url->scheme = copy(url->scheme);
-    url->username = copy(url->username);
-    url->password = copy(url->password);
-    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
-    url->port = copy(url->port);
-    url->path = copy(url->path);
+    url->scheme = pn_strdup(url->scheme);
+    url->username = pn_strdup(url->username);
+    url->password = pn_strdup(url->password);
+    url->host = (url->host && !*url->host) ? NULL : pn_strdup(url->host);
+    url->port = pn_strdup(url->port);
+    url->path = pn_strdup(url->path);
 
     free(str2);
     return url;
@@ -130,23 +233,6 @@
     pn_string_clear(url->str);
 }
 
-/** URL-encode src and append to dst. */
-static void pni_urlencode(pn_string_t *dst, const char* src) {
-    static const char *bad = "@:/";
-
-    if (!src) return;
-    const char *i = src;
-    const char *j = strpbrk(i, bad);
-    while (j) {
-        pn_string_addf(dst, "%.*s", (int)(j-i), i);
-        pn_string_addf(dst, "%%%02X", (int)*j);
-        i = j + 1;
-        j = strpbrk(i, bad);
-    }
-    pn_string_addf(dst, "%s", i);
-}
-
-
 /** Return the string form of a URL. */
 const char *pn_url_str(pn_url_t *url) {
     if (pn_string_get(url->str) == NULL) {
@@ -175,7 +261,7 @@
 const char *pn_url_get_port(pn_url_t *url) { return url->port; }
 const char *pn_url_get_path(pn_url_t *url) { return url->path; }
 
-#define SET(part) free(url->part); url->part = copy(part); pn_string_clear(url->str)
+#define SET(part) free(url->part); url->part = pn_strdup(part); pn_string_clear(url->str)
 void pn_url_set_scheme(pn_url_t *url, const char *scheme) { SET(scheme); }
 void pn_url_set_username(pn_url_t *url, const char *username) { SET(username); }
 void pn_url_set_password(pn_url_t *url, const char *password) { SET(password); }
diff --git a/proton-c/src/handlers/iohandler.c b/proton-c/src/handlers/iohandler.c
index 9154884..db18c0c 100644
--- a/proton-c/src/handlers/iohandler.c
+++ b/proton-c/src/handlers/iohandler.c
@@ -19,8 +19,11 @@
  *
  */
 
+#include "reactor/io.h"
+#include "reactor/reactor.h"
+#include "reactor/selector.h"
+
 #include <proton/handlers.h>
-#include <proton/selector.h>
 #include <proton/transport.h>
 #include <assert.h>
 
@@ -62,7 +65,7 @@
   pn_record_t *record = pn_reactor_attachments(reactor);
   pn_selector_t *selector = (pn_selector_t *) pn_record_get(record, PN_SELECTOR);
   if (!selector) {
-    selector = pn_io_selector(pn_reactor_io(reactor));
+    selector = pn_io_selector(pni_reactor_io(reactor));
     pn_record_def(record, PN_SELECTOR, PN_OBJECT);
     pn_record_set(record, PN_SELECTOR, selector);
     pn_decref(selector);
diff --git a/proton-c/src/types.c b/proton-c/src/libqpid-proton-core.pc.in
similarity index 68%
copy from proton-c/src/types.c
copy to proton-c/src/libqpid-proton-core.pc.in
index 4f8048d..ff99108 100644
--- a/proton-c/src/types.c
+++ b/proton-c/src/libqpid-proton-core.pc.in
@@ -1,5 +1,4 @@
 /*
- *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -16,26 +15,16 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
- *
  */
 
-#include "platform.h"
-#include <proton/types.h>
-#include <stdlib.h>
-#include <string.h>
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
 
-pn_bytes_t pn_bytes(size_t size, const char *start)
-{
-  pn_bytes_t bytes = {size, start};
-  return bytes;
-}
-
-pn_rwbytes_t pn_rwbytes(size_t size, char *start)
-{
-  pn_rwbytes_t bytes = {size, start};
-  return bytes;
-}
-
-pn_timestamp_t pn_timestamp_now() {
-  return pn_i_now();
-}
+Name: Proton Core
+Description: Qpid Proton C core protocol library
+Version: @PN_VERSION@
+URL: http://qpid.apache.org/proton/
+Libs: -L${libdir} -lqpid-proton-core
+Cflags: -I${includedir}
diff --git a/proton-c/src/messenger/messenger.c b/proton-c/src/messenger/messenger.c
index 64be017..264a733 100644
--- a/proton-c/src/messenger/messenger.c
+++ b/proton-c/src/messenger/messenger.c
@@ -27,7 +27,6 @@
 #include <proton/object.h>
 #include <proton/sasl.h>
 #include <proton/session.h>
-#include <proton/selector.h>
 
 #include <assert.h>
 #include <ctype.h>
@@ -35,14 +34,17 @@
 #include <string.h>
 #include <stdio.h>
 
-#include "util.h"
-#include "platform.h"
-#include "platform_fmt.h"
+#include "core/log_private.h"
+#include "core/util.h"
+#include "platform/platform.h" // pn_i_getpid, pn_i_now, pni_snprintf
+#include "platform/platform_fmt.h"
 #include "store.h"
-#include "transform.h"
 #include "subscription.h"
-#include "selectable.h"
-#include "log_private.h"
+#include "transform.h"
+
+#include "reactor/io.h"
+#include "reactor/selectable.h"
+#include "reactor/selector.h"
 
 typedef struct pn_link_ctx_t pn_link_ctx_t;
 
@@ -980,7 +982,7 @@
             pn_condition_redirect_port(condition));
   } else if (pn_condition_is_set(condition)) {
     char error[1024];
-    snprintf(error, 1024, "(%s) %s",
+    pni_snprintf(error, 1024, "(%s) %s",
              pn_condition_get_name(condition),
              pn_condition_get_description(condition));
     pn_error_report(pfx, error);
diff --git a/proton-c/src/messenger/store.c b/proton-c/src/messenger/store.c
index bdd7e24..44f24f1 100644
--- a/proton-c/src/messenger/store.c
+++ b/proton-c/src/messenger/store.c
@@ -28,7 +28,7 @@
 #endif
 #include <stdlib.h>
 #include <string.h>
-#include "util.h"
+#include "core/util.h"
 #include "store.h"
 
 typedef struct pni_stream_t pni_stream_t;
diff --git a/proton-c/src/messenger/store.h b/proton-c/src/messenger/store.h
index 2ca243b..22bb94e 100644
--- a/proton-c/src/messenger/store.h
+++ b/proton-c/src/messenger/store.h
@@ -22,7 +22,7 @@
  *
  */
 
-#include "buffer.h"
+#include "core/buffer.h"
 
 typedef struct pni_store_t pni_store_t;
 typedef struct pni_entry_t pni_entry_t;
diff --git a/proton-c/src/messenger/transform.h b/proton-c/src/messenger/transform.h
index c9350ef..3288f6c 100644
--- a/proton-c/src/messenger/transform.h
+++ b/proton-c/src/messenger/transform.h
@@ -22,8 +22,9 @@
  *
  */
 
+#include "core/buffer.h"
+
 #include <proton/object.h>
-#include "buffer.h"
 
 typedef struct pn_transform_t pn_transform_t;
 
diff --git a/proton-c/src/platform.c b/proton-c/src/platform/platform.c
similarity index 78%
rename from proton-c/src/platform.c
rename to proton-c/src/platform/platform.c
index 3a8cade..393f75c 100644
--- a/proton-c/src/platform.c
+++ b/proton-c/src/platform/platform.c
@@ -20,7 +20,10 @@
  */
 
 #include "platform.h"
-#include "util.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 #ifdef PN_WINAPI
 #include <windows.h>
@@ -34,6 +37,20 @@
 }
 #endif
 
+void pni_vfatal(const char *fmt, va_list ap)
+{
+  vfprintf(stderr, fmt, ap);
+  abort();
+}
+
+void pni_fatal(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  pni_vfatal(fmt, ap);
+  va_end(ap);
+}
+
 /* Allow for systems that do not implement clock_gettime()*/
 #ifdef USE_CLOCK_GETTIME
 #include <time.h>
@@ -70,7 +87,7 @@
 static void pn_i_strerror(int errnum, char *buf, size_t buflen)
 {
   // PROTON-1029 provide a simple default in case strerror fails
-  snprintf(buf, buflen, "errno: %d", errnum);
+  pni_snprintf(buf, buflen, "errno: %d", errnum);
 #ifdef USE_STRERROR_R
   strerror_r(errnum, buf, buflen);
 #elif USE_STRERROR_S
@@ -103,32 +120,3 @@
 #else
 #error "Don't know how to convert int64_t values on this platform"
 #endif
-
-#ifdef _MSC_VER
-// [v]snprintf on Windows only matches C99 when no errors or overflow.
-int pn_i_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap) {
-  if (fmt == NULL)
-    return -1;
-  if ((buf == NULL) && (count > 0))
-    return -1;
-  if (count > 0) {
-    int n = vsnprintf_s(buf, count, _TRUNCATE, fmt, ap);
-    if (n >= 0)  // no overflow
-      return n;  // same as C99
-    buf[count-1] = '\0';
-  }
-  // separate call to get needed buffer size on overflow
-  int n = _vscprintf(fmt, ap);
-  if (n >= (int) count)
-    return n;
-  return -1;
-}
-
-int pn_i_snprintf(char *buf, size_t count, const char *fmt, ...) {
-  va_list ap;
-  va_start(ap, fmt);
-  int n = pn_i_vsnprintf(buf, count, fmt, ap);
-  va_end(ap);
-  return n;
-}
-#endif
diff --git a/proton-c/src/platform.h b/proton-c/src/platform/platform.h
similarity index 82%
rename from proton-c/src/platform.h
rename to proton-c/src/platform/platform.h
index 6a0bbc1..d846cda 100644
--- a/proton-c/src/platform.h
+++ b/proton-c/src/platform/platform.h
@@ -25,10 +25,6 @@
 #include "proton/types.h"
 #include "proton/error.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /** Get the current PID
  *
  * @return process id
@@ -69,18 +65,15 @@
  */
 int64_t pn_i_atoll(const char* num);
 
-#ifdef _MSC_VER
-/** Windows snprintf and vsnprintf substitutes.
- *
- * Provide the expected C99 behavior for these functions.
- */
-#include <stdio.h>
+int pni_snprintf(char *buf, size_t count, const char *fmt, ...);
+int pni_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap);
 
-#define snprintf pn_i_snprintf
-#define vsnprintf pn_i_vsnprintf
+#ifndef _MSC_VER
 
-int pn_i_snprintf(char *buf, size_t count, const char *fmt, ...);
-int pn_i_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap);
+#define pni_snprintf snprintf
+#define pni_vsnprintf vsnprintf
+
+#else
 
 #if !defined(S_ISDIR)
 # define S_ISDIR(X) ((X) & _S_IFDIR)
@@ -94,8 +87,7 @@
 #endif
 #endif
 
-#ifdef __cplusplus
-}
-#endif
+// Low level pretty rubbish URL parser
+void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **host, char **port, char **path);
 
 #endif /* platform.h */
diff --git a/proton-c/src/platform_fmt.h b/proton-c/src/platform/platform_fmt.h
similarity index 100%
rename from proton-c/src/platform_fmt.h
rename to proton-c/src/platform/platform_fmt.h
diff --git a/proton-c/src/reactor/acceptor.c b/proton-c/src/reactor/acceptor.c
index f56f7bd..a044748 100644
--- a/proton-c/src/reactor/acceptor.c
+++ b/proton-c/src/reactor/acceptor.c
@@ -19,13 +19,14 @@
  *
  */
 
-#include <proton/io.h>
 #include <proton/sasl.h>
-#include <proton/selector.h>
 #include <proton/transport.h>
 #include <proton/connection.h>
+
+#include "io.h"
 #include "reactor.h"
 #include "selectable.h"
+#include "selector.h"
 
 #include <string.h>
 
@@ -38,7 +39,7 @@
 void pni_acceptor_readable(pn_selectable_t *sel) {
   pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
   char name[1024];
-  pn_socket_t sock = pn_accept(pn_reactor_io(reactor), pn_selectable_get_fd(sel), name, 1024);
+  pn_socket_t sock = pn_accept(pni_reactor_io(reactor), pn_selectable_get_fd(sel), name, 1024);
   pn_handler_t *handler = (pn_handler_t *) pn_record_get(pn_selectable_attachments(sel), PNI_ACCEPTOR_HANDLER);
   if (!handler) { handler = pn_reactor_get_handler(reactor); }
   pn_record_t *record = pn_selectable_attachments(sel);
@@ -67,12 +68,12 @@
 void pni_acceptor_finalize(pn_selectable_t *sel) {
   pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
   if (pn_selectable_get_fd(sel) != PN_INVALID_SOCKET) {
-    pn_close(pn_reactor_io(reactor), pn_selectable_get_fd(sel));
+    pn_close(pni_reactor_io(reactor), pn_selectable_get_fd(sel));
   }
 }
 
 pn_acceptor_t *pn_reactor_acceptor(pn_reactor_t *reactor, const char *host, const char *port, pn_handler_t *handler) {
-  pn_socket_t socket = pn_listen(pn_reactor_io(reactor), host, port);
+  pn_socket_t socket = pn_listen(pni_reactor_io(reactor), host, port);
   if (socket == PN_INVALID_SOCKET) {
     return NULL;
   }
@@ -94,7 +95,7 @@
   if (!pn_selectable_is_terminal(sel)) {
     pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
     pn_socket_t socket = pn_selectable_get_fd(sel);
-    pn_close(pn_reactor_io(reactor), socket);
+    pn_close(pni_reactor_io(reactor), socket);
     pn_selectable_set_fd(sel, PN_INVALID_SOCKET);
     pn_selectable_terminate(sel);
     pn_reactor_update(reactor, sel);
diff --git a/proton-c/src/reactor/connection.c b/proton-c/src/reactor/connection.c
index d73e386..4bc8b8d 100644
--- a/proton-c/src/reactor/connection.c
+++ b/proton-c/src/reactor/connection.c
@@ -28,6 +28,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
+#include "io.h"
 #include "selectable.h"
 #include "reactor.h"
 
@@ -187,12 +188,12 @@
       pn_transport_close_tail(transport);
       pn_transport_close_head(transport);
   } else {
-      pn_socket_t sock = pn_connect(pn_reactor_io(reactor), host, port);
+      pn_socket_t sock = pn_connect(pni_reactor_io(reactor), host, port);
       // invalid sockets are ignored by poll, so we need to do this manualy
       if (sock == PN_INVALID_SOCKET) {
           pn_condition_t *cond = pn_transport_condition(transport);
           pn_condition_set_name(cond, "proton:io");
-          pn_condition_set_description(cond, pn_error_text(pn_io_error(pn_reactor_io(reactor))));
+          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
           pn_transport_close_tail(transport);
           pn_transport_close_head(transport);
       } else {
@@ -215,14 +216,14 @@
   pn_transport_t *transport = pni_transport(sel);
   ssize_t capacity = pn_transport_capacity(transport);
   if (capacity > 0) {
-    ssize_t n = pn_recv(pn_reactor_io(reactor), pn_selectable_get_fd(sel),
+    ssize_t n = pn_recv(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
                         pn_transport_tail(transport), capacity);
     if (n <= 0) {
-      if (n == 0 || !pn_wouldblock(pn_reactor_io(reactor))) {
+      if (n == 0 || !pn_wouldblock(pni_reactor_io(reactor))) {
         if (n < 0) {
           pn_condition_t *cond = pn_transport_condition(transport);
           pn_condition_set_name(cond, "proton:io");
-          pn_condition_set_description(cond, pn_error_text(pn_io_error(pn_reactor_io(reactor))));
+          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
         }
         pn_transport_close_tail(transport);
       }
@@ -246,14 +247,14 @@
   pn_transport_t *transport = pni_transport(sel);
   ssize_t pending = pn_transport_pending(transport);
   if (pending > 0) {
-    ssize_t n = pn_send(pn_reactor_io(reactor), pn_selectable_get_fd(sel),
+    ssize_t n = pn_send(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
                         pn_transport_head(transport), pending);
     if (n < 0) {
-      if (!pn_wouldblock(pn_reactor_io(reactor))) {
+      if (!pn_wouldblock(pni_reactor_io(reactor))) {
         pn_condition_t *cond = pn_transport_condition(transport);
         if (!pn_condition_is_set(cond)) {
           pn_condition_set_name(cond, "proton:io");
-          pn_condition_set_description(cond, pn_error_text(pn_io_error(pn_reactor_io(reactor))));
+          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
         }
         pn_transport_close_head(transport);
       }
@@ -296,7 +297,7 @@
   pn_record_t *record = pn_transport_attachments(transport);
   pn_record_set(record, PN_TRANCTX, NULL);
   pn_socket_t fd = pn_selectable_get_fd(sel);
-  pn_close(pn_reactor_io(reactor), fd);
+  pn_close(pni_reactor_io(reactor), fd);
 }
 
 pn_selectable_t *pn_reactor_selectable_transport(pn_reactor_t *reactor, pn_socket_t sock, pn_transport_t *transport) {
diff --git a/proton-c/src/reactor/io.h b/proton-c/src/reactor/io.h
new file mode 100644
index 0000000..24596ec
--- /dev/null
+++ b/proton-c/src/reactor/io.h
@@ -0,0 +1,70 @@
+#ifndef PROTON_IO_H
+#define PROTON_IO_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "selector.h"
+
+#include <proton/import_export.h>
+#include <proton/error.h>
+#include <proton/type_compat.h>
+#include <stddef.h>
+
+/**
+ * A ::pn_io_t manages IO for a group of pn_socket_t handles.  A
+ * pn_io_t object may have zero or one pn_selector_t selectors
+ * associated with it (see ::pn_io_selector()).  If one is associated,
+ * all the pn_socket_t handles managed by a pn_io_t must use that
+ * pn_selector_t instance.
+ *
+ * The pn_io_t interface is single-threaded. All methods are intended
+ * to be used by one thread at a time, except that multiple threads
+ * may use:
+ *
+ *   ::pn_write()
+ *   ::pn_send()
+ *   ::pn_recv()
+ *   ::pn_close()
+ *   ::pn_selector_select()
+ *
+ * provided at most one thread is calling ::pn_selector_select() and
+ * the other threads are operating on separate pn_socket_t handles.
+ */
+typedef struct pn_io_t pn_io_t;
+
+pn_io_t *pn_io(void);
+void pn_io_free(pn_io_t *io);
+pn_error_t *pn_io_error(pn_io_t *io);
+pn_socket_t pn_connect(pn_io_t *io, const char *host, const char *port);
+pn_socket_t pn_listen(pn_io_t *io, const char *host, const char *port);
+
+pn_socket_t pn_accept(pn_io_t *io, pn_socket_t socket, char *name, size_t size);
+void pn_close(pn_io_t *io, pn_socket_t socket);
+ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size);
+ssize_t pn_recv(pn_io_t *io, pn_socket_t socket, void *buf, size_t size);
+int pn_pipe(pn_io_t *io, pn_socket_t *dest);
+ssize_t pn_read(pn_io_t *io, pn_socket_t socket, void *buf, size_t size);
+ssize_t pn_write(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size);
+bool pn_wouldblock(pn_io_t *io);
+pn_selector_t *pn_io_selector(pn_io_t *io);
+
+#endif /* io.h */
diff --git a/proton-c/src/posix/io.c b/proton-c/src/reactor/io/posix/io.c
similarity index 97%
rename from proton-c/src/posix/io.c
rename to proton-c/src/reactor/io/posix/io.c
index 27d1a35..5a0de3b 100644
--- a/proton-c/src/posix/io.c
+++ b/proton-c/src/reactor/io/posix/io.c
@@ -19,9 +19,11 @@
  *
  */
 
-#include <proton/io.h>
+#include "reactor/io.h"
+#include "reactor/selector.h"
+#include "platform/platform.h" // pn_i_error_from_errno
+
 #include <proton/object.h>
-#include <proton/selector.h>
 
 #include <ctype.h>
 #include <errno.h>
@@ -35,8 +37,6 @@
 #include <fcntl.h>
 #include <assert.h>
 
-#include "platform.h"
-
 #define MAX_HOST (1024)
 #define MAX_SERV (64)
 
@@ -218,7 +218,7 @@
       return PN_INVALID_SOCKET;
     } else {
       pn_configure_sock(io, sock);
-      snprintf(name, size, "%s:%s", io->host, io->serv);
+      pni_snprintf(name, size, "%s:%s", io->host, io->serv);
       return sock;
     }
   }
diff --git a/proton-c/src/posix/selector.c b/proton-c/src/reactor/io/posix/selector.c
similarity index 96%
rename from proton-c/src/posix/selector.c
rename to proton-c/src/reactor/io/posix/selector.c
index 7f72c84..bf6882a 100644
--- a/proton-c/src/posix/selector.c
+++ b/proton-c/src/reactor/io/posix/selector.c
@@ -19,14 +19,17 @@
  *
  */
 
-#include <proton/selector.h>
+#include "core/util.h"
+#include "platform/platform.h" // pn_i_now, pn_i_error_from_errno
+#include "reactor/io.h"
+#include "reactor/selector.h"
+#include "reactor/selectable.h"
+
 #include <proton/error.h>
+
 #include <poll.h>
 #include <stdlib.h>
 #include <assert.h>
-#include "platform.h"
-#include "selectable.h"
-#include "util.h"
 
 struct pn_selector_t {
   struct pollfd *fds;
diff --git a/proton-c/src/windows/io.c b/proton-c/src/reactor/io/windows/io.c
similarity index 98%
rename from proton-c/src/windows/io.c
rename to proton-c/src/reactor/io/windows/io.c
index 4a87fd2..3ae6722 100644
--- a/proton-c/src/windows/io.c
+++ b/proton-c/src/reactor/io/windows/io.c
@@ -30,12 +30,14 @@
 #include <mswsock.h>
 #include <Ws2tcpip.h>
 
-#include "platform.h"
-#include <proton/io.h>
-#include <proton/object.h>
-#include <proton/selector.h>
+#include "reactor/io.h"
+#include "reactor/selector.h"
+
+#include "platform/platform.h"
 #include "iocp.h"
-#include "util.h"
+#include "core/util.h"
+
+#include <proton/object.h>
 
 #include <ctype.h>
 #include <errno.h>
@@ -301,7 +303,7 @@
     return INVALID_SOCKET;
   } else {
     pn_configure_sock(io, accept_sock);
-    snprintf(name, size, "%s:%s", io->host, io->serv);
+    pni_snprintf(name, size, "%s:%s", io->host, io->serv);
     if (listend) {
       pni_iocpdesc_start(pni_iocpdesc_map_get(io->iocp, accept_sock));
     }
diff --git a/proton-c/src/windows/iocp.c b/proton-c/src/reactor/io/windows/iocp.c
similarity index 99%
rename from proton-c/src/windows/iocp.c
rename to proton-c/src/reactor/io/windows/iocp.c
index d1abc9a..8a1a64a 100644
--- a/proton-c/src/windows/iocp.c
+++ b/proton-c/src/reactor/io/windows/iocp.c
@@ -29,14 +29,17 @@
 #include <mswsock.h>
 #include <Ws2tcpip.h>
 
-#include "platform.h"
+#include "reactor/io.h"
+#include "reactor/selector.h"
+
+#include "iocp.h"
+#include "platform/platform.h"
+#include "core/util.h"
+
 #include <proton/object.h>
-#include <proton/io.h>
-#include <proton/selector.h>
 #include <proton/error.h>
 #include <proton/transport.h>
-#include "iocp.h"
-#include "util.h"
+
 #include <assert.h>
 
 /*
diff --git a/proton-c/src/windows/iocp.h b/proton-c/src/reactor/io/windows/iocp.h
similarity index 98%
rename from proton-c/src/windows/iocp.h
rename to proton-c/src/reactor/io/windows/iocp.h
index 0e052e5..07f47be 100644
--- a/proton-c/src/windows/iocp.h
+++ b/proton-c/src/reactor/io/windows/iocp.h
@@ -26,10 +26,6 @@
 #include <proton/selectable.h>
 #include <proton/type_compat.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef struct pni_acceptor_t pni_acceptor_t;
 typedef struct write_result_t write_result_t;
 typedef struct read_result_t read_result_t;
@@ -137,8 +133,4 @@
 
 int pni_win32_error(pn_error_t *error, const char *msg, HRESULT code);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* iocp.h */
diff --git a/proton-c/src/windows/selector.c b/proton-c/src/reactor/io/windows/selector.c
similarity index 98%
rename from proton-c/src/windows/selector.c
rename to proton-c/src/reactor/io/windows/selector.c
index f139aec..15da73b 100644
--- a/proton-c/src/windows/selector.c
+++ b/proton-c/src/reactor/io/windows/selector.c
@@ -28,15 +28,17 @@
 #include <winsock2.h>
 #include <Ws2tcpip.h>
 
-#include "platform.h"
+#include "reactor/io.h"
+#include "reactor/selectable.h"
+#include "reactor/selector.h"
+
+#include "iocp.h"
+#include "platform/platform.h"
+#include "core/util.h"
+
 #include <proton/object.h>
-#include <proton/io.h>
-#include <proton/selector.h>
 #include <proton/error.h>
 #include <assert.h>
-#include "selectable.h"
-#include "util.h"
-#include "iocp.h"
 
 static void interests_update(iocpdesc_t *iocpd, int interests);
 static void deadlines_update(iocpdesc_t *iocpd, pn_timestamp_t t);
diff --git a/proton-c/src/windows/write_pipeline.c b/proton-c/src/reactor/io/windows/write_pipeline.c
similarity index 98%
rename from proton-c/src/windows/write_pipeline.c
rename to proton-c/src/reactor/io/windows/write_pipeline.c
index e14e714..905c7f6 100644
--- a/proton-c/src/windows/write_pipeline.c
+++ b/proton-c/src/reactor/io/windows/write_pipeline.c
@@ -36,15 +36,17 @@
 #include <winsock2.h>
 #include <Ws2tcpip.h>
 
-#include "platform.h"
-#include <proton/object.h>
-#include <proton/io.h>
-#include <proton/selector.h>
-#include <proton/error.h>
-#include <assert.h>
-#include "selectable.h"
-#include "util.h"
+#include "reactor/io.h"
+#include "reactor/selector.h"
+#include "reactor/selectable.h"
+
 #include "iocp.h"
+#include "core/util.h"
+
+#include <proton/error.h>
+#include <proton/object.h>
+
+#include <assert.h>
 
 // Max overlapped writes per socket
 #define IOCP_MAX_OWRITES 16
diff --git a/proton-c/src/reactor/reactor.c b/proton-c/src/reactor/reactor.c
index a83a881..abf5d1e 100644
--- a/proton-c/src/reactor/reactor.c
+++ b/proton-c/src/reactor/reactor.c
@@ -19,23 +19,24 @@
  *
  */
 
+#include "io.h"
+#include "reactor.h"
+#include "selectable.h"
+#include "platform/platform.h" // pn_i_now
+
 #include <proton/object.h>
 #include <proton/handlers.h>
-#include <proton/io.h>
 #include <proton/event.h>
 #include <proton/transport.h>
 #include <proton/connection.h>
 #include <proton/session.h>
 #include <proton/link.h>
 #include <proton/delivery.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 
-#include "reactor.h"
-#include "selectable.h"
-#include "platform.h"
-
 struct pn_reactor_t {
   pn_record_t *attachments;
   pn_io_t *io;
@@ -164,7 +165,7 @@
   pn_incref(reactor->handler);
 }
 
-pn_io_t *pn_reactor_io(pn_reactor_t *reactor) {
+pn_io_t *pni_reactor_io(pn_reactor_t *reactor) {
   assert(reactor);
   return reactor->io;
 }
@@ -389,6 +390,16 @@
   return pn_event_type(event) == PN_REACTOR_QUIESCED;
 }
 
+pn_handler_t *pn_event_root(pn_event_t *event)
+{
+  pn_handler_t *h = pn_record_get_handler(pn_event_attachments(event));
+  return h;
+}
+
+static void pni_event_set_root(pn_event_t *event, pn_handler_t *handler) {
+  pn_record_set_handler(pn_event_attachments(event), handler);
+}
+
 bool pn_reactor_process(pn_reactor_t *reactor) {
   assert(reactor);
   pn_reactor_mark(reactor);
diff --git a/proton-c/src/reactor/reactor.h b/proton-c/src/reactor/reactor.h
index 461e8b3..bfb397c 100644
--- a/proton-c/src/reactor/reactor.h
+++ b/proton-c/src/reactor/reactor.h
@@ -26,9 +26,9 @@
 #include <proton/url.h>
 
 void pni_record_init_reactor(pn_record_t *record, pn_reactor_t *reactor);
-void pni_event_set_root(pn_event_t *event, pn_handler_t *handler);
 void pni_reactor_set_connection_peer_address(pn_connection_t *connection,
                                              const char *host,
                                              const char *port);
+pn_io_t *pni_reactor_io(pn_reactor_t *reactor);
 
 #endif /* src/reactor.h */
diff --git a/proton-c/src/selectable.c b/proton-c/src/reactor/selectable.c
similarity index 99%
rename from proton-c/src/selectable.c
rename to proton-c/src/reactor/selectable.c
index 88a60f7..b42ad1f 100644
--- a/proton-c/src/selectable.c
+++ b/proton-c/src/reactor/selectable.c
@@ -19,11 +19,14 @@
  *
  */
 
-#include <proton/error.h>
-#include <proton/io.h>
 #include "selectable.h"
-#include <stdlib.h>
+
+#include <proton/error.h>
+
+#include "io.h"
+
 #include <assert.h>
+#include <stdlib.h>
 
 pn_selectables_t *pn_selectables(void)
 {
diff --git a/proton-c/src/selectable.h b/proton-c/src/reactor/selectable.h
similarity index 100%
rename from proton-c/src/selectable.h
rename to proton-c/src/reactor/selectable.h
diff --git a/proton-c/src/reactor/selector.h b/proton-c/src/reactor/selector.h
new file mode 100644
index 0000000..2a1e31f
--- /dev/null
+++ b/proton-c/src/reactor/selector.h
@@ -0,0 +1,53 @@
+#ifndef PROTON_SELECTOR_H
+#define PROTON_SELECTOR_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/selectable.h>
+#include <proton/type_compat.h>
+
+#define PN_READABLE (1)
+#define PN_WRITABLE (2)
+#define PN_EXPIRED (4)
+#define PN_ERROR (8)
+
+/**
+ * A ::pn_selector_t provides a selection mechanism that allows
+ * efficient monitoring of a large number of Proton connections and
+ * listeners.
+ *
+ * External (non-Proton) sockets may also be monitored, either solely
+ * for event notification (read, write, and timer) or event
+ * notification and use with pn_io_t interfaces.
+ */
+typedef struct pn_selector_t pn_selector_t;
+
+pn_selector_t *pni_selector(void);
+void pn_selector_free(pn_selector_t *selector);
+void pn_selector_add(pn_selector_t *selector, pn_selectable_t *selectable);
+void pn_selector_update(pn_selector_t *selector, pn_selectable_t *selectable);
+void pn_selector_remove(pn_selector_t *selector, pn_selectable_t *selectable);
+size_t pn_selector_size(pn_selector_t *selector);
+int pn_selector_select(pn_selector_t *select, int timeout);
+pn_selectable_t *pn_selector_next(pn_selector_t *select, int *events);
+
+#endif /* selector.h */
diff --git a/proton-c/src/sasl/cyrus_sasl.c b/proton-c/src/sasl/cyrus_sasl.c
index dfc13d0..0d81489 100644
--- a/proton-c/src/sasl/cyrus_sasl.c
+++ b/proton-c/src/sasl/cyrus_sasl.c
@@ -19,10 +19,10 @@
  *
  */
 
-#include "config.h"
+#include "core/config.h"
+#include "core/engine-internal.h"
 #include "sasl-internal.h"
 
-#include "engine/engine-internal.h"
 
 #include <sasl/sasl.h>
 #include <pthread.h>
diff --git a/proton-c/src/sasl/none_sasl.c b/proton-c/src/sasl/none_sasl.c
index d1ee67f..0408a8f 100644
--- a/proton-c/src/sasl/none_sasl.c
+++ b/proton-c/src/sasl/none_sasl.c
@@ -21,7 +21,7 @@
 
 #include "sasl-internal.h"
 
-#include "engine/engine-internal.h"
+#include "core/engine-internal.h"
 
 static const char ANONYMOUS[] = "ANONYMOUS";
 static const char EXTERNAL[] = "EXTERNAL";
diff --git a/proton-c/src/sasl/sasl-internal.h b/proton-c/src/sasl/sasl-internal.h
index 063cd0d..2873777 100644
--- a/proton-c/src/sasl/sasl-internal.h
+++ b/proton-c/src/sasl/sasl-internal.h
@@ -22,11 +22,12 @@
 #ifndef PROTON_SASL_INTERNAL_H
 #define PROTON_SASL_INTERNAL_H 1
 
-#include "buffer.h"
+#include "core/buffer.h"
+#include "core/engine-internal.h"
+
 #include "proton/types.h"
 #include "proton/sasl.h"
 
-#include "engine/engine-internal.h"
 
 // SASL APIs used by transport code
 void pn_sasl_free(pn_transport_t *transport);
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index 47dc76c..c917d58 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -21,13 +21,14 @@
 
 #include "sasl-internal.h"
 
-#include "dispatch_actions.h"
-#include "engine/engine-internal.h"
+#include "core/autodetect.h"
+#include "core/dispatch_actions.h"
+#include "core/engine-internal.h"
+#include "core/util.h"
 #include "protocol.h"
+
 #include "proton/ssl.h"
 #include "proton/types.h"
-#include "util.h"
-#include "transport/autodetect.h"
 
 #include <assert.h>
 
diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c
index 48cb051..0d7c40b 100644
--- a/proton-c/src/ssl/openssl.c
+++ b/proton-c/src/ssl/openssl.c
@@ -19,11 +19,12 @@
  *
  */
 
+#include "platform/platform.h"
+#include "core/util.h"
+#include "core/engine-internal.h"
+
 #include <proton/ssl.h>
 #include <proton/engine.h>
-#include "engine/engine-internal.h"
-#include "platform.h"
-#include "util.h"
 
 // openssl on windows expects the user to have already included
 // winsock.h
@@ -749,7 +750,7 @@
   if (ssl->ssl && (c = SSL_get_current_cipher( ssl->ssl ))) {
     const char *v = SSL_CIPHER_get_name(c);
     if (v) {
-      snprintf( buffer, size, "%s", v );
+      pni_snprintf( buffer, size, "%s", v );
       return true;
     }
   }
@@ -765,7 +766,7 @@
   if (ssl->ssl && (c = SSL_get_current_cipher( ssl->ssl ))) {
     const char *v = SSL_CIPHER_get_version(c);
     if (v) {
-      snprintf( buffer, size, "%s", v );
+      pni_snprintf( buffer, size, "%s", v );
       return true;
     }
   }
@@ -1345,7 +1346,7 @@
         char *cursor = fingerprint;
 
         for (size_t i=0; i<len ; i++) {
-            cursor +=  snprintf((char *)cursor, fingerprint_length, "%02x", bytes[i]);
+            cursor +=  pni_snprintf((char *)cursor, fingerprint_length, "%02x", bytes[i]);
             fingerprint_length = fingerprint_length - 2;
         }
 
diff --git a/proton-c/src/windows/schannel.c b/proton-c/src/ssl/schannel.c
similarity index 99%
rename from proton-c/src/windows/schannel.c
rename to proton-c/src/ssl/schannel.c
index 0201034..420e7c5 100644
--- a/proton-c/src/windows/schannel.c
+++ b/proton-c/src/ssl/schannel.c
@@ -34,10 +34,10 @@
 
 #include <proton/ssl.h>
 #include <proton/engine.h>
-#include "engine/engine-internal.h"
-#include "platform.h"
-#include "util.h"
-#include "transport/autodetect.h"
+#include "core/engine-internal.h"
+#include "platform/platform.h"
+#include "core/util.h"
+#include "core/autodetect.h"
 
 #include <assert.h>
 
@@ -674,7 +674,7 @@
   SecPkgContext_ConnectionInfo info;
   if (QueryContextAttributes(&ssl->ctxt_handle, SECPKG_ATTR_CONNECTION_INFO, &info) == SEC_E_OK) {
     // TODO: come up with string for all permutations?
-    snprintf( buffer, size, "%x_%x:%x_%x:%x_%x",
+    pni_snprintf( buffer, size, "%x_%x:%x_%x:%x_%x",
               info.aiExch, info.dwExchStrength,
               info.aiCipher, info.dwCipherStrength,
               info.aiHash, info.dwHashStrength);
@@ -692,12 +692,12 @@
   SecPkgContext_ConnectionInfo info;
   if (QueryContextAttributes(&ssl->ctxt_handle, SECPKG_ATTR_CONNECTION_INFO, &info) == SEC_E_OK) {
     if (info.dwProtocol & (SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_SERVER))
-      snprintf(buffer, size, "%s", "TLSv1");
+      pni_snprintf(buffer, size, "%s", "TLSv1");
     // TLSV1.1 and TLSV1.2 are supported as of XP-SP3, but not defined until VS2010
     else if ((info.dwProtocol & 0x300))
-      snprintf(buffer, size, "%s", "TLSv1.1");
+      pni_snprintf(buffer, size, "%s", "TLSv1.1");
     else if ((info.dwProtocol & 0xC00))
-      snprintf(buffer, size, "%s", "TLSv1.2");
+      pni_snprintf(buffer, size, "%s", "TLSv1.2");
     else {
       ssl_log_error("unexpected protocol %x\n", info.dwProtocol);
       return false;
diff --git a/proton-c/src/ssl/ssl_stub.c b/proton-c/src/ssl/ssl_stub.c
index c836b59..db2d983 100644
--- a/proton-c/src/ssl/ssl_stub.c
+++ b/proton-c/src/ssl/ssl_stub.c
@@ -22,7 +22,7 @@
 #include <proton/ssl.h>
 #include <proton/error.h>
 #include <proton/transport.h>
-#include "engine/engine-internal.h"
+#include "core/engine-internal.h"
 
 
 /** @file
diff --git a/proton-c/src/tests/data.c b/proton-c/src/tests/data.c
index 8fb8217..10e7039 100644
--- a/proton-c/src/tests/data.c
+++ b/proton-c/src/tests/data.c
@@ -22,7 +22,7 @@
 #undef NDEBUG                   /* Make sure that assert() is enabled even in a release build. */
 
 #include <proton/codec.h>
-#include "../codec/data.h"
+#include "core/data.h"
 #include <assert.h>
 #include <stdio.h>
 
diff --git a/proton-c/src/codec/types.xml b/proton-c/src/types.xml
similarity index 100%
rename from proton-c/src/codec/types.xml
rename to proton-c/src/types.xml
diff --git a/tools/cmake/Modules/WindowsC99SymbolCheck.py b/tools/cmake/Modules/WindowsC99SymbolCheck.py
index 8e81ad9..7c2c9f2 100644
--- a/tools/cmake/Modules/WindowsC99SymbolCheck.py
+++ b/tools/cmake/Modules/WindowsC99SymbolCheck.py
@@ -53,7 +53,7 @@
         m = re.search(r'UNDEF.*\b([a-zA-Z_]*snprintf)\b', line)
         if m :
             sym = m.group(1)
-            if re.match(r'_*pn_i_v?snprintf', sym) is None :
+            if re.match(r'_*pni_v?snprintf', sym) is None :
                 raise Exception('Unsafe use of C99 violating function in  ' + objfile + ' : ' + sym)
 
 def main():