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); }
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); }