internal static async Task ReceiveAndReplyClientMessage(TcpClient clientWssAccepted, NetworkStream clientStream, byte[] wssReceivedBytes, HttpRequest firstRequestOfHandShake) { bool fin = (wssReceivedBytes[0] & 0b10000000) != 0; bool mask = (wssReceivedBytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set" int opcode = wssReceivedBytes[0] & 0b00001111, // expecting 1 - text message msglen = wssReceivedBytes[1] - 128, // & 0111 1111 offset = 2; if (msglen == 126) { // was ToUInt16(bytes, offset) but the result is incorrect msglen = BitConverter.ToUInt16(new byte[] { wssReceivedBytes[3], wssReceivedBytes[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) { Console.WriteLine("msglen == 0"); } else if (mask) { byte[] decoded = new byte[msglen]; byte[] masks = new byte[4] { wssReceivedBytes[offset], wssReceivedBytes[offset + 1], wssReceivedBytes[offset + 2], wssReceivedBytes[offset + 3] }; offset += 4; for (int i = 0; i < msglen; ++i) { decoded[i] = (byte)(wssReceivedBytes[offset + i] ^ masks[i % 4]); } string receivedFromClient = Encoding.UTF8.GetString(decoded); var wssResponse = await RoutingHandler.HandleWss(new HttpRequest() { UrlRelative = firstRequestOfHandShake.UrlRelative, Method = "wss", CreatedAt = DateTime.Now, Body = receivedFromClient, RemoteEndPoint = clientWssAccepted.Client.RemoteEndPoint.ToString() }); WebsocketServerHub.Send(clientWssAccepted, clientStream, wssResponse); } else { Console.WriteLine("mask bit not set"); } }
public static void Publish(string urlRelative, IResponse response) { if (_channel.TryGetValue(urlRelative, out BlockingCollection <KeyValuePair <TcpClient, NetworkStream> > clients) && clients != null) { List <Task> tasks = new List <Task>(); foreach (var client in clients) { tasks.Add(Task.Run(() => { if (!client.Key.Client.Connected) { WebsocketServerHub.Remove(urlRelative); return; } WebsocketServerHub.Send(client.Key, client.Value, response); })); } //want to make sure sent all to client //Task.WhenAll(tasks).GetAwaiter().GetResult(); } }