private void OnAcceptted(ListeningContext context)
        {
            if (context.AcceptSocket == null || context.AcceptSocket.RemoteEndPoint == null)
            {
                // Canceled due to shutdown.
                return;
            }

#if !API_SIGNATURE_TEST
            MsgPackRpcServerProtocolsTrace.TraceEvent(
                MsgPackRpcServerProtocolsTrace.EndAccept,
                "Accept. {{ \"Socket\" : 0x{0:X}, \"RemoteEndPoint\" : \"{1}\", \"LocalEndPoint\" : \"{2}\" }}",
                ServerTransport.GetHandle(context.AcceptSocket),
                ServerTransport.GetRemoteEndPoint(context.AcceptSocket, context),
                ServerTransport.GetLocalEndPoint(context.AcceptSocket)
                );
#endif

            Contract.Assert(context.BytesTransferred == 0, context.BytesTransferred.ToString());

            var transport = this.GetTransport(context.AcceptSocket);
            context.AcceptSocket = null;
            this.Accept(context);
            transport.Receive(this.GetRequestContext(transport));
        }
Example #2
0
        /// <summary>
        ///		Unpack request/notification message array header.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        internal bool UnpackRequestHeader(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            if (context.RootUnpacker == null)
            {
                context.UnpackingBuffer = new ByteArraySegmentStream(context.ReceivedData);
                context.RootUnpacker    = Unpacker.Create(context.UnpackingBuffer, false);
                Interlocked.Increment(ref this._processing);
                context.RenewSessionId();
                if (this._manager.Server.Configuration.ReceiveTimeout != null)
                {
                    context.Timeout += this.OnReceiveTimeout;
                    context.StartWatchTimeout(this._manager.Server.Configuration.ReceiveTimeout.Value);
                }

                if (MsgPackRpcServerProtocolsTrace.ShouldTrace(MsgPackRpcServerProtocolsTrace.NewSession))
                {
                    MsgPackRpcServerProtocolsTrace.TraceEvent(
                        MsgPackRpcServerProtocolsTrace.NewSession,
                        "New session is created. {{ \"SessionID\" : {0} }}",
                        context.SessionId
                        );
                }
            }

            if (!context.ReadFromRootUnpacker())
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.NeedRequestHeader,
                    "Array header is needed. {{ \"SessionID\" : {0} }}",
                    context.SessionId
                    );
                return(false);
            }

            if (!context.RootUnpacker.IsArrayHeader)
            {
                this.HandleDeserializationError(context, "Invalid request/notify message stream. Message must be array.", () => context.UnpackingBuffer.ToArray());
                return(true);
            }

            if (context.RootUnpacker.ItemsCount != 3 && context.RootUnpacker.ItemsCount != 4)
            {
                this.HandleDeserializationError(
                    context,
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "Invalid request/notify message stream. Message must be valid size array. Actual size is {0}.",
                        context.RootUnpacker.ItemsCount
                        ),
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }

            context.HeaderUnpacker = context.RootUnpacker.ReadSubtree();
            context.NextProcess    = UnpackMessageType;
            return(context.NextProcess(context));
        }
        private void OnCompleted(object sender, SocketAsyncEventArgs e)
        {
            var socket = sender as Socket;

            if (!this.HandleSocketError(socket, e))
            {
                return;
            }

            switch (e.LastOperation)
            {
            case SocketAsyncOperation.Accept:
            {
                var context = e as ListeningContext;
                Contract.Assert(context != null);
                this.OnAcceptted(context);
                break;
            }

            default:
            {
#if !API_SIGNATURE_TEST
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.UnexpectedLastOperation,
                    "Unexpected operation. {{ \"Socket\" : 0x{0:X}, \"RemoteEndPoint\" : \"{1}\", \"LocalEndPoint\" : \"{2}\", \"LastOperation\" : \"{3}\" }}",
                    ServerTransport.GetHandle(socket),
                    ServerTransport.GetRemoteEndPoint(socket, e),
                    ServerTransport.GetLocalEndPoint(socket),
                    e.LastOperation
                    );
#endif
                break;
            }
            }
        }
