Browse Source

Merge remote-tracking branch 'origin/zmq4' into net-standard

# Conflicts:
#	.gitignore
#	src/Abc.Zebus.Tests/Abc.Zebus.Tests.csproj
#	src/Abc.Zebus/Abc.Zebus.csproj
#	src/Abc.Zebus/Transport/ZmqInboundSocket.cs
#	src/Abc.Zebus/Transport/ZmqOutboundSocket.cs
Lucas Trzesniewski 7 years ago
parent
commit
da6f602543

+ 1 - 0
.gitignore

@@ -24,6 +24,7 @@ Thumbs.db
 *.sbr
 *.ncrunchproject
 *.ncrunchsolution
+*.orig
 obj/
 [Rr]elease*/
 _ReSharper*/

+ 1 - 1
build/Abc.Zebus.nuspec

@@ -24,7 +24,7 @@
   <files>
     <file src="Abc.Zebus.dll" target="lib\net46\" />
     <file src="Abc.Zebus.pdb" target="lib\net46\" />
-    <file src=".\..\..\lib\zmq\clrzmq.dll" target="lib\net46\" />
+    <file src=".\..\..\lib\zmq\ZeroMQ.dll" target="lib\net46\" />
     <file src=".\..\..\src\Abc.Zebus\**\*.cs" target="src" />
   </files>
 </package>

BIN
lib/zmq/ZeroMQ.dll


+ 1263 - 0
lib/zmq/ZeroMQ.xml

