Exemplo n.º 1
0
        /// <summary>
        ///     Start the server (synchronous)
        /// </summary>
        /// <returns>'true' if the server was successfully started, 'false' if the server failed to start</returns>
        public override Boolean Start()
        {
            if (IsStarted)
            {
                return(false);
            }

            // Setup buffers
            _receiveBuffer = new NetworkDataBuffer();
            _sendBuffer    = new NetworkDataBuffer();

            // Setup event args
            _receiveEventArg            = new SocketAsyncEventArgs();
            _receiveEventArg.Completed += OnAsyncCompleted;
            _sendEventArg            = new SocketAsyncEventArgs();
            _sendEventArg.Completed += OnAsyncCompleted;

            // Create a new server socket
            Socket = new Socket(Endpoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

            // Update the server socket disposed flag
            IsSocketDisposed = false;

            // Apply the option: reuse address
            Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, OptionReuseAddress);
            // Apply the option: exclusive address use
            Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, OptionExclusiveAddressUse);
            // Apply the option: dual mode (this option must be applied before recieving)
            if (Socket.AddressFamily == AddressFamily.InterNetworkV6)
            {
                Socket.DualMode = OptionDualMode;
            }

            // Bind the server socket to the IP endpoint
            Socket.Bind(Endpoint);
            // Refresh the endpoint property based on the actual endpoint created
            Endpoint = (IPEndPoint)Socket.LocalEndPoint;

            // Prepare receive endpoint
            _receiveEndpoint = new IPEndPoint(Endpoint.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, 0);

            // Prepare receive & send buffers
            _receiveBuffer.Reserve(OptionReceiveBufferSize);

            // Reset statistic
            BytesPending      = 0;
            BytesSending      = 0;
            BytesSent         = 0;
            BytesReceived     = 0;
            DatagramsSent     = 0;
            DatagramsReceived = 0;

            // Update the started flag
            IsStarted = true;

            // Call the server started handler
            OnStarted();

            return(true);
        }
Exemplo n.º 2
0
        /// <summary>
        ///     This method is invoked when an asynchronous receive operation completes
        /// </summary>
        private void ProcessReceive(IAsyncResult result)
        {
            try
            {
                if (!IsHandshaked)
                {
                    return;
                }

                // Validate SSL stream Id
                Guid?sslStreamId = result.AsyncState as Guid?;
                if (_sslStreamId != sslStreamId)
                {
                    return;
                }

                // End the SSL read
                Int64 size = _sslStream.EndRead(result);

                // Received some data from the client
                if (size > 0)
                {
                    // Update statistic
                    BytesReceived += size;
                    Interlocked.Add(ref Server.bytesReceived, size);

                    // Call the buffer received handler
                    OnReceived(_receiveBuffer.Data, 0, size);

                    // If the receive buffer is full increase its size
                    if (_receiveBuffer.Capacity == size)
                    {
                        _receiveBuffer.Reserve(2 * size);
                    }
                }

                receiving = false;

                // If zero is returned from a read operation, the remote end has closed the connection
                if (size > 0)
                {
                    if (!result.CompletedSynchronously)
                    {
                        TryReceive();
                    }
                }
                else
                {
                    Disconnect();
                }
            }
            catch (Exception)
            {
                SendError(SocketError.OperationAborted);
                Disconnect();
            }
        }
Exemplo n.º 3
0
        /// <summary>
        ///     This method is invoked when an asynchronous receive operation completes
        /// </summary>
        private Boolean ProcessReceive(SocketAsyncEventArgs e)
        {
            if (!IsConnected)
            {
                return(false);
            }

            Int64 size = e.BytesTransferred;

            // Received some data from the client
            if (size > 0)
            {
                // Update statistic
                BytesReceived += size;
                Interlocked.Add(ref Server.bytesReceived, size);

                // Call the buffer received handler
                OnReceived(_receiveBuffer.Data, 0, size);

                // If the receive buffer is full increase its size
                if (_receiveBuffer.Capacity == size)
                {
                    _receiveBuffer.Reserve(2 * size);
                }
            }

            receiving = false;

            // Try to receive again if the session is valid
            if (e.SocketError == SocketError.Success)
            {
                // If zero is returned from a read operation, the remote end has closed the connection
                if (size > 0)
                {
                    return(true);
                }

                Disconnect();
            }
            else
            {
                SendError(e.SocketError);
                Disconnect();
            }

            return(false);
        }