Example #4
0
        /// <summary>
        ///		Unpack Message ID part on request message.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        private bool UnpackMessageId(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            if (!context.ReadFromHeaderUnpacker())
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.NeedMessageId,
                    "Message ID is needed. {{ \"SessionID\" : {0} }}",
                    context.SessionId
                    );
                return(false);
            }

            try
            {
                context.MessageId = unchecked (( int )context.HeaderUnpacker.LastReadData.AsUInt32());
            }
            catch (InvalidOperationException)
            {
                this.HandleDeserializationError(
                    context,
                    "Invalid request message stream. ID must be UInt32 compatible integer.",
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }

            context.NextProcess = this.UnpackMethodName;
            return(context.NextProcess(context));
        }
Example #5
0
        /// <summary>
        ///		Unpack array elements of Arguments part on request/notification message.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        private bool UnpackArguments(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            while (context.UnpackedArgumentsCount < context.ArgumentsCount)
            {
                if (!context.ReadFromArgumentsBufferUnpacker())
                {
                    MsgPackRpcServerProtocolsTrace.TraceEvent(
                        MsgPackRpcServerProtocolsTrace.NeedArgumentsElement,
                        "Arguments array element is needed. {0}/{1}  {{ \"SessionID\" : {2} }}",
                        context.UnpackedArgumentsCount,
                        context.ArgumentsCount,
                        context.SessionId
                        );
                    return(false);
                }

                context.ArgumentsBufferPacker.Pack(context.ArgumentsBufferUnpacker.LastReadData);
                context.UnpackedArgumentsCount++;
            }

            context.ArgumentsBuffer.Position = 0;
            context.ArgumentsUnpacker        = Unpacker.Create(context.ArgumentsBuffer, false);
            context.NextProcess = this.Dispatch;
            return(context.NextProcess(context));
        }
Example #6
0
        /// <summary>
        ///		Unpack Method Name part on request/notification message.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        private bool UnpackMethodName(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            if (!context.ReadFromHeaderUnpacker())
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.NeedMethodName,
                    "Method Name is needed. {{ \"SessionID\" : {0} }}",
                    context.SessionId
                    );
                return(false);
            }

            try
            {
                context.MethodName = context.HeaderUnpacker.LastReadData.AsString();
            }
            catch (InvalidOperationException)
            {
                this.HandleDeserializationError(
                    context,
                    "Invalid request/notify message stream. Method name must be UTF-8 string.",
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }

            context.NextProcess = this.UnpackArgumentsHeader;
            return(context.NextProcess(context));
        }