@@ -0,0 +1,1263 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>ZeroMQ</name>
+    </assembly>
+    <members>
+        <member name="T:ZeroMQ.lib.SafeLibraryHandle">
+            <summary>
+            Safe handle for unmanaged libraries. See http://msdn.microsoft.com/msdnmag/issues/05/10/Reliability/ for more about safe handles.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.lib.UnmanagedLibrary">
+            <summary>
+            Utility class to wrap an unmanaged shared lib and be responsible for freeing it.
+            </summary>
+            <remarks>
+            This is a managed wrapper over the native LoadLibrary, GetProcAddress, and FreeLibrary calls on Windows
+            and dlopen, dlsym, and dlclose on Posix environments.
+            </remarks>
+        </member>
+        <member name="M:ZeroMQ.lib.UnmanagedLibrary.GetUnmanagedFunction``1(System.String)">
+            <summary>
+            Dynamically look up a function in the dll via kernel32!GetProcAddress or libdl!dlsym.
+            </summary>
+            <typeparam name="TDelegate">Delegate type to load</typeparam>
+            <param name="functionName">Raw name of the function in the export table.</param>
+            <returns>A delegate to the unmanaged function.</returns>
+            <exception cref="T:System.MissingMethodException">Thrown if the given function name is not found in the library.</exception>
+            <remarks>
+            GetProcAddress results are valid as long as the dll is not yet unloaded. This
+            is very very dangerous to use since you need to ensure that the dll is not unloaded
+            until after you're done with any objects implemented by the dll. For example, if you
+            get a delegate that then gets an IUnknown implemented by this dll,
+            you can not dispose this library until that IUnknown is collected. Else, you may free
+            the library and then the CLR may call release on that IUnknown and it will crash.
+            </remarks>
+        </member>
+        <member name="T:ZeroMQ.ZDevice">
+            <summary>
+            Forwards messages received by a front-end socket to a back-end socket, from which
+            they are then sent.
+            </summary>
+            <remarks>
+            The base implementation of <see cref="T:ZeroMQ.ZDevice"/> is <b>not</b> threadsafe. Do not construct
+            a device with sockets that were created in separate threads or separate contexts.
+            </remarks>
+        </member>
+        <member name="F:ZeroMQ.ZDevice.PollingInterval">
+            <summary>
+            The polling interval in milliseconds.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZDevice.Context">
+            <summary>
+            The ZContext reference, to not become finalized
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZDevice.FrontendSocket">
+            <summary>
+            The frontend socket that will normally pass messages to <see cref="F:ZeroMQ.ZDevice.BackendSocket"/>.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZDevice.BackendSocket">
+            <summary>
+            The backend socket that will normally receive messages from (and possibly send replies to) <see cref="F:ZeroMQ.ZDevice.FrontendSocket"/>.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.#ctor">
+            <summary>
+            You are using ZContext.Current!
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.#ctor(ZeroMQ.ZSocketType,ZeroMQ.ZSocketType)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZDevice"/> class.
+            You are using ZContext.Current!
+            </summary>
+            <param name="frontendSocket">
+            A <see cref="T:ZeroMQ.ZSocket"/> that will pass incoming messages to <paramref name="backendSocket"/>.
+            </param>
+            <param name="backendSocket">
+            A <see cref="T:ZeroMQ.ZSocket"/> that will receive messages from (and optionally send replies to) <paramref name="frontendSocket"/>.
+            </param>
+            <param name="mode">The <see cref="!:DeviceMode"/> for the current device.</param>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.#ctor(ZeroMQ.ZContext,ZeroMQ.ZSocketType,ZeroMQ.ZSocketType)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZDevice"/> class.
+            </summary>
+            <param name="frontendSocket">
+            A <see cref="T:ZeroMQ.ZSocket"/> that will pass incoming messages to <paramref name="backendSocket"/>.
+            </param>
+            <param name="backendSocket">
+            A <see cref="T:ZeroMQ.ZSocket"/> that will receive messages from (and optionally send replies to) <paramref name="frontendSocket"/>.
+            </param>
+            <param name="mode">The <see cref="!:DeviceMode"/> for the current device.</param>
+        </member>
+        <member name="P:ZeroMQ.ZDevice.BackendSetup">
+            <summary>
+            Gets a <see cref="T:ZeroMQ.ZSocketSetup"/> for configuring the frontend socket.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZDevice.FrontendSetup">
+            <summary>
+            Gets a <see cref="T:ZeroMQ.ZSocketSetup"/> for configuring the backend socket.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.Initialize">
+            <summary>
+            Initializes the frontend and backend sockets. Called automatically when starting the device.
+            If called multiple times, will only execute once.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.Run">
+            <summary>
+            Start the device in the current thread. Should be used by implementations of the <see cref="!:DeviceRunner.Start"/> method.
+            </summary>
+            <remarks>
+            Initializes the sockets prior to starting the device with <see cref="M:ZeroMQ.ZDevice.Initialize(ZeroMQ.ZSocketType,ZeroMQ.ZSocketType,ZeroMQ.ZError@)"/>.
+            </remarks>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.FrontendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Invoked when a message has been received by the frontend socket.
+            </summary>
+            <param name="args">A <see cref="!:SocketEventArgs"/> object containing the poll event args.</param>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.BackendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Invoked when a message has been received by the backend socket.
+            </summary>
+            <param name="args">A <see cref="!:SocketEventArgs"/> object containing the poll event args.</param>
+        </member>
+        <member name="M:ZeroMQ.ZDevice.Dispose(System.Boolean)">
+            <summary>
+            Stops the device and releases the underlying sockets. Optionally disposes of managed resources.
+            </summary>
+            <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+        </member>
+        <member name="T:ZeroMQ.Monitoring.ZMonitors">
+            <summary>
+            Defines extension methods related to monitoring for <see cref="T:ZeroMQ.ZSocket"/> instances.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitors.Monitor(ZeroMQ.ZSocket,System.String)">
+            <summary>
+            Spawns a <see cref="F:ZeroMQ.ZSocketType.PAIR"/> socket that publishes all events for
+            the specified socket over the inproc transport at the given endpoint.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitors.Monitor(ZeroMQ.ZSocket,System.String,ZeroMQ.ZError@)">
+            <summary>
+            Spawns a <see cref="F:ZeroMQ.ZSocketType.PAIR"/> socket that publishes all events for
+            the specified socket over the inproc transport at the given endpoint.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitors.Monitor(ZeroMQ.ZSocket,System.String,ZeroMQ.Monitoring.ZMonitorEvents)">
+            <summary>
+            Spawns a <see cref="F:ZeroMQ.ZSocketType.PAIR"/> socket that publishes all events for
+            the specified socket over the inproc transport at the given endpoint.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitors.Monitor(ZeroMQ.ZSocket,System.String,ZeroMQ.Monitoring.ZMonitorEvents,ZeroMQ.ZError@)">
+            <summary>
+            Spawns a <see cref="F:ZeroMQ.ZSocketType.PAIR"/> socket that publishes all events for
+            the specified socket over the inproc transport at the given endpoint.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.Monitoring.ZMonitorEvents">
+            <summary>
+            Socket transport events (for TCP and IPC sockets) that can be monitored.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.Connected">
+            <summary>
+            Triggered when a connection has been established to a remote peer.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.ConnectDelayed">
+            <summary>
+            Triggered when an immediate connection attempt is delayed and it's completion is being polled for.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.ConnectRetried">
+            <summary>
+            Triggered when a connection attempt is being handled by reconnect timer. The reconnect interval is recomputed for each attempt.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.Listening">
+            <summary>
+            Triggered when a socket is successfully bound to a an interface.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.BindFailed">
+            <summary>
+            Triggered when a socket could not bind to a given interface.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.Accepted">
+            <summary>
+            Triggered when a connection from a remote peer has been established with a socket's listen address.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.AcceptFailed">
+            <summary>
+            Triggered when a connection attempt to a socket's bound address fails.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.Closed">
+            <summary>
+            Triggered when a connection's underlying descriptor has been closed.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.CloseFailed">
+            <summary>
+            Triggered when a descriptor could not be released back to the OS.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.Disconnected">
+            <summary>
+            Triggered when the stream engine (tcp and ipc specific) detects a corrupted / broken session.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.Stopped">
+            <summary>
+            Monitoring on this socket ended.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitorEvents.AllEvents">
+            <summary>
+            Any <see cref="T:ZeroMQ.Monitoring.ZMonitorEvents"/> event, maybe readable from EventValue.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.Monitoring.ZMonitor">
+            <summary>
+            Monitors state change events on another socket within the same context.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Monitoring.ZMonitor.PollingInterval">
+            <summary>
+            The polling interval in milliseconds.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitor.Create(System.String,ZeroMQ.ZError@)">
+            <summary>
+            Create a socket with the current context and the specified socket type.
+            </summary>
+            <param name="socketType">A <see cref="T:ZeroMQ.ZSocketType"/> value for the socket.</param>
+            <returns>A <see cref="T:ZeroMQ.ZSocket"/> instance with the current context and the specified socket type.</returns>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitor.Create(ZeroMQ.ZContext,System.String,ZeroMQ.ZError@)">
+            <summary>
+            Create a socket with the current context and the specified socket type.
+            </summary>
+            <param name="socketType">A <see cref="T:ZeroMQ.ZSocketType"/> value for the socket.</param>
+            <returns>A <see cref="T:ZeroMQ.ZSocket"/> instance with the current context and the specified socket type.</returns>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.Connected">
+            <summary>
+            Occurs when a new connection is established.
+            NOTE: Do not rely on the <see cref="!:ZMonitorEventArgs.Address"/> value for
+            'Connected' messages, as the memory address contained in the message may no longer
+            point to the correct value.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.ConnectDelayed">
+            <summary>
+            Occurs when a synchronous connection attempt failed, and its completion is being polled for.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.ConnectRetried">
+            <summary>
+            Occurs when an asynchronous connect / reconnection attempt is being handled by a reconnect timer.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.Listening">
+            <summary>
+            Occurs when a socket is bound to an address and is ready to accept connections.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.BindFailed">
+            <summary>
+            Occurs when a socket could not bind to an address.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.Accepted">
+            <summary>
+            Occurs when a connection from a remote peer has been established with a socket's listen address.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.AcceptFailed">
+            <summary>
+            Occurs when a connection attempt to a socket's bound address fails.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.Closed">
+            <summary>
+            Occurs when a connection was closed.
+            NOTE: Do not rely on the <see cref="!:ZMonitorEventArgs.Address"/> value for
+            'Closed' messages, as the memory address contained in the message may no longer
+            point to the correct value.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.CloseFailed">
+            <summary>
+            Occurs when a connection couldn't be closed.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.Disconnected">
+            <summary>
+            Occurs when the stream engine (tcp and ipc specific) detects a corrupted / broken session.
+            </summary>
+        </member>
+        <member name="E:ZeroMQ.Monitoring.ZMonitor.Stopped">
+            <summary>
+            Monitoring on this socket ended.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.Monitoring.ZMonitor.Endpoint">
+            <summary>
+            Gets the endpoint to which the monitor socket is connected.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitor.Run">
+            <summary>
+            Begins monitoring for state changes, raising the appropriate events as they arrive.
+            </summary>
+            <remarks>NOTE: This is a blocking method and should be run from another thread.</remarks>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitor.Dispose(System.Boolean)">
+            <summary>
+            Releases the unmanaged resources used by the <see cref="T:ZeroMQ.Monitoring.ZMonitor"/>, and optionally disposes of the managed resources.
+            </summary>
+            <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+        </member>
+        <member name="T:ZeroMQ.Monitoring.ZMonitorEventArgs">
+            <summary>
+            A base class for the all ZmqMonitor events.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Monitoring.ZMonitorEventArgs.#ctor(ZeroMQ.Monitoring.ZMonitor,ZeroMQ.Monitoring.ZMonitorEventData)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Monitoring.ZMonitorEventArgs"/> class.
+            </summary>
+            <param name="monitor">The <see cref="T:ZeroMQ.Monitoring.ZMonitor"/> that triggered the event.</param>
+            <param name="address">The peer address.</param>
+        </member>
+        <member name="P:ZeroMQ.Monitoring.ZMonitorEventArgs.Monitor">
+            <summary>
+            Gets the monitor that triggered the event.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.Monitoring.ZMonitorFileDescriptorEventArgs">
+            <summary>
+            Provides data for <see cref="E:ZeroMQ.Monitoring.ZMonitor.Connected"/>, <see cref="E:ZeroMQ.Monitoring.ZMonitor.Listening"/>, <see cref="E:ZeroMQ.Monitoring.ZMonitor.Accepted"/>, <see cref="E:ZeroMQ.Monitoring.ZMonitor.Closed"/> and <see cref="E:ZeroMQ.Monitoring.ZMonitor.Disconnected"/> events.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.Monitoring.ZMonitorFileDescriptorEventArgs.FileDescriptor_Posix">
+            <summary>
+            Gets the monitor descriptor (Posix)
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.Monitoring.ZMonitorFileDescriptorEventArgs.FileDescriptor_Windows">
+            <summary>
+            Gets the monitor descriptor (Windows)
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.Monitoring.ZMonitorIntervalEventArgs">
+            <summary>
+            Provides data for <see cref="E:ZeroMQ.Monitoring.ZMonitor.ConnectRetried"/> event.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.Monitoring.ZMonitorIntervalEventArgs.Interval">
+            <summary>
+            Gets the computed reconnect interval.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZActor.#ctor(ZeroMQ.ZAction0,System.Object[])">
+            <summary>
+            You are using ZContext.Current!
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZActor.#ctor(System.String,ZeroMQ.ZAction0,System.Object[])">
+            <summary>
+            You are using ZContext.Current!
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZThread"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Finalize">
+            <summary>
+            Finalizes an instance of the <see cref="T:ZeroMQ.ZThread"/> class.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZThread.IsCancellationRequested">
+            <summary>
+            Gets a value indicating whether the device loop is running.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Start(System.Threading.CancellationTokenSource)">
+            <summary>
+            Start the device in the current thread.
+            </summary>
+            <exception cref="T:System.ObjectDisposedException">The <see cref="T:ZeroMQ.ZThread"/> has already been disposed.</exception>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Join">
+            <summary>
+            Blocks the calling thread until the device terminates.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Join(System.Int32)">
+            <summary>
+            Blocks the calling thread until the device terminates.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Join(System.TimeSpan)">
+            <summary>
+            Blocks the calling thread until the device terminates or the specified time elapses.
+            </summary>
+            <param name="timeout">
+            A <see cref="T:System.TimeSpan"/> set to the amount of time to wait for the device to terminate.
+            </param>
+            <returns>
+            true if the device terminated; false if the device has not terminated after
+            the amount of time specified by <paramref name="timeout"/> has elapsed.
+            </returns>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Stop">
+            <summary>
+            Stop the device in such a way that it can be restarted.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Close">
+            <summary>
+            Stop the device and safely terminate the underlying sockets.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Dispose">
+            <summary>
+            Releases all resources used by the current instance, including the frontend and backend sockets.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZThread.Dispose(System.Boolean)">
+            <summary>
+            Stops the device and releases the underlying sockets. Optionally disposes of managed resources.
+            </summary>
+            <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+        </member>
+        <member name="T:ZeroMQ.ZSocketSetup">
+            <summary>
+            Defines a fluent interface for configuring device sockets.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocketSetup.Bind(System.String)">
+            <summary>
+            Configure the socket to bind to a given endpoint. See <see cref="M:ZeroMQ.ZSocket.Bind(System.String)"/> for details.
+            </summary>
+            <param name="endpoint">A string representing the endpoint to which the socket will bind.</param>
+            <returns>The current <see cref="T:ZeroMQ.ZSocketSetup"/> object.</returns>
+        </member>
+        <member name="M:ZeroMQ.ZSocketSetup.Connect(System.String)">
+            <summary>
+            Configure the socket to connect to a given endpoint. See <see cref="M:ZeroMQ.ZSocket.Connect(System.String)"/> for details.
+            </summary>
+            <param name="endpoint">A string representing the endpoint to which the socket will connect.</param>
+            <returns>The current <see cref="T:ZeroMQ.ZSocketSetup"/> object.</returns>
+        </member>
+        <member name="M:ZeroMQ.ZSocketSetup.Subscribe(System.Byte[])">
+            <summary>
+            Configure the socket to subscribe to a specific prefix. See <see cref="M:ZeroMQ.ZSocket.Subscribe(System.Byte[])"/> for details.
+            </summary>
+            <param name="prefix">A byte array containing the prefix to which the socket will subscribe.</param>
+            <returns>The current <see cref="T:ZeroMQ.ZSocketSetup"/> object.</returns>
+        </member>
+        <member name="M:ZeroMQ.ZSocketSetup.SubscribeAll">
+            <summary>
+            Configure the socket to subscribe to all incoming messages. See <see cref="M:ZeroMQ.ZSocket.SubscribeAll"/> for details.
+            </summary>
+            <returns>The current <see cref="T:ZeroMQ.ZSocketSetup"/> object.</returns>
+        </member>
+        <member name="T:ZeroMQ.Devices.PubSubDevice">
+            <summary>
+            Device for a Publisher and Subscribers
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.PubSubDevice.FrontendType">
+            <summary>
+            The frontend <see cref="T:ZeroMQ.ZSocketType"/> for a forwarder device.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.PubSubDevice.BackendType">
+            <summary>
+            The backend <see cref="T:ZeroMQ.ZSocketType"/> for a forwarder device.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PubSubDevice.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PubSubDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PubSubDevice.#ctor(ZeroMQ.ZContext)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PubSubDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PubSubDevice.#ctor(System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PubSubDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PubSubDevice.#ctor(ZeroMQ.ZContext,System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PubSubDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PubSubDevice.FrontendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Forwards requests from the frontend socket to the backend socket.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PubSubDevice.BackendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            PubSub Forwards the Subscription messages
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.Devices.PushPullDevice">
+            <summary>
+            Queuing Push-Pull Device
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.PushPullDevice.FrontendType">
+            <summary>
+            The frontend <see cref="T:ZeroMQ.ZSocketType"/> for a streamer device.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.PushPullDevice.BackendType">
+            <summary>
+            The backend <see cref="T:ZeroMQ.ZSocketType"/> for a streamer device.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PushPullDevice.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PushPullDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PushPullDevice.#ctor(ZeroMQ.ZContext)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PushPullDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PushPullDevice.#ctor(System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PushPullDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PushPullDevice.#ctor(ZeroMQ.ZContext,System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.PushPullDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PushPullDevice.FrontendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Forwards requests from the frontend socket to the backend socket.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.PushPullDevice.BackendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Not implemented for the <see cref="T:ZeroMQ.Devices.PushPullDevice"/>.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.Devices.RouterDealerDevice">
+            <summary>
+            A Device on Routers and Dealers
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.RouterDealerDevice.FrontendType">
+            <summary>
+            The frontend <see cref="T:ZeroMQ.ZSocketType"/> for a queue device.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.RouterDealerDevice.BackendType">
+            <summary>
+            The backend <see cref="T:ZeroMQ.ZSocketType"/> for a queue device.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.RouterDealerDevice.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.RouterDealerDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.RouterDealerDevice.#ctor(ZeroMQ.ZContext)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.RouterDealerDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.RouterDealerDevice.#ctor(System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.RouterDealerDevice"/> class
+            and binds to the specified Frontend and Backend address.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.RouterDealerDevice.#ctor(ZeroMQ.ZContext,System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.RouterDealerDevice"/> class
+            and binds to the specified Frontend and Backend address.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.RouterDealerDevice.FrontendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Forwards requests from the frontend socket to the backend socket.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.RouterDealerDevice.BackendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Forwards replies from the backend socket to the frontend socket.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.Devices.StreamDealerDevice">
+            <summary>
+            The Stream to Dealer is a Device for reading 
+            and sending REPlies to TCP
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.StreamDealerDevice.FrontendType">
+            <summary>
+            The frontend <see cref="T:ZeroMQ.ZSocketType"/> for a queue device.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.Devices.StreamDealerDevice.BackendType">
+            <summary>
+            The backend <see cref="T:ZeroMQ.ZSocketType"/> for a queue device.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.StreamDealerDevice.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.StreamDealerDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.StreamDealerDevice.#ctor(ZeroMQ.ZContext)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.StreamDealerDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.StreamDealerDevice.#ctor(System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.StreamDealerDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.StreamDealerDevice.#ctor(ZeroMQ.ZContext,System.String,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.Devices.StreamDealerDevice"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.StreamDealerDevice.FrontendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Forwards requests from the frontend socket to the backend socket.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.Devices.StreamDealerDevice.BackendHandler(ZeroMQ.ZSocket,ZeroMQ.ZMessage@,ZeroMQ.ZError@)">
+            <summary>
+            Forwards replies from the backend socket to the frontend socket.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.RouterMandatory">
+            <summary>
+            Specifies <see cref="F:ZeroMQ.ZSocketType.ROUTER"/> socket behavior when
+            an unroutable message is encountered.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.RouterMandatory.Discard">
+            <summary>
+            Silently discard messages.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.RouterMandatory.Report">
+            <summary>
+            Force sending to fail with an 'EAGAIN' error code, effectively
+            enabling blocking sends.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.TcpKeepaliveBehaviour">
+            <summary>
+            Keep-alive packets behavior for a <see cref="T:ZeroMQ.ZSocket"/> connection.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.TcpKeepaliveBehaviour.Default">
+            <summary>
+            Use Operating System default behavior.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.TcpKeepaliveBehaviour.Disable">
+            <summary>
+            Disable keep-alive packets.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.TcpKeepaliveBehaviour.Enable">
+            <summary>
+            Enable keep-alive packets.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.ZContext">
+            <summary>
+            Creates <see cref="T:ZeroMQ.ZSocket"/> instances within a process boundary.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZContext.Encoding">
+            <summary>
+            Gets and protected sets the default Encoding.
+            Note: Do not set the Encoding after ZContext.Create.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZContext.#ctor">
+            <summary>
+            Create a <see cref="T:ZeroMQ.ZContext"/> instance.
+            </summary>
+            <returns><see cref="T:ZeroMQ.ZContext"/></returns>
+        </member>
+        <member name="M:ZeroMQ.ZContext.Create">
+            <summary>
+            Create a <see cref="T:ZeroMQ.ZContext"/> instance.
+            </summary>
+            <returns><see cref="T:ZeroMQ.ZContext"/></returns>
+        </member>
+        <member name="P:ZeroMQ.ZContext.ContextPtr">
+            <summary>
+            Gets a handle to the native ZeroMQ context.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZContext.ThreadPoolSize">
+            <summary>
+            Gets or sets the size of the thread pool for the current context (default = 1).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZContext.MaxSockets">
+            <summary>
+            Gets or sets the maximum number of sockets for the current context (default = 1024).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZContext.IPv6Enabled">
+            <summary>
+            Gets or sets the supported socket protocol(s) when using TCP transports. (Default = <see cref="!:ProtocolType.Ipv4Only"/>).
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZContext.Shutdown">
+            <summary>
+            Shutdown the ZeroMQ context.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZContext.Shutdown(ZeroMQ.ZError@)">
+            <summary>
+            Shutdown the ZeroMQ context.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZContext.Terminate">
+            <summary>
+            Terminate the ZeroMQ context.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZContext.Terminate(ZeroMQ.ZError@)">
+            <summary>
+            Terminate the ZeroMQ context.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.ZException">
+            <summary>
+            An exception thrown by the result of libzmq.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZException.ErrNo">
+            <summary>
+            Gets the error code returned by libzmq.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZException.ErrName">
+            <summary>
+            Gets the error code returned by libzmq.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZException.ErrText">
+            <summary>
+            Gets the error text returned by libzmq.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZException.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZException"/> class.
+            </summary>
+            <param name="errorCode">The error code returned by the ZeroMQ library call.</param>
+        </member>
+        <member name="M:ZeroMQ.ZException.#ctor(ZeroMQ.ZError)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZException"/> class.
+            </summary>
+            <param name="errorCode">The error code returned by the ZeroMQ library call.</param>
+        </member>
+        <member name="M:ZeroMQ.ZException.#ctor(ZeroMQ.ZError,System.String)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZException"/> class.
+            </summary>
+            <param name="errorCode">The error code returned by the ZeroMQ library call.</param>
+        </member>
+        <member name="M:ZeroMQ.ZException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZException"/> class.
+            </summary>
+            <param name="info"><see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+            <param name="context"><see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        </member>
+        <member name="T:ZeroMQ.ZFrame">
+            <summary>
+            A single part message, sent or received via a <see cref="T:ZeroMQ.ZSocket"/>.
+            </summary>
+        </member>
+        <member name="T:ZeroMQ.ZMessage">
+            <summary>
+            A single or multi-part message, sent or received via a <see cref="T:ZeroMQ.ZSocket"/>.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZMessage.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZMessage"/> class.
+            Creates an empty message.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZMessage.#ctor(System.Collections.Generic.IEnumerable{ZeroMQ.ZFrame})">
+            <summary>
+            Initializes a new instance of the <see cref="T:ZeroMQ.ZMessage"/> class.
+            Creates a message that contains the given <see cref="T:ZeroMQ.ZFrame"/> objects.
+            </summary>
+            <param name="frames">A collection of <see cref="T:ZeroMQ.ZFrame"/> objects to be stored by this <see cref="T:ZeroMQ.ZMessage"/>.</param>
+            <exception cref="T:System.ArgumentNullException"><paramref name="frames"/> is null.</exception>
+        </member>
+        <member name="M:ZeroMQ.ZMessage.RemoveAt(System.Int32)">
+            <summary>
+            Removes ZFrames. Note: Disposes the ZFrame.
+            </summary>
+            <returns>The <see cref="T:ZeroMQ.ZFrame"/>.</returns>
+        </member>
+        <member name="M:ZeroMQ.ZMessage.RemoveAt(System.Int32,System.Boolean)">
+            <summary>
+            Removes ZFrames.
+            </summary>
+            <returns>The <see cref="T:ZeroMQ.ZFrame"/>.</returns>
+            <param name="dispose">If set to <c>false</c>, do not dispose the ZFrame.</param>
+        </member>
+        <member name="T:ZeroMQ.ZSocket">
+            <summary>
+            Sends and receives messages, single frames and byte frames across ZeroMQ.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Create(ZeroMQ.ZContext,ZeroMQ.ZSocketType)">
+            <summary>
+            Create a <see cref="T:ZeroMQ.ZSocket"/> instance.
+            </summary>
+            <returns><see cref="T:ZeroMQ.ZSocket"/></returns>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Create(ZeroMQ.ZContext,ZeroMQ.ZSocketType,ZeroMQ.ZError@)">
+            <summary>
+            Create a <see cref="T:ZeroMQ.ZSocket"/> instance.
+            </summary>
+            <returns><see cref="T:ZeroMQ.ZSocket"/></returns>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.#ctor(ZeroMQ.ZSocketType)">
+            <summary>
+            Create a <see cref="T:ZeroMQ.ZSocket"/> instance.
+            You are using ZContext.Current!
+            </summary>
+            <returns><see cref="T:ZeroMQ.ZSocket"/></returns>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.#ctor(ZeroMQ.ZContext,ZeroMQ.ZSocketType)">
+            <summary>
+            Create a <see cref="T:ZeroMQ.ZSocket"/> instance.
+            </summary>
+            <returns><see cref="T:ZeroMQ.ZSocket"/></returns>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Finalize">
+            <summary>
+            Finalizes an instance of the <see cref="T:ZeroMQ.ZSocket"/> class.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Dispose(System.Boolean)">
+            <summary>
+            Releases the unmanaged resources used by the <see cref="T:ZeroMQ.ZSocket"/>, and optionally disposes of the managed resources.
+            </summary>
+            <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Close">
+            <summary>
+            Close the current socket.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Close(ZeroMQ.ZError@)">
+            <summary>
+            Close the current socket.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.SocketType">
+            <summary>
+            Gets the <see cref="T:ZeroMQ.ZSocketType"/> value for the current socket.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Bind(System.String)">
+            <summary>
+            Bind the specified endpoint.
+            </summary>
+            <param name="endpoint">A string consisting of a transport and an address, formatted as <c><em>transport</em>://<em>address</em></c>.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Bind(System.String,ZeroMQ.ZError@)">
+            <summary>
+            Bind the specified endpoint.
+            </summary>
+            <param name="endpoint">A string consisting of a transport and an address, formatted as <c><em>transport</em>://<em>address</em></c>.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Unbind(System.String)">
+            <summary>
+            Unbind the specified endpoint.
+            </summary>
+            <param name="endpoint">A string consisting of a transport and an address, formatted as <c><em>transport</em>://<em>address</em></c>.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Unbind(System.String,ZeroMQ.ZError@)">
+            <summary>
+            Unbind the specified endpoint.
+            </summary>
+            <param name="endpoint">A string consisting of a transport and an address, formatted as <c><em>transport</em>://<em>address</em></c>.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Connect(System.String)">
+            <summary>
+            Connect the specified endpoint.
+            </summary>
+            <param name="endpoint">A string consisting of a transport and an address, formatted as <c><em>transport</em>://<em>address</em></c>.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Connect(System.String,ZeroMQ.ZError@)">
+            <summary>
+            Connect the specified endpoint.
+            </summary>
+            <param name="endpoint">A string consisting of a transport and an address, formatted as <c><em>transport</em>://<em>address</em></c>.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Disconnect(System.String)">
+            <summary>
+            Disconnect the specified endpoint.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Disconnect(System.String,ZeroMQ.ZError@)">
+            <summary>
+            Disconnect the specified endpoint.
+            </summary>
+            <param name="endpoint">A string consisting of a transport and an address, formatted as <c><em>transport</em>://<em>address</em></c>.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.ReceiveBytes(System.Byte[],System.Int32,System.Int32)">
+            <summary>
+            Receives HARD bytes into a new byte[n]. Please don't use ReceiveBytes, use instead ReceiveFrame.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.ReceiveBytes(System.Byte[],System.Int32,System.Int32,ZeroMQ.ZSocketFlags,ZeroMQ.ZError@)">
+            <summary>
+            Receives HARD bytes into a new byte[n]. Please don't use ReceiveBytes, use instead ReceiveFrame.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.SendBytes(System.Byte[],System.Int32,System.Int32)">
+            <summary>
+            Sends HARD bytes from a byte[n]. Please don't use SendBytes, use instead SendFrame.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.SendBytes(System.Byte[],System.Int32,System.Int32,ZeroMQ.ZSocketFlags,ZeroMQ.ZError@)">
+            <summary>
+            Sends HARD bytes from a byte[n]. Please don't use SendBytes, use instead SendFrame.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Send(System.Byte[],System.Int32,System.Int32)">
+            <summary>
+            Sends HARD bytes from a byte[n]. Please don't use SendBytes, use instead SendFrame.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Send(System.Byte[],System.Int32,System.Int32,ZeroMQ.ZSocketFlags,ZeroMQ.ZError@)">
+            <summary>
+            Sends HARD bytes from a byte[n]. Please don't use SendBytes, use instead SendFrame.
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.SubscribeAll">
+            <summary>
+            Subscribe to all messages.
+            </summary>
+            <remarks>
+            Only applies to <see cref="F:ZeroMQ.ZSocketType.SUB"/> and <see cref="F:ZeroMQ.ZSocketType.XSUB"/> sockets.
+            </remarks>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Subscribe(System.Byte[])">
+            <summary>
+            Subscribe to messages that begin with a specified prefix.
+            </summary>
+            <remarks>
+            Only applies to <see cref="F:ZeroMQ.ZSocketType.SUB"/> and <see cref="F:ZeroMQ.ZSocketType.XSUB"/> sockets.
+            </remarks>
+            <param name="prefix">Prefix for subscribed messages.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Subscribe(System.String)">
+            <summary>
+            Subscribe to messages that begin with a specified prefix.
+            </summary>
+            <remarks>
+            Only applies to <see cref="F:ZeroMQ.ZSocketType.SUB"/> and <see cref="F:ZeroMQ.ZSocketType.XSUB"/> sockets.
+            </remarks>
+            <param name="prefix">Prefix for subscribed messages.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.UnsubscribeAll">
+            <summary>
+            Unsubscribe from all messages.
+            </summary>
+            <remarks>
+            Only applies to <see cref="F:ZeroMQ.ZSocketType.SUB"/> and <see cref="F:ZeroMQ.ZSocketType.XSUB"/> sockets.
+            </remarks>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Unsubscribe(System.Byte[])">
+            <summary>
+            Unsubscribe from messages that begin with a specified prefix.
+            </summary>
+            <remarks>
+            Only applies to <see cref="F:ZeroMQ.ZSocketType.SUB"/> and <see cref="F:ZeroMQ.ZSocketType.XSUB"/> sockets.
+            </remarks>
+            <param name="prefix">Prefix for subscribed messages.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.Unsubscribe(System.String)">
+            <summary>
+            Unsubscribe from messages that begin with a specified prefix.
+            </summary>
+            <remarks>
+            Only applies to <see cref="F:ZeroMQ.ZSocketType.SUB"/> and <see cref="F:ZeroMQ.ZSocketType.XSUB"/> sockets.
+            </remarks>
+            <param name="prefix">Prefix for subscribed messages.</param>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.ReceiveMore">
+            <summary>
+            Gets a value indicating whether the multi-part message currently being read has more message parts to follow.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.Affinity">
+            <summary>
+            Gets or sets the I/O thread affinity for newly created connections on this socket.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.Backlog">
+            <summary>
+            Gets or sets the maximum length of the queue of outstanding peer connections. (Default = 100 connections).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.Identity">
+            <summary>
+            Gets or sets the Identity.
+            </summary>
+            <value>Identity as byte[]</value>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.IdentityString">
+            <summary>
+            Gets or sets the Identity.
+            Note: The string contains chars like \0 (null terminator,
+            which are NOT printed (in Console.WriteLine)!
+            </summary>
+            <value>Identity as string</value>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.Linger">
+            <summary>
+            Gets or sets the linger period for socket shutdown. (Default = <see cref="F:System.TimeSpan.MaxValue"/>, infinite).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.MaxMessageSize">
+            <summary>
+            Gets or sets the maximum size for inbound messages (bytes). (Default = -1, no limit).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.MulticastHops">
+            <summary>
+            Gets or sets the time-to-live field in every multicast packet sent from this socket (network hops). (Default = 1 hop).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.MulticastRate">
+            <summary>
+            Gets or sets the maximum send or receive data rate for multicast transports (kbps). (Default = 100 kbps).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.ReceiveBufferSize">
+            <summary>
+            Gets or sets the underlying kernel receive buffer size for the current socket (bytes). (Default = 0, OS default).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.ReceiveHighWatermark">
+            <summary>
+            Gets or sets the high water mark for inbound messages (number of messages). (Default = 0, no limit).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.ReceiveTimeout">
+            <summary>
+            Gets or sets the timeout for receive operations. (Default = <see cref="F:System.TimeSpan.MaxValue"/>, infinite).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.ReconnectInterval">
+            <summary>
+            Gets or sets the initial reconnection interval. (Default = 100 milliseconds).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.ReconnectIntervalMax">
+            <summary>
+            Gets or sets the maximum reconnection interval. (Default = 0, only use <see cref="P:ZeroMQ.ZSocket.ReconnectInterval"/>).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.MulticastRecoveryInterval">
+            <summary>
+            Gets or sets the recovery interval for multicast transports. (Default = 10 seconds).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.SendBufferSize">
+            <summary>
+            Gets or sets the underlying kernel transmit buffer size for the current socket (bytes). (Default = 0, OS default).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.SendHighWatermark">
+            <summary>
+            Gets or sets the high water mark for outbound messages (number of messages). (Default = 0, no limit).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.SendTimeout">
+            <summary>
+            Gets or sets the timeout for send operations. (Default = <see cref="F:System.TimeSpan.MaxValue"/>, infinite).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.TcpKeepAlive">
+            <summary>
+            Gets or sets the override value for the SO_KEEPALIVE TCP socket option. (where supported by OS). (Default = -1, OS default).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.TcpKeepAliveCount">
+            <summary>
+            Gets or sets the override value for the 'TCP_KEEPCNT' socket option (where supported by OS). (Default = -1, OS default).
+            The default value of '-1' means to skip any overrides and leave it to OS default.
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.TcpKeepAliveIdle">
+            <summary>
+            Gets or sets the override value for the TCP_KEEPCNT (or TCP_KEEPALIVE on some OS). (Default = -1, OS default).
+            </summary>
+        </member>
+        <member name="P:ZeroMQ.ZSocket.TcpKeepAliveInterval">
+            <summary>
+            Gets or sets the override value for the TCP_KEEPINTVL socket option (where supported by OS). (Default = -1, OS default).
+            </summary>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.AddTcpAcceptFilter(System.String)">
+            <summary>
+            Add a filter that will be applied for each new TCP transport connection on a listening socket.
+            Example: "127.0.0.1", "mail.ru/24", "::1", "::1/128", "3ffe:1::", "3ffe:1::/56"
+            </summary>
+            <seealso cref="M:ZeroMQ.ZSocket.ClearTcpAcceptFilter"/>
+            <remarks>
+            If no filters are applied, then TCP transport allows connections from any IP.
+            If at least one filter is applied then new connection source IP should be matched.
+            </remarks>
+            <param name="filter">IPV6 or IPV4 CIDR filter.</param>
+        </member>
+        <member name="M:ZeroMQ.ZSocket.ClearTcpAcceptFilter">
+            <summary>
+            Reset all TCP filters assigned by <see cref="M:ZeroMQ.ZSocket.AddTcpAcceptFilter(System.String)"/>
+            and allow TCP transport to accept connections from any IP.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketFlags.None">
+            <summary>
+            No socket flags are specified.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketFlags.DontWait">
+            <summary>
+            The operation should be performed in non-blocking mode.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketFlags.More">
+            <summary>
+            The message being sent is a multi-part message, and that further message parts are to follow.
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.PAIR">
+            <summary>
+            Exclusive Pair
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.PUB">
+            <summary>
+            Publish
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.SUB">
+            <summary>
+            Subscribe
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.REQ">
+            <summary>
+            Request
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.REP">
+            <summary>
+            Reply / Response
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.DEALER">
+            <summary>
+            Dealer
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.ROUTER">
+            <summary>
+            Router
+            </summary>
+            <remarks>
+            When receiving messages a <see cref="F:ZeroMQ.ZSocketType.ROUTER"/> socket shall prepend a message
+            part containing the identity of the originating peer to the message before
+            passing it to the application. When sending messages a ZMQ_ROUTER socket shall remove
+            the first part of the message and use it to determine the identity of the peer the message
+            shall be routed to. If the peer does not exist anymore the message shall be silently discarded.
+            </remarks>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.PULL">
+            <summary>
+            Pull
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.PUSH">
+            <summary>
+            Push
+            </summary>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.XPUB">
+            <summary>
+            XPublisher
+            </summary>
+            <remarks>
+            Subscription message is a byte '1' (for subscriptions) or byte '0' (for unsubscriptions) followed by the subscription body.
+            </remarks>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.XSUB">
+            <summary>
+            XSubscriber
+            </summary>
+            <remarks>
+            Subscription message is a byte '1' (for subscriptions) or byte '0' (for unsubscriptions) followed by the subscription body.
+            </remarks>
+        </member>
+        <member name="F:ZeroMQ.ZSocketType.STREAM">
+            <summary>
+            Stream
+            </summary>
+            <remarks>
+            </remarks>
+        </member>
+        <member name="T:ZeroMQ.ZSymbol">
+            <summary>
+            TODO merge this with its sole subclass, ZError
+            </summary>
+        </member>
+    </members>
+</doc>

BIN
lib/zmq/clrzmq.dll


+ 2 - 2
src/Abc.Zebus.Tests/Abc.Zebus.Tests.csproj

@@ -45,8 +45,8 @@
   </ItemGroup>
 
   <ItemGroup>
-    <Reference Include="clrzmq">
-      <HintPath>..\..\lib\zmq\clrzmq.dll</HintPath>
+    <Reference Include="ZeroMQ">
+      <HintPath>..\..\lib\zmq\ZeroMQ.dll</HintPath>
     </Reference>
     <Reference Include="VersionedLibrary_2">
       <HintPath>.\VersionedLibrary_2.dll</HintPath>

+ 4 - 0
src/Abc.Zebus.Tests/Core/BusPerformanceTests.cs

@@ -7,6 +7,7 @@ using Abc.Zebus.Dispatch;
 using Abc.Zebus.Scan;
 using Abc.Zebus.Testing;
 using Abc.Zebus.Testing.Measurements;
+using Abc.Zebus.Transport;
 using Abc.Zebus.Util;
 using NUnit.Framework;
 using ProtoBuf;
@@ -52,6 +53,7 @@ namespace Abc.Zebus.Tests.Core
             // 02/10/2013 VAN: 60k/s
             // 25/11/2013 CAO: 66k/s
             // 10/12/2013 CAO: 72k/s
+            // 23/11/2017 CAO: 176k/s
 
             const int messageCount = 1000 * 1000;
 
@@ -160,6 +162,7 @@ namespace Abc.Zebus.Tests.Core
             return new BusFactory()
                 .WithPeerId("Abc.Zebus.Perf.Sender.*")
                 .WithConfiguration(new BusConfiguration(false, _directoryEndPoint), "Dev")
+                .ConfigureContainer(x => x.For<ZmqSocketOptions>().Use(new ZmqSocketOptions { SendHighWaterMark = 100000, SendTimeout = 10.Second() }))
                 .CreateAndStartBus();
         }
 
