public SocketConnection(Socket socket, EndPoint localEndPoint)
        {
#pragma warning disable 168 // unused local variable
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            this.closeState = STATE_OPEN;

            try { this.LocalEndPoint = socket.LocalEndPoint; }
            catch (ArgumentException getLocalEndPointError) // Mono B_ug he AddressFamily InterNetworkV6 is not valid for the System.Net.IPEndPoint end point, use InterNetwork instead.
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine($"An error occurred while trying to get '{nameof(socket.LocalEndPoint)}' property of established connection." + getLocalEndPointError.Unwrap());
#endif
                this.LocalEndPoint = localEndPoint;
            }
            try { this.RemoteEndPoint = socket.RemoteEndPoint; }
            catch (ArgumentException getRemoteEndPointError) // Mono B_ug he AddressFamily InterNetworkV6 is not valid for the System.Net.IPEndPoint end point, use InterNetwork instead.
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine($"An error occurred while trying to get '{nameof(socket.RemoteEndPoint)}' property of established connection." + getRemoteEndPointError.Unwrap());
#endif
                if (UnixSocketTransport.IsUnixEndPoint(localEndPoint))
                {
                    this.RemoteEndPoint = localEndPoint;
                }
                else
                {
                    this.RemoteEndPoint = null;
                }
            }

            this.socket = socket;

            this.networkStream = new NetworkStream(socket, true);
            this.socketEvents  = new SocketAsyncEventArgs[EVENT_COUNT];
            for (var i = 0; i < this.socketEvents.Length; i++)
            {
                var socketEvent = new SocketAsyncEventArgs();
                socketEvent.Completed += this.OnSocketOperationCompleted;
                this.socketEvents[i]   = socketEvent;
            }
#pragma warning restore 168
        }
        /// <inheritdoc />
        internal override async Task <NetworkConnection> ConnectAsync(Uri address, WebSocketListenerOptions options, CancellationToken cancellation)
        {
            if (address == null)
            {
                throw new ArgumentNullException(nameof(address));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var remoteEndPoint = this.GetRemoteEndPoint(address);
            var protocolType   = this.GetProtocolType(address, remoteEndPoint);
            // prepare socket
            var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Stream, protocolType);

            this.SetupClientSocket(socket, remoteEndPoint);
            try
            {
                // prepare connection
                var socketConnectedCondition = new AsyncConditionSource
                {
                    ContinueOnCapturedContext = false
                };
                var socketAsyncEventArgs = new SocketAsyncEventArgs
                {
                    RemoteEndPoint = remoteEndPoint,
                    UserToken      = socketConnectedCondition
                };

                // connect
                socketAsyncEventArgs.Completed += (_, e) => ((AsyncConditionSource)e.UserToken).Set();

                // interrupt connection when cancellation token is set
                var connectInterruptRegistration = cancellation.CanBeCanceled ?
                                                   cancellation.Register(s => ((AsyncConditionSource)s).Interrupt(new OperationCanceledException()), socketConnectedCondition) :
                                                   default(CancellationTokenRegistration);
                using (connectInterruptRegistration)
                {
                    if (socket.ConnectAsync(socketAsyncEventArgs) == false)
                    {
                        socketConnectedCondition.Set();
                    }

                    await socketConnectedCondition;
                }
                cancellation.ThrowIfCancellationRequested();

                // check connection result
                if (socketAsyncEventArgs.ConnectByNameError != null)
                {
                    throw socketAsyncEventArgs.ConnectByNameError;
                }

                if (socketAsyncEventArgs.SocketError != SocketError.Success)
                {
                    throw new WebSocketException($"Failed to open socket to '{address}' due error '{socketAsyncEventArgs.SocketError}'.",
                                                 new SocketException((int)socketAsyncEventArgs.SocketError));
                }

                var localEndPoint = default(EndPoint);
                try
                {
                    localEndPoint = socket.LocalEndPoint;
                }
                catch
                {
                    if (UnixSocketTransport.IsUnixEndPoint(remoteEndPoint))
                    {
                        localEndPoint = remoteEndPoint;
                    }
                }

                var connection = new SocketConnection(socket, localEndPoint);
                socket = null;
                return(connection);
            }
            finally
            {
                if (socket != null)
                {
                    SafeEnd.Dispose(socket, options.Logger);
                }
            }
        }