Example #7
0
        /// <summary>
        ///		Unpack Message Type part on request/notification message.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        private bool UnpackMessageType(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            if (!context.ReadFromHeaderUnpacker())
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.NeedMessageType,
                    "Message Type is needed. {{ \"SessionID\" : {0} }}",
                    context.SessionId
                    );
                return(false);
            }

            int numericType;

            try
            {
                numericType = context.HeaderUnpacker.LastReadData.AsInt32();
            }
            catch (InvalidOperationException)
            {
                this.HandleDeserializationError(context, "Invalid request/notify message stream. Message Type must be Int32 compatible integer.", () => context.UnpackingBuffer.ToArray());
                return(true);
            }

            MessageType type = ( MessageType )numericType;

            context.MessageType = type;

            switch (type)
            {
            case MessageType.Request:
            {
                context.NextProcess = this.UnpackMessageId;
                break;
            }

            case MessageType.Notification:
            {
                context.NextProcess = this.UnpackMethodName;
                break;
            }

            default:
            {
                this.HandleDeserializationError(
                    context,
                    String.Format(CultureInfo.CurrentCulture, "Unknown message type '{0:x8}'", numericType),
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }
            }

            return(context.NextProcess(context));
        }
        /// <summary>
        ///		Handles the socket error as server error.
        /// </summary>
        /// <param name="socket">The <see cref="Socket"/> caused error.</param>
        /// <param name="context">The <see cref="SocketAsyncEventArgs"/> instance containing the asynchronous operation data.</param>
        /// <returns>
        ///		<c>true</c>, if the error can be ignore, it is in shutdown which is initiated by another thread, for example; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="socket"/> is <c>null</c>.
        ///		Or <paramref name="context"/> is <c>null</c>.
        /// </exception>
        /// <remarks>
        ///		When this method returns <c>false</c>, <see cref="RpcServer.ServerError"/> event will be also ocurred.
        /// </remarks>
        protected internal bool HandleSocketError(Socket socket, SocketAsyncEventArgs context)
        {
            if (socket == null)
            {
                throw new ArgumentNullException("socket");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            Contract.EndContractBlock();

            bool?isError = context.SocketError.IsError();

            if (isError == null)
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.IgnoreableError,
                    "Ignoreable error. {{ \"Socket\" : 0x{0:X}, \"RemoteEndpoint\" : \"{1}\", \"LocalEndpoint\" : \"{2}\", \"LastOperation\" : \"{3}\", \"SocketError\" : \"{4}\", \"ErrorCode\" : 0x{5:X} }}",
                    ServerTransport.GetHandle(socket),
                    ServerTransport.GetRemoteEndPoint(socket, context),
                    ServerTransport.GetLocalEndPoint(socket),
                    context.LastOperation,
                    context.SocketError,
                    ( int )context.SocketError
                    );
                return(true);
            }
            else if (isError.GetValueOrDefault())
            {
                var errorDetail =
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "Socket error. {{ \"Socket\" : 0x{0:X}, \"RemoteEndpoint\" : \"{1}\", \"LocalEndpoint\" : \"{2}\", \"LastOperation\" : \"{3}\", \"SocketError\" : \"{4}\", \"ErrorCode\" : 0x{5:X} }}",
                        ServerTransport.GetHandle(socket),
                        ServerTransport.GetRemoteEndPoint(socket, context),
                        ServerTransport.GetLocalEndPoint(socket),
                        context.LastOperation,
                        context.SocketError,
                        ( int )context.SocketError
                        );
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.SocketError,
                    errorDetail
                    );

                this.RaiseServerError(new RpcTransportException(context.SocketError.ToRpcError(), "Socket error.", errorDetail, new SocketException(( int )context.SocketError)));
                return(false);
            }

            return(true);
        }
 /// <summary>
 ///		Releases unmanaged and - optionally - managed resources
 /// </summary>
 /// <param name="disposing">
 ///		<c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.
 ///	</param>
 private void DisposeOnce(bool disposing)
 {
     if (Interlocked.CompareExchange(ref this._isDisposed, 1, 0) == 0)
     {
         MsgPackRpcServerProtocolsTrace.TraceEvent(
             MsgPackRpcServerProtocolsTrace.DisposeManager,
             "Dispose. {{ \"Manager\" : \"{0}\" }}",
             this
             );
         this.Dispose(disposing);
     }
 }