@@ -169,6 +172,7 @@ namespace Abc.Zebus.Tests.Core
                 .WithPeerId("Abc.Zebus.Perf.Receiver.*")
                 .WithConfiguration(new BusConfiguration(isPersistent, _directoryEndPoint), "Dev")
                 .WithHandlers(typeof(PerfHandler))
+                .ConfigureContainer(x => x.For<ZmqSocketOptions>().Use(new ZmqSocketOptions { ReceiveHighWaterMark = 100000 }))
                 .CreateAndStartBus();
         }
 

+ 0 - 21
src/Abc.Zebus.Tests/Messages/FakeCommandWithTimestamp.cs

@@ -1,21 +0,0 @@
-using System;
-using ProtoBuf;
-
-namespace Abc.Zebus.Tests.Messages
-{
-    [ProtoContract]
-    public class FakeCommandWithTimestamp : ICommand
-    {
-        [ProtoMember(1, IsRequired = true)]
-        public readonly TimeSpan Timestamp;
-
-        FakeCommandWithTimestamp()
-        {
-        }
-
-        public FakeCommandWithTimestamp(TimeSpan timestamp)
-        {
-            Timestamp = timestamp;
-        }
-    }
-}

+ 13 - 11
src/Abc.Zebus.Tests/Transport/ZmqTests.cs

