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 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); }
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 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; } }
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; }
public void AddMessage(SOEMessage message) { if (IsMessage) { // Handle multi messages if (OpCode == (ushort)SOEOPCodes.MULTI_MESSAGE) { if (message.GetOpCode() == (ushort)SOEOPCodes.MULTI_MESSAGE) { // Setup a reader SOEReader reader = new SOEReader(message); // Get the messages and add them byte[] messages = reader.ReadToEnd(); AddBytes(messages); } else { // Get the size of the message int size = message.GetLength(); // Is the size bigger than 255? if (size > 0xFF) { // Do the stupid >255 thing AddByte(0xFF); size -= 0xFF; // Get how many bytes to add byte toAdd = (byte)((size / 0xFF) + (size % 0xFF) & 0xFF); AddByte(toAdd); // Add sizes until we're at a value of 0 while (size > 0) { // Do we not want to add 0xFF? if (size < 0xFF) { // Add the rest of the size AddByte((byte)size); size = 0; } else { // Add 0xFF AddByte(0xFF); size -= 0xFF; } } } else { // Just do the regular size adding AddByte((byte)(size & 0xFF)); } // Add the actual message AddBytes(message.GetRaw()); } } } else { // Just add the message AddBytes(message.GetRaw()); } }
private void ReceiveMessage(SOEPacket packet) { SOEReader reader = new SOEReader(packet); // Have we received in order? ushort sequenceNumber = reader.ReadUInt16(); if ((sequenceNumber != LastReceivedSequenceNumber + 1) && (sequenceNumber != 0)) { ReceivedSequenceOutOfOrder(sequenceNumber); return; } // Acknowledge Acknowledge(sequenceNumber); LastReceivedSequenceNumber = sequenceNumber; // Get the SOEMessage byte[] data = reader.ReadToEnd(); // Handle! Client.ReceiveMessage(data); }
private void ReceiveFragment(SOEPacket packet) { // Setup a reader SOEReader reader = new SOEReader(packet); reader.ReadUInt16(); // Have we already started a fragmented packet? if (StartedFragmentedPacket) { // One less fragment till we need to acknowledge! FragmentsTillAck--; // Get our sequence number uint previousFragmentSequenceNumber = FragmentSequenceNumber; FragmentSequenceNumber = reader.ReadUInt16(); // Did we get a correct sequence number? if (FragmentSequenceNumber != previousFragmentSequenceNumber + 1) { // Out of order! ReceivedSequenceOutOfOrder(FragmentSequenceNumber); return; } // Append the rest of the packet to the fragmented data for (int i = 4; i < FragmentedData.Length; i++) { FragmentedData[ReceivedFragmentsSize] = reader.ReadByte(); ReceivedFragmentsSize++; } } else { // We're expecting the starting packet FragmentSequenceNumber = reader.ReadUInt16(); uint totalSize = reader.ReadUInt32(); // Is this a valid sequence number? if ((FragmentSequenceNumber != LastReceivedSequenceNumber + 1) && (FragmentSequenceNumber != 0)) { // Out of order! ReceivedSequenceOutOfOrder(FragmentSequenceNumber); return; } // Get the total size FragmentedData = new byte[totalSize]; // How many fragments till we need to acknowledge FragmentsTillAck = 4; // Append the rest of the packet to the fragmented data for (int i = 8; i < FragmentedData.Length; i++) { FragmentedData[ReceivedFragmentsSize] = reader.ReadByte(); ReceivedFragmentsSize++; } // Started a fragmented packet StartedFragmentedPacket = true; } // Are we finished with the fragmented data? if (ReceivedFragmentsSize >= FragmentedData.Length) { // Finish fragmented packet StartedFragmentedPacket = false; FragmentsTillAck = 0; // Handle the fragmented packet as a RELIABLE_DATA packet SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.RELIABLE_DATA); writer.AddBytes(FragmentedData); SOEPacket wholePacket = writer.GetFinalSOEPacket(Client, false, false); // Receive this packet! Receive(wholePacket); return; } // Do we need to acknowledge? if (FragmentsTillAck == 0) { Acknowledge(FragmentSequenceNumber); FragmentsTillAck = 5; } }
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 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 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 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(); }