public NetworkDataBuffer ReceiveBinary()
        {
            NetworkDataBuffer result = new NetworkDataBuffer();

            if (!webSocketNetwork.WsHandshaked)
            {
                return(result);
            }

            NetworkDataBuffer cache = new NetworkDataBuffer();

            // Receive WebSocket frame data
            while (!webSocketNetwork.WsReceived)
            {
                Int32 required = webSocketNetwork.RequiredReceiveFrameSize();
                cache.Resize(required);
                Int32 received = (Int32)base.Receive(cache.Data, 0, required);
                if (received != required)
                {
                    return(result);
                }

                webSocketNetwork.PrepareReceiveFrame(cache.Data, 0, received);
            }

            // Copy WebSocket frame data
            result.Append(webSocketNetwork.WsReceiveBuffer.ToArray(), webSocketNetwork.WsHeaderSize, webSocketNetwork.WsHeaderSize + webSocketNetwork.WsPayloadSize);
            webSocketNetwork.PrepareReceiveFrame(null, 0, 0);
            return(result);
        }
Exemple #2
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);
        }
        /// <summary>
        ///     Connect the client (asynchronous)
        /// </summary>
        /// <returns>'true' if the client was successfully connected, 'false' if the client failed to connect</returns>
        public override Boolean ConnectAsync()
        {
            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;
            }

            // Async connect to the server
            IsConnecting = true;
            if (!Socket.ConnectAsync(connectEventArg))
            {
                ProcessConnect(connectEventArg);
            }

            return(true);
        }
        /// <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();
            }
        }
        /// <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);
        }
        /// <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);
        }
        /// <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();
        }