@@ -1,5 +1,4 @@
 using System;
-using Abc.Zebus.Transport;
 using Abc.Zebus.Util;
 using NUnit.Framework;
 using ZeroMQ;
@@ -17,48 +16,51 @@ namespace Abc.Zebus.Tests.Transport
             var message = new byte[50];
             var receiveBuffer = new byte[100];
 
-            using (var context = ZmqContext.Create())
+            using (var context = ZContext.Create())
             {
                 var sendEndpoint = $"tcp://localhost:{TcpUtil.GetRandomUnusedPort()}";
                 var receiveEndpoint = sendEndpoint.Replace("localhost", "*");
 
-                var receiver = context.CreateSocket(SocketType.PULL);
+                var receiver = new ZSocket(context, ZSocketType.PULL);
                 receiver.ReceiveHighWatermark = 10;
+                receiver.ReceiveTimeout = 200.Milliseconds();
                 receiver.Bind(receiveEndpoint);
 
-                var sender = context.CreateSocket(SocketType.PUSH);
+                var sender = new ZSocket(context, ZSocketType.PUSH);
                 sender.SendHighWatermark = 10;
                 sender.Connect(sendEndpoint);
 
                 for (var i = 0; i < 10; ++i)
                 {
-                    var sendStatus = sender.Send(message);
+                    var sendStatus = sender.Send(message, 0, message.Length);
                     Console.WriteLine(sendStatus);
                 }
                 for (var i = 0; i < 10; ++i)
                 {
-                    var bytes = receiver.Receive(receiveBuffer, 200.Milliseconds());
+                    var bytes = receiver.ReceiveBytes(receiveBuffer, 0, receiveBuffer.Length);
                     Console.WriteLine(bytes);
                 }
 
-                receiver.Unbind(receiveEndpoint);
+                receiver.Unbind(receiver.LastEndpoint);
 
                 for (var i = 0; i < 10; ++i)
                 {
-                    var sendStatus = sender.Send(message);
+                    var sendStatus = sender.Send(message, 0, message.Length);
                     Console.WriteLine(sendStatus);
                 }
 
-                sender.Disconnect(sendEndpoint);
+                sender.Disconnect(sender.LastEndpoint);
+                sender.SendTimeout = 1000.Milliseconds();
                 sender.Connect(sendEndpoint);
 
-                var oneMoreSend = sender.SendWithTimeout(message, message.Length, 1000.Milliseconds());
+                var oneMoreSend = sender.Send(message, 0, message.Length);
                 Console.WriteLine(oneMoreSend);
 
+                receiver.ReceiveTimeout = 2000.Milliseconds();
                 receiver.Bind(receiveEndpoint);
                 
                 var receivedMessageCount = 0;
-                while (receiver.Receive(receiveBuffer, 2000.Milliseconds()) != -1)
+                while (receiver.ReceiveBytes(receiveBuffer, 0, receiveBuffer.Length) != -1)
                 {
                     ++receivedMessageCount;
                 }

+ 24 - 56
src/Abc.Zebus.Tests/Transport/ZmqTransportTests.cs

@@ -1,5 +1,4 @@
 using Abc.Zebus.Directory;
-using Abc.Zebus.Serialization;
 using Abc.Zebus.Testing;
 using Abc.Zebus.Testing.Extensions;
 using Abc.Zebus.Tests.Messages;
@@ -37,8 +36,7 @@ namespace Abc.Zebus.Tests.Transport
             {
                 try
                 {
-                    if (transport.IsListening)
-                        transport.Stop(true);
+                    transport.Stop(true);
                 }
                 catch (Exception)
                 {
@@ -487,37 +485,40 @@ namespace Abc.Zebus.Tests.Transport
         {
             var receivedMessages = new List<TransportMessage>();
 
-            var receivingPeerId = new PeerId("Abc.Receiving.0");
-            var stopwatch = Stopwatch.StartNew();
-            var receivingTransport = CreateAndStartZmqTransport(onMessageReceived: receivedMessages.Add, peerId: receivingPeerId.ToString(), 
-                                                                transportFactory: conf => new CapturingIsListeningTimeZmqTransport(conf, stopwatch));
-            var receivingPeer = new Peer(receivingPeerId, receivingTransport.InboundEndPoint);
-            var messageSerializer = new MessageSerializer();
-            bool receivedWhileNotListening = false;
-            receivingTransport.MessageReceived += message =>
-            {
-                var cmdWithTimetamp = (FakeCommandWithTimestamp)messageSerializer.Deserialize(message.MessageTypeId, message.Content);
+            var receivingTransport = CreateAndStartZmqTransport(onMessageReceived: receivedMessages.Add);
 
-                if (cmdWithTimetamp.Timestamp > ((CapturingIsListeningTimeZmqTransport)receivingTransport).IsListeningSwitchTimestamp)
-                    receivedWhileNotListening = true;
-            };
+            var receivingPeer = new Peer(receivingTransport.PeerId, receivingTransport.InboundEndPoint);
+            bool receivedWhileNotListening = false;
+            receivingTransport.MessageReceived += message => receivedWhileNotListening |= !receivingTransport.IsListening;
 
             var sendingTransport = CreateAndStartZmqTransport();
             var shouldSendMessages = true;
-            var sendTask = Task.Factory.StartNew(() =>
+
+            Task.Factory.StartNew(() =>
             {
+                var sendCount = 0;
+                var spinWait = new SpinWait();
+                // ReSharper disable once AccessToModifiedClosure
                 while (shouldSendMessages)
-                    sendingTransport.Send(new FakeCommandWithTimestamp(stopwatch.Elapsed).ToTransportMessage(), new[] { receivingPeer });
-
+                {
+                    sendingTransport.Send(new FakeCommand(0).ToTransportMessage(), new[] { receivingPeer });
+                    sendCount++;
+                    spinWait.SpinOnce();
+                }
+                Console.WriteLine($"{sendCount} messages sent");
             });
-            Wait.Until(() => sendTask.Status == TaskStatus.Running, 10.Seconds());
+
             Wait.Until(() => receivedMessages.Count > 1, 10.Seconds());
-            
+            Console.WriteLine("Message received");
+
             receivingTransport.Stop();
+            Console.WriteLine("Receiving transport stopped");
 
             receivedWhileNotListening.ShouldBeFalse();
             shouldSendMessages = false;
+
             sendingTransport.Stop();
+            Console.WriteLine("Sending transport stopped");
         }
 
         [Test]
@@ -590,8 +591,7 @@ namespace Abc.Zebus.Tests.Transport
             }
         }
 
-        private ZmqTransport CreateAndStartZmqTransport(string endPoint = null, Action<TransportMessage> onMessageReceived = null, string peerId = null,
-                                                        string environment = _environment, Func<IZmqTransportConfiguration, ZmqTransport> transportFactory = null)
+        private ZmqTransport CreateAndStartZmqTransport(string endPoint = null, Action<TransportMessage> onMessageReceived = null, string peerId = null, string environment = _environment)
         {
             var configurationMock = new Mock<IZmqTransportConfiguration>();
             configurationMock.SetupGet(x => x.InboundEndPoint).Returns(endPoint);
@@ -600,7 +600,7 @@ namespace Abc.Zebus.Tests.Transport
             if (peerId == null)
                 peerId = "Abc.Testing." + _transports.Count;
 
-            var transport = transportFactory == null ? new ZmqTransport(configurationMock.Object, new ZmqSocketOptions(), new DefaultZmqOutboundSocketErrorHandler()) : transportFactory(configurationMock.Object);
+            var transport = new ZmqTransport(configurationMock.Object, new ZmqSocketOptions(), new DefaultZmqOutboundSocketErrorHandler());
             transport.SetLogId(_transports.Count);
 
             transport.SocketOptions.SendTimeout = 10.Milliseconds();
@@ -614,37 +614,5 @@ namespace Abc.Zebus.Tests.Transport
             transport.Start();
             return transport;
         }
-
-        private class CapturingIsListeningTimeZmqTransport : ZmqTransport
-        {
-            private readonly Stopwatch _stopwatch;
-            private readonly object _lock = new object();
-            public TimeSpan IsListeningSwitchTimestamp { get; private set; }
-
-            public override bool IsListening
-            {
-                get
-                {
-                    lock (_lock)
-                        return base.IsListening;
-                }
-                internal set
-                {
-                    lock (_lock)
-                    {
-                        base.IsListening = value;
-                        if (!value)
-                            IsListeningSwitchTimestamp = _stopwatch.Elapsed;
-                    }
-                }
-            }
-
-
-            public CapturingIsListeningTimeZmqTransport(IZmqTransportConfiguration configuration, Stopwatch stopwatch) : base(configuration, new ZmqSocketOptions(), new DefaultZmqOutboundSocketErrorHandler())
-            {
-                _stopwatch = stopwatch;
-                IsListeningSwitchTimestamp = TimeSpan.MaxValue;
-            }
-        }
     }
 }