Example #10
0
        /// <summary>
        ///		Unpack array header of Arguments part on request/notification message.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        private bool UnpackArgumentsHeader(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            if (!context.ReadFromHeaderUnpacker())
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.NeedArgumentsArrayHeader,
                    "Arguments array header is needed. {{ \"SessionID\" : {0} }}",
                    context.SessionId
                    );
                return(false);
            }

            if (!context.HeaderUnpacker.IsArrayHeader)
            {
                this.HandleDeserializationError(
                    context,
                    "Invalid request/notify message stream. Arguments must be array.",
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }

            // TODO: Avoid actual unpacking to improve performance.
            context.ArgumentsBufferUnpacker = context.HeaderUnpacker.ReadSubtree();

            if (Int32.MaxValue < context.ArgumentsBufferUnpacker.ItemsCount)
            {
                this.HandleDeserializationError(
                    context,
                    RpcError.MessageTooLargeError,
                    "Too many arguments.",
                    context.ArgumentsBufferUnpacker.ItemsCount.ToString("#,0", CultureInfo.CurrentCulture),
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }

            context.ArgumentsCount        = unchecked (( int )(context.ArgumentsBufferUnpacker.ItemsCount));
            context.ArgumentsBufferPacker = Packer.Create(context.ArgumentsBuffer, false);
            context.ArgumentsBufferPacker.PackArrayHeader(context.ArgumentsCount);
            context.UnpackedArgumentsCount = 0;
            context.NextProcess            = this.UnpackArguments;
            return(context.NextProcess(context));
        }
 /// <summary>
 ///		Initiates server shutdown process.
 /// </summary>
 /// <returns>
 ///		If shutdown process is initiated, then <c>true</c>.
 ///		If shutdown is already initiated or completed, then <c>false</c>.
 /// </returns>
 /// <remarks>
 ///		To observe shutdown completion, subscribe <see cref="ShutdownCompleted"/> event.
 /// </remarks>
 public bool BeginShutdown()
 {
     if (Interlocked.Exchange(ref this._isInShutdown, 1) == 0)
     {
         MsgPackRpcServerProtocolsTrace.TraceEvent(
             MsgPackRpcServerProtocolsTrace.BeginShutdownManager,
             "Begin shutdown. {{ \"Manager\" : \"{0}\" }}",
             this
             );
         this.BeginShutdownCore();
         return(true);
     }
     else
     {
         return(false);
     }
 }
        /// <summary>
        /// When overridden in derived class, releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                this.IsActive = false;
                base.Dispose(disposing);
                this._listeningSocket.Close();
            }
            finally
            {
                if (this.Configuration.UdpListenerThreadExitTimeout == null)
                {
                    this._listeningThread.Join();
                }
                else
                {
                    if (!this._listeningThread.Join(this.Configuration.UdpListenerThreadExitTimeout.Value))
                    {
                        this._listeningThread.Interrupt();
                        if (!this._listeningThread.Join(this.Configuration.UdpListenerThreadExitTimeout.Value))
                        {
                            // Suspend is needed to capture stack trace.
#pragma warning disable 0612,0618
                            this._listeningThread.Suspend();
#pragma warning restore 0612,0618

#if !API_SIGNATURE_TEST
                            MsgPackRpcServerProtocolsTrace.TraceEvent(
                                MsgPackRpcServerProtocolsTrace.FailedToStopUdpServerManagerListenerThread,
                                "Failed to stop the UDP server manager listener thread. Stack trace: {0}{1}",
                                Environment.NewLine,
                                new StackTrace(this._listeningThread, true)
                                );
#endif
                            // Suspend was needed to capture stack trace.
#pragma warning disable 0612,0618
                            this._listeningThread.Resume();
#pragma warning restore 0612,0618
                        }
                    }
                }
            }
        }
        /// <summary>
        ///		Raises <see cref="ShutdownCompleted"/> event.
        /// </summary>
        /// <param name="e">The <see cref="MsgPack.Rpc.Protocols.ShutdownCompletedEventArgs"/> instance containing the event data.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="e"/> is <c>null</c>.
        /// </exception>
        protected virtual void OnShutdownCompleted(ShutdownCompletedEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            Contract.EndContractBlock();

            MsgPackRpcServerProtocolsTrace.TraceEvent(
                MsgPackRpcServerProtocolsTrace.ManagerShutdownCompleted,
                "Manager shutdown is completed. {{ \"Manager\" : \"{0}\" }}",
                this
                );

            var handler = Interlocked.CompareExchange(ref this._shutdownCompleted, null, null);

            if (handler != null)
            {
                handler(this, e);
            }
        }
        private void Accept(ListeningContext context)
        {
            // Ensure buffers are cleared to avoid unepxected data feeding on Accept
            context.SetBuffer(null, 0, 0);
            context.BufferList = null;

            try
            {
                if (this.IsInShutdown)
                {
                    return;
                }

#if !API_SIGNATURE_TEST
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.BeginAccept,
                    "Wait for connection. {{ \"Socket\" : 0x{0:X}, \"LocalEndPoint\" : \"{1}\" }}",
                    this._listeningSocket.Handle,
                    this._listeningSocket.LocalEndPoint
                    );
#endif

                if (!this._listeningSocket.AcceptAsync(context))
                {
                    // Avoid recursive acceptance and the subsequent request delay.
                    // Task is bit heavy here.
                    ThreadPool.QueueUserWorkItem(_ => this.OnAcceptted(context));
                }
            }
            catch (ObjectDisposedException)
            {
                if (!this.IsDisposed)
                {
                    throw;
                }
            }
        }
        /// <summary>
        ///		Initializes a new instance of the <see cref="UdpServerTransportManager"/> class.
        /// </summary>
        /// <param name="server">The server which will host this instance.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="server"/> is <c>null</c>.
        /// </exception>
        public UdpServerTransportManager(RpcServer server)
            : base(server)
        {
#if !API_SIGNATURE_TEST
            base.SetTransportPool(server.Configuration.UdpTransportPoolProvider(() => new UdpServerTransport(this), server.Configuration.CreateTransportPoolConfiguration()));
#endif

            var addressFamily   = (server.Configuration.PreferIPv4 || !Socket.OSSupportsIPv6) ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6;
            var bindingEndPoint = this.Configuration.BindingEndPoint;
#if !API_SIGNATURE_TEST
            if (bindingEndPoint == null)
            {
                bindingEndPoint =
                    new IPEndPoint(
#if MONO
                        this.Configuration.PreferIPv4 && Socket.SupportsIPv4
#else
                        this.Configuration.PreferIPv4 && Socket.OSSupportsIPv4
#endif
                                                ? IPAddress.Any
                                                : IPAddress.IPv6Any,
                        57319                         // arbitrary number
                        );
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.DefaultEndPoint,
                    "Default end point is selected. {{ \"EndPoint\" : \"{0}\", \"AddressFamily\" : {1}, \"PreferIPv4\" : {2}, \"OSSupportsIPv6\" : {3} }}",
                    bindingEndPoint,
                    addressFamily,
                    server.Configuration.PreferIPv4,
                    Socket.OSSupportsIPv6
                    );
            }
