public void HandlePing(SOEClient sender) { // Setup a writer SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.PING); SOEPacket pong = writer.GetFinalSOEPacket(sender, false, false); // Send a pong! sender.SendPacket(pong); }
public void AddNewClient(SOEClient newClient) { // Do they exist already? if (SessionID2ClientID.ContainsKey(newClient.GetSessionID())) { // Disconnect the new client Log("[WARNING] Someone tried connecting with the same Session ID!"); newClient.Disconnect((ushort)SOEDisconnectReasons.ConnectFail); // Don't continue adding this connection return; } // Is there already a connection from this endpoint? if (Host2ClientID.ContainsKey(newClient.Client)) { // Disconnect the new client Log("[WARNING] Someone tried connecting from the same endpoint!"); newClient.Disconnect((ushort)SOEDisconnectReasons.ConnectFail); // Don't continue adding this connection return; } // Loop through the Clients list, looking for an open space int newClientId; for (newClientId = 0; newClientId < Clients.Count; newClientId++) { // Is this client nulled? if (Clients[newClientId] == null) { // We've found an empty space! break; } } // Set their Client ID newClient.SetClientID(newClientId); // Add them to the Clients map if (newClientId >= Clients.Count) { Clients.Add(newClient); } else { Clients[newClientId] = newClient; } // Add them to our maps Host2ClientID.Add(newClient.Client, newClientId); SessionID2ClientID.Add(newClient.GetSessionID(), newClientId); // Log Log("New client connection from {0}, (ID: {1})", newClient.GetClientAddress(), newClient.GetClientID()); }
private byte[] DecompressPacket(SOEClient sender, byte[] packet) { // Compressable? if (!sender.IsCompressable()) { return(packet); } // Remove the OpCode and compression flag byte[] data = new byte[packet.Length - 3]; for (int i = 3; i < packet.Length; i++) { data[i - 3] = packet[i]; } byte[] decompressedData = data; // Decompress the old packet.. MemoryStream dataStream = new MemoryStream(data); MemoryStream decompressed = new MemoryStream(); if (packet[2] == 0x01) { using (ZlibStream zlibStream = new ZlibStream(dataStream, CompressionMode.Decompress)) { zlibStream.CopyTo(decompressed); } // Reconstruct the packet.. decompressedData = decompressed.ToArray(); } // Reconstruct the packet.. byte[] newPacket = new byte[decompressedData.Length + 2]; // OpCode int place = 0; for (int i = 0; i < 2; i++) { newPacket[place] = packet[i]; place++; } // Data for (int i = 0; i < decompressedData.Length; i++) { newPacket[place] = decompressedData[i]; place++; } // And.. return! return(newPacket); }
public void ReceiveMessage(SOEClient sender, byte[] rawMessage) { if (WANT_MESSAGE_THREADING) { IncomingMessages.Enqueue(new SOEPendingMessage(sender, rawMessage)); } else { Protocol.HandleMessage(sender, rawMessage); } }
public void HandleMessage(SOEClient sender, byte[] rawMessage) { // Read the message... SOEReader reader = new SOEReader(rawMessage); ushort opCode = reader.ReadHostUInt16(); // Make the message SOEMessage message = new SOEMessage(opCode, rawMessage); // Handle it HandleMessage(sender, message); }
public void HandleSessionRequest(SOEClient sender, SOEPacket packet) { // Setup a reader SOEReader reader = new SOEReader(packet); // Get the data from the packet uint crcLength = reader.ReadUInt32(); uint sessionID = reader.ReadUInt32(); uint udpBufferSize = reader.ReadUInt32(); string protocol = reader.ReadNullTerminatedString(); // Is the client using the correct protocol? if (ProtocolString == protocol) { // Can we encrypt/compress? bool encryptable = false; bool compressable = true; // Start the session and manage the client sender.StartSession(crcLength, sessionID, udpBufferSize); sender.SetCompressable(compressable); sender.SetEncryptable(encryptable); Server.ConnectionManager.AddNewClient(sender); // Setup a writer SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.SESSION_RESPONSE); // Write a response writer.AddUInt32(sessionID); writer.AddUInt32(sender.GetCRCSeed()); writer.AddByte((byte)crcLength); writer.AddBoolean(compressable); writer.AddBoolean(encryptable); writer.AddUInt32(udpBufferSize); writer.AddUInt32(3); // Get the response SOEPacket response = writer.GetFinalSOEPacket(sender, false, false); // Send the response! sender.SendPacket(response); } else { // They aren't using the right protocol... Log("Got connection request from client with incorrect protocol. Client: {0}, Server: {1}", protocol, ProtocolString); } }
public void HandlePacket(SOEClient sender, SOEPacket packet) { // Operation ushort opCode = packet.GetOpCode(); // Security Measure if (!sender.HasSession()) { if (opCode != (ushort)SOEOPCodes.SESSION_REQUEST) { // We really don't care about this client. // They can try send stuff as much as possible. // TODO: Handle this (cuz attacks) return; } } // Handle! switch ((SOEOPCodes)opCode) { case SOEOPCodes.SESSION_REQUEST: HandleSessionRequest(sender, packet); break; case SOEOPCodes.MULTI: Console.WriteLine("MULTI!"); // TODO break; case SOEOPCodes.DISCONNECT: HandleDisconnect(sender, packet); break; case SOEOPCodes.PING: HandlePing(sender); break; case SOEOPCodes.RELIABLE_DATA: case SOEOPCodes.FRAGMENTED_RELIABLE_DATA: case SOEOPCodes.ACK_RELIABLE_DATA: sender.DataChannel.Receive(packet); break; default: Log("Received Unknown SOEPacket 0x{0:X2}!", packet.GetOpCode()); break; } }
public SOEDataChannel(SOEClient client) { // Associated client Client = client; // Defaults LastReceivedSequenceNumber = 0; LastDataSendTime = 0; NextSequenceNumber = 0; StartedFragmentedPacket = false; FragmentSequenceNumber = 0; ReceivedFragmentsSize = 0; FragmentsTillAck = 6; BusySendingFragmentedPacket = false; FragmentedQueue = new Queue <SOEMessage>(); }
public void HandleDisconnect(SOEClient sender, SOEPacket packet) { // Setup a reader SOEReader reader = new SOEReader(packet); // Get the data from the packet uint sessionID = reader.ReadUInt32(); ushort reason = reader.ReadUInt16(); // Handle if (sessionID == sender.GetSessionID()) { Console.WriteLine("Disconnecting"); Server.ConnectionManager.DisconnectClient(sender, reason, true); } }
public SOEDataChannel(SOEClient client) { // Associated client Client = client; // Defaults LastReceivedSequenceNumber = 0; LastDataSendTime = 0; NextSequenceNumber = 0; StartedFragmentedPacket = false; FragmentSequenceNumber = 0; ReceivedFragmentsSize = 0; FragmentsTillAck = 6; BusySendingFragmentedPacket = false; FragmentedQueue = new Queue<SOEMessage>(); }
public void HandleMultiData(SOEClient sender, SOEMessage message) { // Setup a reader and skip the OpCode SOEReader reader = new SOEReader(message); int offset = 2; // Get the data length int dataLength = message.GetLength(); // Get the packets while (offset < dataLength) { // Message size int MessageSize = reader.ReadByte(); byte extendedMessageAmount = 0; // If the first byte is 0xFF then: // Read how many bytes to add, and then add that many if (MessageSize == 0xFF) { // How many bytes are there? extendedMessageAmount = reader.ReadByte(); // Add that many bytes for (int i = 0; i < extendedMessageAmount; i++) { MessageSize += reader.ReadByte(); } extendedMessageAmount++; } // Read the Message data from the size byte[] data = reader.ReadBytes(MessageSize); // Handle the Message sender.ReceiveMessage(data); // Move along offset += MessageSize + extendedMessageAmount + 1; } }
private byte[] DecryptPacket(SOEClient sender, byte[] packet) { // Compressable? if (!sender.IsEncrypted()) { return(packet); } // Setup our streams SOEReader reader = new SOEReader(packet); SOEWriter newPacket = new SOEWriter(reader.ReadUInt16()); // Skip the compression flag reader.ReadByte(); // Get our data int blockCount = (packet.Length - 3) / 4; int byteCount = (packet.Length - 3) % 4; uint key = sender.GetCRCSeed(); // Decrypt the blocks of 4 bytes for (int i = 0; i < blockCount; i++) { uint temp = reader.ReadUInt32(); uint value = temp ^ key; key = temp; newPacket.AddUInt32(value); } // Decrypt the rest of the singular bytes byte newKey = (byte)((key >> 24) & 0xFF); for (int i = 0; i < byteCount; i++) { byte value = (byte)(reader.ReadByte() ^ newKey); newPacket.AddByte(value); } // Return the decrypted packet return(newPacket.GetRaw()); }
private void DoNetCycle() { // Receive a packet IPEndPoint sender = new IPEndPoint(IPAddress.Any, Port); byte[] rawPacket; try { rawPacket = UdpClient.Receive(ref sender); } catch (SocketException) { // Maybe we just killed the client? return; } // Get the associated client (or create a new fake one) SOEClient client = ConnectionManager.GetClientFromHost(sender); if (client == null) { // Make a fake client for new connections client = new SOEClient(ConnectionManager, sender); } // Do we wanna handle this, or give it to our workers? if (WANT_PACKET_THREADING) { // Put it in the queue for our workers.. IncomingPackets.Enqueue(new SOEPendingPacket(client, rawPacket)); } else { // Handle the packet Protocol.HandlePacket(client, rawPacket); } }
public void HandleMessage(SOEClient sender, SOEMessage message) { // Handlers if (MessageHandlers.HasHandler(ProtocolString, message.GetOpCode())) { // Log string messageName = MessageHandlers.Protocol2MessageName[ProtocolString][message.GetOpCode()]; Log("Received 0x{0:X}, {1}_{2}!", message.GetOpCode(), Server.GAME_NAME, messageName); // Handle it MessageHandlers.GetHandler(ProtocolString, message.GetOpCode())(sender, message); } else { // Log Log("Received Unknown SOEMessage {0}!", message.GetOpCode()); foreach (byte b in message.GetRaw()) { Console.Write("0x{0:X2} ", b); } Console.WriteLine(); } }
public void StartKeepAliveThread() { Thread keepAliveThread = new Thread((threadStart3) => { while (Server.Running) { // Get a Now time for this cycle int now = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; // Loop through the clients for (int i = 0; i < Clients.Count; i++) { // Client SOEClient client = GetClient(i); // Empty space? if (client == null) { continue; } // Idle? if (now > (client.GetLastInteraction() + Server.CLIENT_TIMEOUT)) { Log("Disconnecting Idle client."); client.Disconnect((ushort)SOEDisconnectReasons.Timeout); } } Thread.Sleep(Server.SERVER_THREAD_SLEEP); } }); keepAliveThread.Name = "SOEServer::KeepAliveThread"; keepAliveThread.Start(); }
public void HandlePacket(SOEClient sender, byte[] rawPacket) { // Read the packet SOEReader reader = new SOEReader(rawPacket); ushort opCode = reader.ReadUInt16(); bool goodPacket = true; // Get the packet data byte[] data = new byte[rawPacket.Length - (int)sender.GetCRCLength()]; for (int i = 0; i < data.Length; i++) { data[i] = rawPacket[i]; } // Get the CRC32 checksum for the packet uint crc32 = sender.GetCRC32Checksum(data); // Get our expected CRC32 checksum uint expectedCRC32 = 0; uint place = sender.GetCRCLength() - 1; for (int i = rawPacket.Length - (int)sender.GetCRCLength(); i < rawPacket.Length; i++) { expectedCRC32 += (uint)(rawPacket[i] << (8 * (int)place)); place--; } // We have our CRCs! Check if the packet is formed correctly! byte[] crc = BitConverter.GetBytes(crc32).Reverse().ToArray(); byte[] expectedCRC = BitConverter.GetBytes(expectedCRC32).Reverse().ToArray(); int start = 4 - (int)sender.GetCRCLength(); for (int i = start; i < sender.GetCRCLength(); i++) { // If they're not the same, we're a bad packet if (crc[i] != expectedCRC[i]) { // Set that we're bad, and get outta the loop goodPacket = false; break; } } // Are we malformed? if (!goodPacket) { Log("[WARNING] Received malformed packet! Incorrect CRC Appended!"); return; } // Remove the CRC rawPacket = data; // Do we need to worry about decryption/decompression? if (sender.HasSession()) { // Is the client encrypted? if (sender.IsEncrypted()) { rawPacket = DecryptPacket(sender, rawPacket); } // Is the client compressable? if (sender.IsCompressable()) { // It seems that all packets after 0x02 are compressable.. rawPacket = DecompressPacket(sender, rawPacket); } } // Handle the decompressed/decrypted packet! HandlePacket(sender, new SOEPacket(opCode, rawPacket)); }
public SOEPendingMessage(SOEClient sender, byte[] packet) { Client = sender; Message = packet; }
public SOEPendingPacket(SOEClient sender, byte[] packet) { Client = sender; Packet = packet; }
public SOEMessage GetFinalSOEMessage(SOEClient client) { // Are we a packet? if (!IsMessage) { // Yes, and there really isn't a nice way to deal with this.. client.Server.Log("[ERROR] Tried Calling 'GetFinalSOEMessage' on written SOEPacket. Returning null."); // Welp, goodbye world! :'( return null; } // Make our message SOEMessage message = new SOEMessage(OpCode, GetRaw()); // Does this message have to be fragmented? if (Data.Count > client.GetBufferSize()) { // Setup a reader and keep track of our size SOEReader reader = new SOEReader(GetRaw()); int size = message.GetLength(); // While there are fragments to be added.. while (size > 0) { // Store the next fragment byte[] raw; // Is this fragment going to be smaller than the buffer size? if (size < client.GetBufferSize()) { raw = reader.ReadBytes(size); size = 0; } else { raw = reader.ReadBytes((int)client.GetBufferSize()); size -= (int)client.GetBufferSize(); } // Add the finalized fragment message.AddFragment(raw); } } // Return the message we made return message; }
private byte[] DecryptPacket(SOEClient sender, byte[] packet) { // Compressable? if (!sender.IsEncrypted()) { return packet; } // Setup our streams SOEReader reader = new SOEReader(packet); SOEWriter newPacket = new SOEWriter(reader.ReadUInt16()); // Skip the compression flag reader.ReadByte(); // Get our data int blockCount = (packet.Length - 3) / 4; int byteCount = (packet.Length - 3) % 4; uint key = sender.GetCRCSeed(); // Decrypt the blocks of 4 bytes for (int i = 0; i < blockCount; i++) { uint temp = reader.ReadUInt32(); uint value = temp ^ key; key = temp; newPacket.AddUInt32(value); } // Decrypt the rest of the singular bytes byte newKey = (byte)((key >> 24) & 0xFF); for (int i = 0; i < byteCount; i++) { byte value = (byte)(reader.ReadByte() ^ newKey); newPacket.AddByte(value); } // Return the decrypted packet return newPacket.GetRaw(); }
public void DisconnectClient(SOEClient client, ushort reason, bool clientBased = false) { // Disconnect Log("Disconnecting client on {0} (ID: {1}) for reason: {2}", client.GetClientAddress(), client.GetClientID(), (SOEDisconnectReasons)reason); // Are they a connected client? if (Clients.Contains(client)) { // We don't care about them anymore // Open their ID as a space Host2ClientID.Remove(client.Client); SessionID2ClientID.Remove(client.GetSessionID()); Clients[client.GetClientID()] = null; } // Was this a disconnect request from the client itself? if (!clientBased) { // Tell them we're disconnecting them SOEWriter packetWriter = new SOEWriter((ushort)SOEOPCodes.DISCONNECT); // Arguments packetWriter.AddUInt32(client.GetSessionID()); packetWriter.AddUInt16(reason); // Send! SOEPacket packet = packetWriter.GetFinalSOEPacket(client, true, false); client.SendPacket(packet); } }
public byte[] Encrypt(SOEClient client, byte[] data) { SOEReader reader = new SOEReader(data); SOEWriter newPacket = new SOEWriter(); int blockCount = data.Length / 4; int byteCount = data.Length % 4; uint key = client.GetCRCSeed(); // Encrypt the blocks of 4 bytes for (int i = 0; i < blockCount; i++) { uint value = key = reader.ReadUInt32() ^ key; newPacket.AddUInt32(value); } // Encrypt the rest of the singular bytes byte newKey = (byte)((key >> 24) & 0xFF); for (int i = 0; i < byteCount; i++) { byte value = (byte)(reader.ReadByte() ^ newKey); newPacket.AddByte(value); } // Return the encrypted packet return newPacket.GetRaw(); }
public void SendPacket(SOEClient client, SOEPacket packet) { // Send the message UdpClient.Send(packet.GetRaw(), packet.GetLength(), client.Client); }
public SOEPacket GetFinalSOEPacket(SOEClient client, bool compressed, bool appendCRC) { // Data byte[] originalPacket = GetRaw(); byte[] rawData = new byte[Data.Count - 2]; byte[] newPacket; // Fail-safe ushort originalOpCode = 0; // Are we a message? if (IsMessage) { // Yes, so we'll try make a data packet. // Can we fit into one packet? SOEMessage message = GetFinalSOEMessage(client); if (message.IsFragmented) { // We're gonna have to fragment, so we can't handle this gracefully... client.Server.Log("[ERROR] Tried to handle 'GetFinalSOEPacket' call on written SOEMessage gracefully but failed due to fragmentation. Returning null."); client.Server.Log("[INFO] Call 'GetFinalSOEMessage' as it deals with fragmentation!"); // Welp, goodbye world! :'( return null; } // Make the new packet Data = new List<byte>(); AddUInt16(client.GetNextSequenceNumber()); AddBytes(originalPacket); // Set our raw data rawData = GetRaw(); // Change our OpCode so that we're a reliable data packet originalOpCode = OpCode; OpCode = (ushort)SOEOPCodes.RELIABLE_DATA; // Because we're reliable data, take compression into consideration and append a CRC compressed = true; appendCRC = true; // We handled it gracefully! :) client.Server.Log("[INFO] Handled 'GetFinalSOEPacket' call on written SOEMessage gracefully."); } else { // Get just the data for this packet. (Remove the OP Code) byte[] completeRawData = GetRaw(); for (int i = 2; i < completeRawData.Length; i++) { rawData[i - 2] = completeRawData[i]; } } // Start a new packet Data = new List<byte>(); AddUInt16(OpCode); // Are we compressable? if (client.IsCompressable()) { if (compressed) { AddBoolean(rawData.Length > 100); if (rawData.Length > 100) { rawData = client.Compress(rawData); } } } // Are we encrypted? if (client.IsEncrypted()) { // Encrypt the SOE Packet rawData = client.Encrypt(rawData); } // Add the raw data AddBytes(rawData); // Appended CRC32? if (appendCRC) { AddBytes(client.GetAppendedCRC32(GetRaw())); } // Set our new packet newPacket = GetRaw(); // Get our old message before compression/encryption Data = new List<byte>(originalPacket); // If we are a message, set our OpCode back if (IsMessage) { // Set our OpCode back too.. OpCode = originalOpCode; } // Return the compressed/encrypted packet return new SOEPacket(OpCode, newPacket); }
private byte[] DecompressPacket(SOEClient sender, byte[] packet) { // Compressable? if (!sender.IsCompressable()) { return packet; } // Remove the OpCode and compression flag byte[] data = new byte[packet.Length - 3]; for (int i = 3; i < packet.Length; i++) { data[i - 3] = packet[i]; } byte[] decompressedData = data; // Decompress the old packet.. MemoryStream dataStream = new MemoryStream(data); MemoryStream decompressed = new MemoryStream(); if (packet[2] == 0x01) { using (ZlibStream zlibStream = new ZlibStream(dataStream, CompressionMode.Decompress)) { zlibStream.CopyTo(decompressed); } // Reconstruct the packet.. decompressedData = decompressed.ToArray(); } // Reconstruct the packet.. byte[] newPacket = new byte[decompressedData.Length + 2]; // OpCode int place = 0; for (int i = 0; i < 2; i++) { newPacket[place] = packet[i]; place++; } // Data for (int i = 0; i < decompressedData.Length; i++) { newPacket[place] = decompressedData[i]; place++; } // And.. return! return newPacket; }