+ 6 - 7
src/Abc.Zebus/Abc.Zebus.csproj

@@ -31,8 +31,8 @@
   </ItemGroup>
 
   <ItemGroup>
-    <Reference Include="clrzmq">
-      <HintPath>..\..\lib\zmq\clrzmq.dll</HintPath>
+    <Reference Include="ZeroMQ">
+      <HintPath>..\..\lib\zmq\ZeroMQ.dll</HintPath>
     </Reference>
     <Reference Include="Microsoft.CSharp" />
   </ItemGroup>
@@ -45,11 +45,10 @@
       <Link>Properties\SharedVersionInfo.cs</Link>
     </Compile>
 
-    <None Include="Transport\libzmq-4.0.5-v140-mt" />
-    <EmbeddedResource Include="Transport\libzmq-x64-0.0.0.0.dll" />
-    <EmbeddedResource Include="Transport\libzmq-x86-0.0.0.0.dll" />
-    <EmbeddedResource Include="Transport\libzmq-x64-0.0.0.0.pdb" />
-    <EmbeddedResource Include="Transport\libzmq-x86-0.0.0.0.pdb" />
+    <EmbeddedResource Include="Transport\libsodium-x64.dll" />
+    <EmbeddedResource Include="Transport\libsodium-x86.dll" />
+    <EmbeddedResource Include="Transport\libzmq-x64.dll" />
+    <EmbeddedResource Include="Transport\libzmq-x86.dll" />
   </ItemGroup>
 
 </Project>