#endif
            this._bindingEndPoint = bindingEndPoint;

            this._listeningEndPoint = new IPEndPoint(addressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, 0);

            this._listeningSocket =
                new Socket(
                    this._bindingEndPoint.AddressFamily,
                    SocketType.Dgram,
                    ProtocolType.Udp
                    );

            if (!this.Configuration.PreferIPv4 &&
                Environment.OSVersion.Platform == PlatformID.Win32NT &&
                Environment.OSVersion.Version.Major >= 6
#if MONO
                && Socket.SupportsIPv6
#else
                && Socket.OSSupportsIPv6
#endif
                )
            {
                // Listen both of IPv4 and IPv6
                this._listeningSocket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
            }

            this._listeningSocket.Bind(this._bindingEndPoint);
            this._listeningThread = new Thread(this.PollArrival)
            {
                IsBackground = true, Name = "UdpListeningThread#" + this.GetHashCode()
            };
            this.IsActive = true;
            this._listeningThread.Start();
        }
        private void PollArrival()
        {
#if !API_SIGNATURE_TEST
            MsgPackRpcServerProtocolsTrace.TraceEvent(
                MsgPackRpcServerProtocolsTrace.StartListen,
                "Start listen. {{ \"Socket\" : 0x{0:X}, \"EndPoint\" : \"{1}\", \"ListenBackLog\" : {2} }}",
                this._listeningSocket.Handle,
                this._bindingEndPoint,
                this.Server.Configuration.ListenBackLog
                );
#endif
            try
            {
                var transport = this.GetTransport(this._listeningSocket);

                while (this.IsActive)
                {
                    ServerRequestContext context;
                    try
                    {
                        // CancellationToken is useless...
                        context = this.GetRequestContext(transport);
                    }
                    catch (ThreadInterruptedException)
                    {
                        this.ReturnTransport(transport);

                        if (this.IsActive)
                        {
                            throw;
                        }
                        else
                        {
                            return;
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        this.ReturnTransport(transport);

                        if (this.IsActive)
                        {
                            throw;
                        }
                        else
                        {
                            return;
                        }
                    }

                    context.RemoteEndPoint = this._listeningEndPoint;

                    if (!this.IsActive)
                    {
                        this.ReturnRequestContext(context);
                        this.ReturnTransport(transport);
                        return;
                    }

                    transport.Receive(context);
                }
            }
#if !API_SIGNATURE_TEST
            catch (Exception ex)
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.UdpServerManagerListenerThreadCrash,
                    "The exception has been occurred in the UDP server manager listener thread. {0}",
                    ex
                    );
            }