Exemplo n.º 4
0
        /// <summary>
        ///     This method is invoked when an asynchronous receive from operation completes
        /// </summary>
        private void ProcessReceiveFrom(SocketAsyncEventArgs e)
        {
            _receiving = false;

            if (!IsStarted)
            {
                return;
            }

            // Check for error
            if (e.SocketError != SocketError.Success)
            {
                SendError(e.SocketError);

                // Call the datagram received zero handler
                OnReceived(e.RemoteEndPoint, _receiveBuffer.Data, 0, 0);

                return;
            }

            Int64 size = e.BytesTransferred;

            // Received some data from the client
            if (size <= 0)
            {
                return;
            }

            // Update statistic
            DatagramsReceived++;
            BytesReceived += size;

            // Call the datagram received handler
            OnReceived(e.RemoteEndPoint, _receiveBuffer.Data, 0, size);

            // If the receive buffer is full increase its size
            if (_receiveBuffer.Capacity == size)
            {
                _receiveBuffer.Reserve(2 * size);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        ///     Connect the session
        /// </summary>
        /// <param name="socket">Session socket</param>
        public override void Connect(Socket socket)
        {
            if (IsConnected)
            {
                throw new AlreadyInitializedException("Already connected");
            }

            Socket = socket;

            // Update the session socket disposed flag
            IsSocketDisposed = false;

            // Setup buffers
            _receiveBuffer  = new NetworkDataBuffer();
            sendBufferMain  = new NetworkDataBuffer();
            sendBufferFlush = new NetworkDataBuffer();

            // Apply the option: keep alive
            if (Server.OptionKeepAlive)
            {
                Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            }

            // Apply the option: no delay
            if (Server.OptionNoDelay)
            {
                Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            }

            // Prepare receive & send buffers
            _receiveBuffer.Reserve(OptionReceiveBufferSize);
            sendBufferMain.Reserve(OptionSendBufferSize);
            sendBufferFlush.Reserve(OptionSendBufferSize);

            // Reset statistic
            BytesPending  = 0;
            BytesSending  = 0;
            BytesSent     = 0;
            BytesReceived = 0;

            // Update the connected flag
            IsConnected = true;

            // Call the session connected handler
            OnConnected();

            // Call the session connected handler in the server
            Server.OnConnectedInternal(this);

            try
            {
                // Create SSL stream
                _sslStreamId = Guid.NewGuid();
                _sslStream   = Server.Context.CertificateValidationCallback is not null
                    ? new SslStream(new NetworkStream(Socket, false), false, Server.Context.CertificateValidationCallback)
                    : new SslStream(new NetworkStream(Socket, false), false);

                // Begin the SSL handshake
                _sslStream.BeginAuthenticateAsServer(Server.Context.Certificate, Server.Context.ClientCertificateRequired, Server.Context.Protocols, false, ProcessHandshake,
                                                     _sslStreamId);
            }
            catch (Exception)
            {
                SendError(SocketError.NotConnected);
                Disconnect();
            }
        }
Exemplo n.º 6
0
        /// <summary>
        ///     Connect the client (synchronous)
        /// </summary>
        /// <remarks>
        ///     Please note that synchronous connect will not receive data automatically!
        ///     You should use Receive() or ReceiveAsync() method manually after successful connection.
        /// </remarks>
        /// <returns>'true' if the client was successfully connected, 'false' if the client failed to connect</returns>
        public override Boolean Connect()
        {
            if (IsConnected || IsHandshaked || IsConnecting || IsHandshaking)
            {
                return(false);
            }

            // Setup buffers
            receiveBuffer  = new NetworkDataBuffer();
            sendBufferMain = new NetworkDataBuffer();
            sendBuffer     = new NetworkDataBuffer();

            // Setup event args
            connectEventArg = new SocketAsyncEventArgs {
                RemoteEndPoint = Endpoint
            };
            connectEventArg.Completed += OnAsyncCompleted;

            // Create a new client socket
            Socket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            // Apply the option: dual mode (this option must be applied before connecting)
            if (Socket.AddressFamily == AddressFamily.InterNetworkV6)
            {
                Socket.DualMode = OptionDualMode;
            }

            try
            {
                // Connect to the server
                Socket.Connect(Endpoint);
            }
            catch (SocketException ex)
            {
                // Close the client socket
                Socket.Close();
                // Dispose the client socket
                Socket.Dispose();
                // Dispose event arguments
                connectEventArg.Dispose();

                // Call the client disconnected handler
                SendError(ex.SocketErrorCode);
                OnDisconnected();
                return(false);
            }

            // Update the client socket disposed flag
            IsSocketDisposed = false;

            // Apply the option: keep alive
            if (OptionKeepAlive)
            {
                Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            }

            // Apply the option: no delay
            if (OptionNoDelay)
            {
                Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            }

            // Prepare receive & send buffers
            receiveBuffer.Reserve(OptionReceiveBufferSize);
            sendBufferMain.Reserve(OptionSendBufferSize);
            sendBuffer.Reserve(OptionSendBufferSize);

            // Reset statistic
            BytesPending  = 0;
            BytesSending  = 0;
            BytesSent     = 0;
            BytesReceived = 0;

            // Update the connected flag
            IsConnected = true;

            // Call the client connected handler
            OnConnected();

            try
            {
                // Create SSL stream
                _sslStreamId = Guid.NewGuid();
                _sslStream   = Context.CertificateValidationCallback is not null
                    ? new SslStream(new NetworkStream(Socket, false), false, Context.CertificateValidationCallback)
                    : new SslStream(new NetworkStream(Socket, false), false);

                // SSL handshake
                _sslStream.AuthenticateAsClient(Address, Context.Certificates ?? new X509CertificateCollection(new[] { Context.Certificate }), Context.Protocols, true);
            }
            catch (Exception)
            {
                SendError(SocketError.NotConnected);
                DisconnectAsync();
                return(false);
            }

            // Update the handshaked flag
            IsHandshaked = true;

            // Call the session handshaked handler
            OnHandshaked();

            // Call the empty send buffer handler
            if (sendBufferMain.IsEmpty)
            {
                OnEmpty();
            }

            return(true);
        }
Exemplo n.º 7
0
        /// <summary>
        ///     Connect the client (synchronous)
        /// </summary>
        /// <remarks>
        ///     Please note that synchronous connect will not receive data automatically!
        ///     You should use Receive() or ReceiveAsync() method manually after successful connection.
        /// </remarks>
        /// <returns>'true' if the client was successfully connected, 'false' if the client failed to connect</returns>
        public override Boolean Connect()
        {
            if (IsConnected || IsConnecting)
            {
                return(false);
            }

            // Setup buffers
            receiveBuffer  = new NetworkDataBuffer();
            sendBufferMain = new NetworkDataBuffer();
            sendBuffer     = new NetworkDataBuffer();

            // Setup event args
            connectEventArg = new SocketAsyncEventArgs {
                RemoteEndPoint = Endpoint
            };
            connectEventArg.Completed  += OnAsyncCompleted;
            _receiveEventArg            = new SocketAsyncEventArgs();
            _receiveEventArg.Completed += OnAsyncCompleted;
            _sendEventArg            = new SocketAsyncEventArgs();
            _sendEventArg.Completed += OnAsyncCompleted;

            // Create a new client socket
            Socket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            // Apply the option: dual mode (this option must be applied before connecting)
            if (Socket.AddressFamily == AddressFamily.InterNetworkV6)
            {
                Socket.DualMode = OptionDualMode;
            }

            try
            {
                // Connect to the server
                Socket.Connect(Endpoint);
            }
            catch (SocketException ex)
            {
                // Close the client socket
                Socket.Close();
                // Dispose the client socket
                Socket.Dispose();
                // Dispose event arguments
                connectEventArg.Dispose();
                _receiveEventArg.Dispose();
                _sendEventArg.Dispose();

                // Call the client disconnected handler
                SendError(ex.SocketErrorCode);
                OnDisconnected();
                return(false);
            }

            // Update the client socket disposed flag
            IsSocketDisposed = false;

            // Apply the option: keep alive
            if (OptionKeepAlive)
            {
                Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            }

            // Apply the option: no delay
            if (OptionNoDelay)
            {
                Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            }

            // Prepare receive & send buffers
            receiveBuffer.Reserve(OptionReceiveBufferSize);
            sendBufferMain.Reserve(OptionSendBufferSize);
            sendBuffer.Reserve(OptionSendBufferSize);

            // Reset statistic
            BytesPending  = 0;
            BytesSending  = 0;
            BytesSent     = 0;
            BytesReceived = 0;

            // Update the connected flag
            IsConnected = true;

            // Call the client connected handler
            OnConnected();

            // Call the empty send buffer handler
            if (sendBufferMain.IsEmpty)
            {
                OnEmpty();
            }

            return(true);
        }
Exemplo n.º 8
0
        /// <summary>
        ///     Connect the session
        /// </summary>
        /// <param name="socket">Session socket</param>
        public override void Connect(Socket socket)
        {
            if (IsConnected)
            {
                throw new AlreadyInitializedException("Already connected");
            }

            Socket = socket;

            // Update the session socket disposed flag
            IsSocketDisposed = false;

            // Setup buffers
            _receiveBuffer  = new NetworkDataBuffer();
            sendBufferMain  = new NetworkDataBuffer();
            sendBufferFlush = new NetworkDataBuffer();

            // Setup event args
            _receiveEventArg            = new SocketAsyncEventArgs();
            _receiveEventArg.Completed += OnAsyncCompleted;
            _sendEventArg            = new SocketAsyncEventArgs();
            _sendEventArg.Completed += OnAsyncCompleted;

            // Apply the option: keep alive
            if (Server.OptionKeepAlive)
            {
                Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            }

            // Apply the option: no delay
            if (Server.OptionNoDelay)
            {
                Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            }

            // Prepare receive & send buffers
            _receiveBuffer.Reserve(OptionReceiveBufferSize);
            sendBufferMain.Reserve(OptionSendBufferSize);
            sendBufferFlush.Reserve(OptionSendBufferSize);

            // Reset statistic
            BytesPending  = 0;
            BytesSending  = 0;
            BytesSent     = 0;
            BytesReceived = 0;

            // Update the connected flag
            IsConnected = true;

            // Call the session connected handler
            OnConnected();

            // Call the session connected handler in the server
            Server.OnConnectedInternal(this);

            // Call the empty send buffer handler
            if (sendBufferMain.IsEmpty)
            {
                OnEmpty();
            }

            // Try to receive something from the client
            TryReceive();
        }