+ 1 - 1
src/Abc.Zebus/Transport/ZmqEndPoint.cs

@@ -49,7 +49,7 @@ namespace Abc.Zebus.Transport
         /// that was used for another environment. If we were to share a port between two environments, clients from the
         /// second environment might try to send us messages that we would have to discard
         /// </remarks>>
-        public void SelectRandomPort(PeerId peerId, string environment)
+        public void SelectRandomPort(string environment)
         {
             _logger.InfoFormat("Selecting random port for {0}", environment);
 

+ 51 - 26
src/Abc.Zebus/Transport/ZmqInboundSocket.cs

@@ -1,6 +1,6 @@
 using System;
+using System.Text;
 using Abc.Zebus.Serialization.Protobuf;
-using Abc.Zebus.Util;
 using log4net;
 using ZeroMQ;
 
@@ -9,17 +9,17 @@ namespace Abc.Zebus.Transport
     internal class ZmqInboundSocket : IDisposable
     {
         private readonly ILog _logger = LogManager.GetLogger(typeof(ZmqInboundSocket));
-        private readonly ZmqContext _context;
+        private readonly ZContext _context;
         private readonly PeerId _peerId;
         private readonly ZmqEndPoint _originalEndpoint;
         private readonly ZmqSocketOptions _options;
         private readonly string _environment;
         private byte[] _readBuffer = new byte[0];
-        private ZmqSocket _socket;
-        private ZmqEndPoint _endPoint;
-        private TimeSpan _lastReceiveTimeout = TimeSpan.MinValue;
+        private ZSocket _socket;
+        private ZmqEndPoint _socketEndPoint;
+        private TimeSpan _lastReceiveTimeout;
 
-        public ZmqInboundSocket(ZmqContext context, PeerId peerId, ZmqEndPoint originalEndpoint, ZmqSocketOptions options, string environment)
+        public ZmqInboundSocket(ZContext context, PeerId peerId, ZmqEndPoint originalEndpoint, ZmqSocketOptions options, string environment)
         {
             _context = context;
             _peerId = peerId;
@@ -32,16 +32,16 @@ namespace Abc.Zebus.Transport
         {
             _socket = CreateSocket();
 
-            _endPoint = new ZmqEndPoint(_originalEndpoint.Value); 
-            if (_endPoint.HasRandomPort)
-                _endPoint.SelectRandomPort(_peerId, _environment);
+            var endPoint = new ZmqEndPoint(_originalEndpoint.Value); 
+            if (endPoint.HasRandomPort)
+                endPoint.SelectRandomPort(_environment);
 
-            _socket.Bind(_endPoint.Value);
+            _socket.Bind(endPoint.Value);
 
-            var endPointWithIp = new ZmqEndPoint(_socket.LastEndpoint);
-            _logger.InfoFormat("Socket bound, Inbound EndPoint: {0}", endPointWithIp.Value);
+            _socketEndPoint = new ZmqEndPoint(_socket.LastEndpoint);
+            _logger.InfoFormat("Socket bound, Inbound EndPoint: {0}", _socketEndPoint.Value);
 
-            return endPointWithIp;
+            return _socketEndPoint;
         }
 
         public void Dispose()
@@ -51,37 +51,62 @@ namespace Abc.Zebus.Transport
 
         public CodedInputStream Receive(TimeSpan? timeout = null)
         {
-            var effectiveTimeout = timeout ?? _options.ReadTimeout;
-            if (effectiveTimeout != _lastReceiveTimeout)
+            var receiveTimeout = timeout ?? _options.ReadTimeout;
+            if (receiveTimeout != _lastReceiveTimeout)
             {
-                _socket.ReceiveTimeout = effectiveTimeout; // This stuff allocates
-                _lastReceiveTimeout = effectiveTimeout;
+                _socket.ReceiveTimeout = receiveTimeout;
+                _lastReceiveTimeout = receiveTimeout;
             }
-            
-            _readBuffer = _socket.Receive(_readBuffer, TimeSpan.MaxValue, out var size);
 
+            var frame = _socket.ReceiveFrame(out var error);
+            if (error == null)
+                return GetStream(frame);
+
+            // EAGAIN: Non-blocking mode was requested and no messages are available at the moment.
+
+            if (error.Number == ZError.EAGAIN)
+                return null;
+
+            throw new ZException(error);
+        }
+
+        private CodedInputStream GetStream(ZFrame frame)
+        {
+            var size = (int)frame.Length;
             if (size <= 0)
                 return null;
 
+            if (_readBuffer.Length < size)
+                _readBuffer = new byte[size];
+
+            frame.Read(_readBuffer, 0, size);
+
             return new CodedInputStream(_readBuffer, 0, size);
         }
 
-        private ZmqSocket CreateSocket()
+        private ZSocket CreateSocket()
         {
-            var socket = _context.CreateSocket(SocketType.PULL);
-            socket.ReceiveHighWatermark = _options.ReceiveHighWaterMark;
-            socket.SetPeerId(_peerId);
+            var socket = new ZSocket(_context, ZSocketType.PULL)
+            {
+                ReceiveHighWatermark = _options.ReceiveHighWaterMark,
+                ReceiveTimeout = _options.ReadTimeout,
+                Identity = Encoding.ASCII.GetBytes(_peerId.ToString()),
+            };
+
+            _lastReceiveTimeout = _options.ReadTimeout;
 
             return socket;
         }
 
         public void Disconnect()
         {
-            if (_endPoint == null)
+            var endpoint = _socket.LastEndpoint;
+            if (endpoint == null)
                 return;
 
-            _logger.InfoFormat("Unbinding socket, Inbound Endpoint: {0}", _endPoint.Value);
-            _socket.Disconnect(_endPoint.Value);
+            _logger.InfoFormat("Unbinding socket, Inbound Endpoint: {0}", endpoint);
+            if (!_socket.Unbind(endpoint, out var error))
+                _logger.WarnFormat("Socket error, Inbound Endpoint: {0}, Erro: {1}", endpoint, error);
         }
     }
 }

+ 35 - 11
src/Abc.Zebus/Transport/ZmqOutboundSocket.cs

@@ -1,5 +1,7 @@
 using System;
 using System.Diagnostics;
+using System.Text;
+using System.Threading;
 using log4net;
 using ZeroMQ;
 
@@ -9,15 +11,15 @@ namespace Abc.Zebus.Transport
     {
         private readonly ILog _logger = LogManager.GetLogger(typeof(ZmqOutboundSocket));
         private readonly Stopwatch _closedStateStopwatch = new Stopwatch();
-        private readonly ZmqContext _context;
+        private readonly ZContext _context;
         private readonly ZmqSocketOptions _options;
         private readonly IZmqOutboundSocketErrorHandler _errorHandler;
-        private ZmqSocket _socket;
+        private ZSocket _socket;
         private int _failedSendCount;
         private bool _isInClosedState;
         private TimeSpan _closedStateDuration;
 
-        public ZmqOutboundSocket(ZmqContext context, PeerId peerId, string endPoint, ZmqSocketOptions options, IZmqOutboundSocketErrorHandler errorHandler)
+        public ZmqOutboundSocket(ZContext context, PeerId peerId, string endPoint, ZmqSocketOptions options, IZmqOutboundSocketErrorHandler errorHandler)
         {
             _context = context;
             _options = options;
@@ -37,12 +39,15 @@ namespace Abc.Zebus.Transport
 
             try
             {
-                _socket = _context.CreateSocket(SocketType.PUSH);
-                _socket.SendHighWatermark = _options.SendHighWaterMark;
-                _socket.TcpKeepalive = TcpKeepaliveBehaviour.Enable;
-                _socket.TcpKeepaliveIdle = 30;
-                _socket.TcpKeepaliveIntvl = 3;
-                _socket.SetPeerId(PeerId);
+                _socket = new ZSocket(_context, ZSocketType.PUSH)
+                {
+                    SendHighWatermark = _options.SendHighWaterMark,
+                    SendTimeout = _options.SendTimeout,
+                    TcpKeepAlive = TcpKeepaliveBehaviour.Enable,
+                    TcpKeepAliveIdle = 30,
+                    TcpKeepAliveInterval = 3,
+                    Identity = Encoding.ASCII.GetBytes(PeerId.ToString()),
+                };
 
                 _socket.Connect(EndPoint);
 
@@ -96,13 +101,32 @@ namespace Abc.Zebus.Transport
             if (!CanSendOrConnect(message))
                 return;
 
-            if (_socket.SendWithTimeout(buffer, length, _options.SendTimeout) >= 0)
+            var stopwatch = Stopwatch.StartNew();
+            var spinWait = new SpinWait();
+
+            ZError error;
+
+            while (true)
             {
+                if (_socket.SendBytes(buffer, 0, length, ZSocketFlags.None, out error))
+                {
                 _failedSendCount = 0;
                 return;
             }
 
-            _logger.ErrorFormat("Unable to send message, destination peer: {0}, MessageTypeId: {1}, MessageId: {2}", PeerId, message.MessageTypeId, message.Id);
+                // EAGAIN: Non-blocking mode was requested and the message cannot be sent at the moment.
+
+                var shouldRetry = error.Number == ZError.EAGAIN;
+                if (shouldRetry && stopwatch.Elapsed < _options.SendTimeout)
+                {
+                    spinWait.SpinOnce();
+                    continue;
+                }
+
+                break;
+            }
+
+            _logger.ErrorFormat("Unable to send message, destination peer: {0}, MessageTypeId: {1}, MessageId: {2}, Error: {3}", PeerId, message.MessageTypeId, message.Id, error);
             _errorHandler.OnSendFailed(PeerId, EndPoint, message.MessageTypeId, message.Id);
 
             if (_failedSendCount >= _options.SendRetriesBeforeSwitchingToClosedState)

+ 9 - 34
src/Abc.Zebus/Transport/ZmqTransport.cs

@@ -21,7 +21,7 @@ namespace Abc.Zebus.Transport
         private ConcurrentDictionary<PeerId, ZmqOutboundSocket> _outboundSockets;
         private BlockingCollection<OutboundSocketAction> _outboundSocketActions;
         private BlockingCollection<PendingDisconnect> _pendingDisconnects;
-        private ZmqContext _context;
+        private ZContext _context;
         private Thread _inboundThread;
         private Thread _outboundThread;
         private Thread _disconnectThread;
@@ -33,29 +33,8 @@ namespace Abc.Zebus.Transport
 
         static ZmqTransport()
         {
-            ExtractLibZmq("x64");
-            ExtractLibZmq("x86");
-        }
-
-        static void ExtractLibZmq(string platform)
-        {
-            var resourceName = $"libzmq-{platform}-0.0.0.0.dll";
-
-            var libraryPath = PathUtil.InBaseDirectory(resourceName);
-            if (File.Exists(libraryPath))
-                return;
-
-            var transportType = typeof(ZmqTransport);
-            using (var resourceStream = transportType.Assembly.GetManifestResourceStream(transportType, resourceName))
-            {
-                if (resourceStream == null)
-                    throw new Exception("Unable to find libzmq in the embedded resources.");
-
-                using (var libraryFileStream = new FileStream(libraryPath, FileMode.OpenOrCreate, FileAccess.Write))
-                {
-                    resourceStream.CopyTo(libraryFileStream);
-                }
-            }
+            ZmqUtil.ExtractLibZmq("x64", "amd64");
+            ZmqUtil.ExtractLibZmq("x86", "i386");
         }
 
         public ZmqTransport(IZmqTransportConfiguration configuration, ZmqSocketOptions socketOptions, IZmqOutboundSocketErrorHandler errorHandler)
@@ -68,11 +47,7 @@ namespace Abc.Zebus.Transport
 
         public event Action<TransportMessage> MessageReceived;
 
-        public virtual bool IsListening
-        {
-            get { return _isListening; }
-            internal set { _isListening = value; }
-        }
+        public bool IsListening => _isListening;
 
         public string InboundEndPoint => _realInboundEndPoint != null ? _realInboundEndPoint.Value : _configuredInboundEndPoint.Value;
 
@@ -114,12 +89,12 @@ namespace Abc.Zebus.Transport
 
         public void Start()
         {
-            IsListening = true;
+            _isListening = true;
 
             _outboundSockets = new ConcurrentDictionary<PeerId, ZmqOutboundSocket>();
             _outboundSocketActions = new BlockingCollection<OutboundSocketAction>();
             _pendingDisconnects = new BlockingCollection<PendingDisconnect>();
-            _context = ZmqContext.Create();
+            _context = new ZContext();
 
             var startSequenceState = new InboundProcStartSequenceState();
 
@@ -157,7 +132,7 @@ namespace Abc.Zebus.Transport
             if (!_outboundThread.Join(30.Seconds()))
                 _logger.Error("Unable to terminate outbound thread");
 
-            IsListening = false;
+            _isListening = false;
             if (!_inboundThread.Join(30.Seconds()))
                 _logger.Error("Unable to terminate inbound thread");
 
@@ -216,7 +191,7 @@ namespace Abc.Zebus.Transport
 
             using (inboundSocket)
             {
-                while (IsListening)
+                while (_isListening)
                 {
                     var inputStream = inboundSocket.Receive();
                     if (inputStream == null)
@@ -283,7 +258,7 @@ namespace Abc.Zebus.Transport
                     return;
                 }
 
-                if (IsListening)
+                if (_isListening)
                     MessageReceived?.Invoke(transportMessage);
             }
             catch (Exception ex)

+ 22 - 20
src/Abc.Zebus/Transport/ZmqUtil.cs

@@ -1,34 +1,36 @@
 using System;
-using System.Diagnostics;
-using System.Text;
-using System.Threading;
-using ZeroMQ;
+using System.IO;
+using Abc.Zebus.Util;
 
 namespace Abc.Zebus.Transport
 {
     public static class ZmqUtil
     {
-        public static void SetPeerId(this ZmqSocket socket, PeerId peerId)
+        internal static void ExtractLibZmq(string platform, string directory)
         {
-            socket.Identity = Encoding.ASCII.GetBytes(peerId.ToString());
-        }
+            var directoryPath = PathUtil.InBaseDirectory(directory);
+            if (!System.IO.Directory.Exists(directoryPath))
+                System.IO.Directory.CreateDirectory(directoryPath);
 
-        public static int SendWithTimeout(this ZmqSocket socket, byte[] buffer, int length, TimeSpan timeout)
-        {
-            var stopwatch = Stopwatch.StartNew();
-            var spinWait = new SpinWait();
-            int result;
-            do
+            foreach (var libraryName in new[] { "libzmq", "libsodium" })
             {
-                result = socket.Send(buffer, length, SocketFlags.DontWait);
-                if (socket.SendStatus != SendStatus.TryAgain)
-                    break;
+                var libraryPath = PathUtil.InBaseDirectory(directory, $"{libraryName}.dll");
+                if (File.Exists(libraryPath))
+                    continue;
 
-                spinWait.SpinOnce();
-            }
-            while (stopwatch.Elapsed <= timeout);
+                var resourceName = $"{libraryName}-{platform}.dll";
+                var transportType = typeof(ZmqTransport);
+                using (var resourceStream = transportType.Assembly.GetManifestResourceStream(transportType, resourceName))
+                {
+                    if (resourceStream == null)
+                        throw new Exception($"Unable to find {libraryName} in the embedded resources.");
 
-            return result;
+                    using (var libraryFileStream = new FileStream(libraryPath, FileMode.OpenOrCreate, FileAccess.Write))
+                    {
+                        resourceStream.CopyTo(libraryFileStream);
+                    }
+                }
+            }
         }
     }
 }

BIN
src/Abc.Zebus/Transport/libsodium-x64.dll


BIN
src/Abc.Zebus/Transport/libsodium-x86.dll


+ 0 - 0
src/Abc.Zebus/Transport/libzmq-4.0.5-v140-mt


BIN
src/Abc.Zebus/Transport/libzmq-x64-0.0.0.0.dll


BIN
src/Abc.Zebus/Transport/libzmq-x64-0.0.0.0.pdb


BIN
src/Abc.Zebus/Transport/libzmq-x64.dll


BIN
src/Abc.Zebus/Transport/libzmq-x86-0.0.0.0.dll


BIN
src/Abc.Zebus/Transport/libzmq-x86-0.0.0.0.pdb


BIN
src/Abc.Zebus/Transport/libzmq-x86.dll