Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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;
            }
        }
Example #5
0
        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;
        }
Example #6
0
        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());
            }
        }
Example #7
0
        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);
        }
Example #8
0
        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;
            }
        }
Example #9
0
        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());
            }
        }
Example #10
0
        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();
        }
Example #11
0
        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));
        }
Example #12
0
        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);
        }
Example #13
0
        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();
        }