public virtual async Task <bool> DisconnectConnectionAsync(IConnectionWSServer connection)
        {
            try
            {
                _numberOfConnections--;

                if (connection.Websocket.State == WebSocketState.Open)
                {
                    await connection.Websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Disconnect", CancellationToken.None);
                }

                await FireEventAsync(this, new WSConnectionServerEventArgs
                {
                    Connection          = connection,
                    ConnectionEventType = ConnectionEventType.Disconnect
                });

                return(true);
            }
            catch (Exception ex)
            {
                await FireEventAsync(this, new WSErrorServerEventArgs
                {
                    Connection = connection,
                    Exception  = ex,
                    Message    = ex.Message
                });
            }
            return(false);
        }
        protected virtual async Task MessageReceivedAsync(string message, IConnectionWSServer connection)
        {
            IPacket packet;

            try
            {
                packet = JsonConvert.DeserializeObject <Packet>(message);

                if (string.IsNullOrWhiteSpace(packet.Data))
                {
                    packet = new Packet
                    {
                        Data      = message,
                        Timestamp = DateTime.UtcNow
                    };
                }
            }
            catch
            {
                packet = new Packet
                {
                    Data      = message,
                    Timestamp = DateTime.UtcNow
                };
            }

            await FireEventAsync(this, new WSMessageServerEventArgs
            {
                MessageEventType = MessageEventType.Receive,
                Message          = packet.Data,
                Packet           = packet,
                Connection       = connection
            });
        }
 public virtual async Task <bool> SendToConnectionAsync(string message, IConnectionWSServer connection)
 {
     return(await SendToConnectionAsync(new Packet
     {
         Data = message,
         Timestamp = DateTime.UtcNow
     }, connection));
 }
 public virtual async Task BroadcastToAllAuthorizedUsersAsync(string message, IConnectionWSServer connectionSending)
 {
     await BroadcastToAllAuthorizedUsersAsync(new Packet
     {
         Data      = message,
         Timestamp = DateTime.UtcNow
     }, connectionSending);
 }