#else
            catch { }
#endif
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TcpServerTransportManager"/> class.
        /// </summary>
        /// <param name="server">The server which will host this instance.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="server"/> is <c>null</c>.
        /// </exception>
        public TcpServerTransportManager(RpcServer server)
            : base(server)
        {
#if !API_SIGNATURE_TEST
            base.SetTransportPool(server.Configuration.TcpTransportPoolProvider(() => new TcpServerTransport(this), server.Configuration.CreateTransportPoolConfiguration()));
#endif

            this._listeningContextPool = server.Configuration.ListeningContextPoolProvider(() => new ListeningContext(), server.Configuration.CreateListeningContextPoolConfiguration());
            var addressFamily   = (server.Configuration.PreferIPv4 || !Socket.OSSupportsIPv6) ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6;
            var bindingEndPoint = this.Configuration.BindingEndPoint;
#if !API_SIGNATURE_TEST
            if (bindingEndPoint == null)
            {
                bindingEndPoint =
                    new IPEndPoint(
#if MONO
                        this.Configuration.PreferIPv4 && Socket.SupportsIPv4
#else
                        this.Configuration.PreferIPv4 && Socket.OSSupportsIPv4
#endif
                                                ? IPAddress.Any
                                                : IPAddress.IPv6Any,
                        57129                         // arbitrary number
                        );
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.DefaultEndPoint,
                    "Default end point is selected. {{ \"EndPoint\" : \"{0}\", \"AddressFamily\" : {1}, \"PreferIPv4\" : {2}, \"OSSupportsIPv6\" : {3} }}",
                    bindingEndPoint,
                    addressFamily,
                    server.Configuration.PreferIPv4,
                    Socket.OSSupportsIPv6
                    );
            }
#endif
            this._listeningSocket =
                new Socket(
                    bindingEndPoint.AddressFamily,
                    SocketType.Stream,
                    ProtocolType.Tcp
                    );

#if !MONO
            if (!this.Configuration.PreferIPv4 &&
                Environment.OSVersion.Platform == PlatformID.Win32NT &&
                Environment.OSVersion.Version.Major >= 6 &&
                Socket.OSSupportsIPv6
                )
            {
                // Listen both of IPv4 and IPv6
                this._listeningSocket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
            }
#endif // !MONO

            this._listeningSocket.Bind(bindingEndPoint);
            this._listeningSocket.Listen(server.Configuration.ListenBackLog);

#if !API_SIGNATURE_TEST
            MsgPackRpcServerProtocolsTrace.TraceEvent(
                MsgPackRpcServerProtocolsTrace.StartListen,
                "Start listen. {{ \"Socket\" : 0x{0:X}, \"EndPoint\" : \"{1}\", \"ListenBackLog\" : {2} }}",
                this._listeningSocket.Handle,
                bindingEndPoint,
                server.Configuration.ListenBackLog
                );
#endif

            this.StartAccept();
        }