public static void WriteMessage(WebClient client, IMessage data, [Optional] Int32 tracker, [Optional] TrackerOrigin origin, bool useTracker = false) { var type = data.GetType(); if (!ProtocolMap.ProtocolCache.Reverse.HasEntry(type)) { TcpServer.WriteLogSafe($"{client.Session.Id} | WARNING: attempted to send invalid command. ignoring."); return; } var streamRaw = new MemoryStream(); streamRaw.Write(BitConverter.GetBytes(ProtocolMap.ProtocolCache.Reverse[type]), 0, 4); streamRaw.Write(BitConverter.GetBytes(useTracker), 0, 1); if (useTracker) { streamRaw.Write(BitConverter.GetBytes(Convert.ToBoolean(origin)), 0, 1); streamRaw.Write(BitConverter.GetBytes(tracker), 0, 4); } streamRaw.Write(BitConverter.GetBytes(ProtocolMap.ProtocolAttributes[type].HasData), 0, 1); data.WriteTo(streamRaw); var res = streamRaw.ToArray(); TcpServer.WriteLogSafe($"{client.Session.Id} | Sending: {BitConverter.ToString(res)}"); client.Session.QueueMessage(res, true); streamRaw.Dispose(); }
private static SceneResponse GetScene() { TcpServer.WriteLogSafe("Get Scene"); sceneResponse.Gameobjects.Clear(); sceneResponse.Gameobjects.AddRange(SceneHandler.CurrentRootObjects.Select(item => new WebGameObject { Reference = 0, Enabled = item.active, Name = item.name })); return(sceneResponse); }
private static void DecodeMessage(WebClient client, byte[] message) { int commandId = BitConverter.ToInt32(message, 0); bool useTracker = BitConverter.ToBoolean(message, 4); TrackerOrigin origin = useTracker && BitConverter.ToBoolean(message, 5) ? TrackerOrigin.Client : TrackerOrigin.Server; int tracker = useTracker ? BitConverter.ToInt32(message, 6) : 0; bool hasData = BitConverter.ToBoolean(message, useTracker ? 10 : 5); int headersLen = useTracker ? 11 : 6; if (!ProtocolMap.ProtocolCache.Forward.HasEntry(commandId)) { TcpServer.WriteLogSafe($"{client.Session.Id} | WARNING: client sent invalid command. ignoring."); return; } TcpServer.WriteLogSafe($"{client.Session.Id} | Recieved [{BitConverter.ToString(message)}]"); var command = hasData ? SignalReceived.BuildSignal(commandId, ref message, headersLen) : null; SignalReceived.OnSignalReceived(client, command, useTracker, tracker, origin); // if (origin != TrackerOrigin.Client) // return; // // if (command == typeof(PingRequest)) // { // WriteMessage(session, new PingResponse // { // Message = session.Id // }, tracker, origin); // // WriteMessage(session, new PingRequest // { // Message = session.Id // }, 0, TrackerOrigin.Server); // } else if (command == typeof(PingResponse)) // { // TcpServer.WriteLogSafe(headersLen); // TcpServer.WriteLogSafe($"{session.Id} | PONG [{PingResponse.Parser.ParseFrom(message, headersLen, message.Length - headersLen)}]"); // } }
static void SendMessage(TcpClient client, byte[] payload, int opcode, bool masking, byte[] mask) { if (masking && mask == null) { throw new ArgumentException(nameof(mask)); } using (var packet = new MemoryStream()) { byte firstbyte = 0b0_0_0_0_0000; // fin | rsv1 | rsv2 | rsv3 | [ OPCODE | OPCODE | OPCODE | OPCODE ] firstbyte |= 0b1_0_0_0_0000; // fin //firstbyte |= 0b0_1_0_0_0000; // rsv1 //firstbyte |= 0b0_0_1_0_0000; // rsv2 //firstbyte |= 0b0_0_0_1_0000; // rsv3 firstbyte += (byte)opcode; // Text packet.WriteByte(firstbyte); // Set bit: bytes[byteIndex] |= mask; byte secondbyte = 0b0_0000000; // mask | [SIZE | SIZE | SIZE | SIZE | SIZE | SIZE | SIZE] if (masking) { secondbyte |= 0b1_0000000; // mask } if (payload.LongLength <= 0b0_1111101) // 125 { secondbyte |= (byte)payload.Length; packet.WriteByte(secondbyte); } else if (payload.LongLength <= UInt16.MaxValue) // If length takes 2 bytes { secondbyte |= 0b0_1111110; // 126 packet.WriteByte(secondbyte); var len = BitConverter.GetBytes(payload.LongLength); Array.Reverse(len, 0, 2); packet.Write(len, 0, 2); } else // if (payload.LongLength <= Int64.MaxValue) // If length takes 8 bytes { secondbyte |= 0b0_1111111; // 127 packet.WriteByte(secondbyte); var len = BitConverter.GetBytes(payload.LongLength); Array.Reverse(len, 0, 8); packet.Write(len, 0, 8); } if (masking) { packet.Write(mask, 0, 4); payload = ApplyMask(payload, mask); } // Write all data to the packet packet.Write(payload, 0, payload.Length); // Get client's stream var stream = client.GetStream(); var finalPacket = packet.ToArray(); TcpServer.WriteLogSafe($@"SENT: {BitConverter.ToString(finalPacket)}"); // Send the packet foreach (var b in finalPacket) { stream.WriteByte(b); } } }
private void MessageLoop() { var session = this; var client = session.Client; var stream = session.ClientStream; var packet = new List <byte>(); var messageOpcode = 0x0; using (var messageBuffer = new MemoryStream()) while (client.Connected) { packet.Clear(); var ab = client.Available; if (ab == 0) { MessageProcessQueue(); continue; } packet.Add((byte)stream.ReadByte()); var fin = (packet[0] & (1 << 7)) != 0; var rsv1 = (packet[0] & (1 << 6)) != 0; var rsv2 = (packet[0] & (1 << 5)) != 0; var rsv3 = (packet[0] & (1 << 4)) != 0; // Must error if is set. //if (rsv1 || rsv2 || rsv3) // return; var opcode = packet[0] & ((1 << 4) - 1); switch (opcode) { case 0x0: // Continuation Frame break; case 0x1: // Text case 0x2: // Binary case 0x8: // Connection Close messageOpcode = opcode; break; case 0x9: continue; // Ping case 0xA: continue; // Pong default: continue; // Reserved } packet.Add((byte)stream.ReadByte()); var masked = IsMasking = (packet[1] & (1 << 7)) != 0; var pseudoLength = packet[1] - (masked ? 128 : 0); ulong actualLength = 0; if (pseudoLength > 0 && pseudoLength < 125) { actualLength = (ulong)pseudoLength; } else if (pseudoLength == 126) { var length = new byte[2]; stream.Read(length, 0, length.Length); packet.AddRange(length); Array.Reverse(length); actualLength = BitConverter.ToUInt16(length, 0); } else if (pseudoLength == 127) { var length = new byte[8]; stream.Read(length, 0, length.Length); packet.AddRange(length); Array.Reverse(length); actualLength = BitConverter.ToUInt64(length, 0); } var mask = new byte[4]; if (masked) { stream.Read(mask, 0, mask.Length); packet.AddRange(mask); } if (actualLength > 0) { var data = new byte[actualLength]; stream.Read(data, 0, data.Length); packet.AddRange(data); if (masked) { data = ApplyMask(data, mask); } messageBuffer.Write(data, 0, data.Length); } TcpServer.WriteLogSafe($@"RECV: {BitConverter.ToString(packet.ToArray())}"); if (!fin) { continue; } var message = messageBuffer.ToArray(); switch (messageOpcode) { case 0x1: AnyMessageReceived?.Invoke(session, message); TextMessageReceived?.Invoke(session, Encoding.UTF8.GetString(message)); break; case 0x2: AnyMessageReceived?.Invoke(session, message); BinaryMessageReceived?.Invoke(session, message); break; case 0x8: Close(); break; default: throw new Exception("Invalid opcode: " + messageOpcode); } messageBuffer.SetLength(0); } }