예제 #5
0
        protected override async Task <bool> UpgradeConnectionAsync(string message, IConnectionWSServer connection)
        {
            // Checking auth token
            var token = message.Substring(message.IndexOf("/") + 1);

            token = token.Substring(0, token.IndexOf(" "));

            await FireEventAsync(this, new WSAuthorizeEventArgs
            {
                Connection  = connection,
                Token       = token,
                UpgradeData = message
            });

            return(true);
        }
 public virtual async Task BroadcastToAllAuthorizedUsersAsync <S>(S packet, IConnectionWSServer connectionSending) where S : IPacket
 {
     if (_handler != null &&
         _handler.IsServerRunning)
     {
         foreach (var identity in _connectionManager.GetAllIdentities())
         {
             foreach (var connection in identity.Connections.ToList())
             {
                 if (connection.Client.GetHashCode() != connection.Client.GetHashCode())
                 {
                     await SendToConnectionAsync(packet, connection);
                 }
             }
         }
     }
 }
        public virtual async Task <bool> SendToConnectionRawAsync(string message, IConnectionWSServer connection)
        {
            if (_handler != null &&
                _handler.IsServerRunning)
            {
                if (_connectionManager.IsConnectionOpen(connection))
                {
                    try
                    {
                        if (!await _handler.SendRawAsync(message, connection))
                        {
                            return(false);
                        }

                        await FireEventAsync(this, new WSMessageServerEventArgs
                        {
                            Message          = message,
                            MessageEventType = MessageEventType.Sent,
                            Packet           = new Packet
                            {
                                Data      = message,
                                Timestamp = DateTime.UtcNow
                            },
                            Connection = connection,
                        });

                        return(true);
                    }
                    catch (Exception ex)
                    {
                        await FireEventAsync(this, new WSErrorServerEventArgs
                        {
                            Connection = connection,
                            Exception  = ex,
                            Message    = ex.Message,
                        });

                        await DisconnectConnectionAsync(connection);
                    }
                }
            }

            return(false);
        }
        protected virtual async Task <bool> UpgradeConnectionAsync(string message, IConnectionWSServer connection)
        {
            Console.WriteLine("=====Handshaking from client=====\n{0}", message);

            // 1. Obtain the value of the "Sec-WebSocket-Key" request header without any leading or trailing whitespace
            // 2. Concatenate it with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (a special GUID specified by RFC 6455)
            // 3. Compute SHA-1 and Base64 hash of the new value
            // 4. Write the hash back as the value of "Sec-WebSocket-Accept" response header in an HTTP response
            var swk                   = Regex.Match(message, $"{HttpKnownHeaderNames.SecWebSocketKey}: (.*)").Groups[1].Value.Trim();
            var swka                  = swk + Statics.WS_SERVER_GUID;
            var swkaSha1              = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka));
            var swkaSha1Base64        = Convert.ToBase64String(swkaSha1);
            var requestedSubprotocols = Regex.Match(message, $"{HttpKnownHeaderNames.SecWebSocketProtocol}: (.*)").Groups[1].Value.Trim().Split(",");

            if (requestedSubprotocols.Where(x => !string.IsNullOrWhiteSpace(x)).ToArray().Length > 0)
            {
                if (!AreSubprotocolsRequestedValid(requestedSubprotocols))
                {
                    var bytes = Encoding.UTF8.GetBytes("Invalid subprotocols requested");
                    await connection.Stream.WriteAsync(bytes);
                    await DisconnectConnectionAsync(connection);

                    return(false);
                }
            }

            // HTTP/1.1 defines the sequence CR LF as the end-of-line marker
            var response = Encoding.UTF8.GetBytes(
                "HTTP/1.1 101 Switching Protocols\r\n" +
                $"{HttpKnownHeaderNames.Connection}: Upgrade\r\n" +
                $"{HttpKnownHeaderNames.Upgrade}: websocket\r\n" +
                $"{HttpKnownHeaderNames.SecWebSocketAccept}: " + swkaSha1Base64 + "\r\n\r\n");

            connection.SubProtocols = requestedSubprotocols;
            await connection.Stream.WriteAsync(response, 0, response.Length);

            _numberOfConnections++;

            await SendRawAsync(_parameters.ConnectionSuccessString, connection);

            return(true);
        }
        public virtual async Task <bool> SendToConnectionAsync <S>(S packet, IConnectionWSServer connection) where S : IPacket
        {
            if (_handler.IsServerRunning)
            {
                if (_connectionManager.IsConnectionOpen(connection))
                {
                    try
                    {
                        if (!await _handler.SendAsync(packet, connection))
                        {
                            return(false);
                        }

                        await FireEventAsync(this, new WSMessageServerEventArgs
                        {
                            Message          = packet.Data,
                            MessageEventType = MessageEventType.Sent,
                            Connection       = connection,
                            Packet           = packet,
                        });

                        return(true);
                    }
                    catch (Exception ex)
                    {
                        await FireEventAsync(this, new WSErrorServerEventArgs
                        {
                            Connection = connection,
                            Exception  = ex,
                            Message    = ex.Message,
                        });

                        await DisconnectConnectionAsync(connection);

                        return(false);
                    }
                }
            }

            return(false);
        }
        public virtual async Task <bool> SendRawAsync(string message, IConnectionWSServer connection)
        {
            try
            {
                await connection.Websocket.SendAsync(buffer : new ArraySegment <byte>(array: Encoding.UTF8.GetBytes(message),
                                                                                      offset: 0,
                                                                                      count: message.Length),
                                                     messageType : WebSocketMessageType.Text,
                                                     endOfMessage : true,
                                                     cancellationToken : CancellationToken.None);

                await FireEventAsync(this, new WSMessageServerEventArgs
                {
                    MessageEventType = MessageEventType.Sent,
                    Message          = message,
                    Packet           = new Packet
                    {
                        Data      = message,
                        Timestamp = DateTime.UtcNow
                    },
                    Connection = connection,
                });

                return(true);
            }
            catch (Exception ex)
            {
                _numberOfConnections--;
                await FireEventAsync(this, new WSErrorServerEventArgs
                {
                    Connection = connection,
                    Exception  = ex,
                    Message    = ex.Message,
                });
            }

            return(false);
        }
        public virtual async Task <bool> SendAsync <T>(T packet, IConnectionWSServer connection) where T : IPacket
        {
            try
            {
                var message = JsonConvert.SerializeObject(packet);

                await connection.Websocket.SendAsync(buffer : new ArraySegment <byte>(array: Encoding.UTF8.GetBytes(message),
                                                                                      offset: 0,
                                                                                      count: message.Length),
                                                     messageType : WebSocketMessageType.Text,
                                                     endOfMessage : true,
                                                     cancellationToken : CancellationToken.None);

                await FireEventAsync(this, new WSMessageServerEventArgs
                {
                    MessageEventType = MessageEventType.Sent,
                    Message          = message,
                    Packet           = packet,
                    Connection       = connection,
                });

                return(true);
            }
            catch (Exception ex)
            {
                await FireEventAsync(this, new WSErrorServerEventArgs
                {
                    Exception  = ex,
                    Message    = ex.Message,
                    Connection = connection,
                });

                await DisconnectConnectionAsync(connection);
            }

            return(false);
        }
        public virtual async Task <bool> SendToConnectionAsync <S>(S packet, IConnectionWSServer connection) where S : IPacket
        {
            if (_handler.IsServerRunning)
            {
                if (_connectionManager.IsConnectionOpen(connection))
                {
                    try
                    {
                        if (!await _handler.SendAsync(packet, connection))
                        {
                            return(false);
                        }

                        await FireEventAsync(this, new WSMessageServerAuthEventArgs <T>
                        {
                            Message          = packet.Data,
                            MessageEventType = MessageEventType.Sent,
                            Connection       = connection,
                            Packet           = packet,
                            UserId           = default
                        });

                        return(true);
                    }
 public void RemoveConnection(IConnectionWSServer connection)
 {
     _connections.TryRemove(connection.Websocket.GetHashCode(), out var instance);
 }
 public bool IsConnectionOpen(IConnectionWSServer connection)
 {
     return(_connections.TryGetValue(connection.Websocket.GetHashCode(), out var instance) ? instance.Websocket.State == WebSocketState.Open : false);
 }
        protected virtual async Task StartReceivingMessagesAsync(IConnectionWSServer connection)
        {
            try
            {
                while (connection.Client.Connected)
                {
                    if (connection.Client.Available < 3)
                    {
                        continue;
                    }
                    ;  // match against "get"

                    var bytes = new byte[connection.Client.Available];
                    await connection.Stream.ReadAsync(bytes, 0, connection.Client.Available);

                    var data = Encoding.UTF8.GetString(bytes);

                    if (Regex.IsMatch(data, "^GET", RegexOptions.IgnoreCase))
                    {
                        if (await UpgradeConnectionAsync(data, connection))
                        {
                            await FireEventAsync(this, new WSConnectionServerEventArgs
                            {
                                Connection          = connection,
                                ConnectionEventType = ConnectionEventType.Connected,
                            });
                        }
                    }
                    else
                    {
                        bool fin  = (bytes[0] & 0b10000000) != 0,
                             mask = (bytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set"

                        int opcode = bytes[0] & 0b00001111,       // expecting 1 - text message
                            msglen = bytes[1] - 128,              // & 0111 1111
                            offset = 2;

                        if (msglen == 126)
                        {
                            // was ToUInt16(bytes, offset) but the result is incorrect
                            msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
                            offset = 4;
                        }
                        else if (msglen == 127)
                        {
                            Console.WriteLine("TODO: msglen == 127, needs qword to store msglen");
                            // i don't really know the byte order, please edit this
                            // msglen = BitConverter.ToUInt64(new byte[] { bytes[5], bytes[4], bytes[3], bytes[2], bytes[9], bytes[8], bytes[7], bytes[6] }, 0);
                            // offset = 10;
                        }

                        if (msglen > 0 && mask)
                        {
                            var decoded = new byte[msglen];
                            var masks   = new byte[4] {
                                bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]
                            };
                            offset += 4;

                            for (int i = 0; i < msglen; ++i)
                            {
                                decoded[i] = (byte)(bytes[offset + i] ^ masks[i % 4]);
                            }

                            var    isDisconnect  = false;
                            byte[] selectedBytes = null;

                            for (int i = 0; i < decoded.Length; i++)
                            {
                                // This checks for a disconnect
                                if (decoded[i] == 0x03)
                                {
                                    isDisconnect = true;

                                    selectedBytes = new byte[i];
                                    for (int j = 0; j < i; j++)
                                    {
                                        selectedBytes[j] = decoded[j];
                                    }
                                    break;
                                }
                            }

                            if (!isDisconnect)
                            {
                                selectedBytes = decoded;
                            }

                            if (selectedBytes != null)
                            {
                                var message = Encoding.UTF8.GetString(selectedBytes);

                                if (!string.IsNullOrWhiteSpace(message))
                                {
                                    if (message.Trim().ToLower() == "pong")
                                    {
                                        connection.HasBeenPinged = false;
                                    }
                                    else
                                    {
                                        await MessageReceivedAsync(message, connection);
                                    }
                                }

                                if (isDisconnect)
                                {
                                    await DisconnectConnectionAsync(connection);
                                }
                            }
                        }
                    }
                }
            }
            catch
            { }

            await FireEventAsync(this, new WSConnectionServerEventArgs
            {
                Connection          = connection,
                ConnectionEventType = ConnectionEventType.Disconnect,
            });
        }
 public virtual async Task <bool> DisconnectConnectionAsync(IConnectionWSServer connection)
 {
     return(await _handler.DisconnectConnectionAsync(connection));
 }
 public bool AddConnection(IConnectionWSServer connection)
 {
     return(!_connections.ContainsKey(connection.Websocket.GetHashCode()) ? _connections.TryAdd(connection.Websocket.GetHashCode(), connection) : false);
 }