예제 #1
0
        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);
        }
예제 #2
0
        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());
        }
예제 #3
0
        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);
        }
예제 #4
0
        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());
        }
예제 #5
0
        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);
        }
예제 #6
0
 public void ReceiveMessage(SOEClient sender, byte[] rawMessage)
 {
     if (WANT_MESSAGE_THREADING)
     {
         IncomingMessages.Enqueue(new SOEPendingMessage(sender, rawMessage));
     }
     else
     {
         Protocol.HandleMessage(sender, rawMessage);
     }
 }
예제 #7
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);
        }
예제 #8
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);
            }
        }
예제 #9
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);
            }
        }
예제 #10
0
        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;
            }
        }
예제 #11
0
        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>();
        }
예제 #12
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);
            }
        }
예제 #13
0
        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>();
        }
예제 #14
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);
            }
        }
예제 #15
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;
            }
        }
예제 #16
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());
        }
예제 #17
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;
            }
        }
예제 #18
0
        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);
            }
        }
예제 #19
0
        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();
            }
        }
예제 #20
0
        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();
        }
예제 #21
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));
        }
예제 #22
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);
        }
예제 #23
0
 public SOEPendingMessage(SOEClient sender, byte[] packet)
 {
     Client = sender;
     Message = packet;
 }
예제 #24
0
        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();
            }
        }
예제 #25
0
        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);
            }
        }
예제 #26
0
 public void ReceiveMessage(SOEClient sender, byte[] rawMessage)
 {
     if (WANT_MESSAGE_THREADING)
     {
         IncomingMessages.Enqueue(new SOEPendingMessage(sender, rawMessage));
     }
     else
     {
         Protocol.HandleMessage(sender, rawMessage);
     }
 }
예제 #27
0
 public SOEPendingPacket(SOEClient sender, byte[] packet)
 {
     Client = sender;
     Packet = packet;
 }
예제 #28
0
 public SOEPendingMessage(SOEClient sender, byte[] packet)
 {
     Client  = sender;
     Message = packet;
 }
예제 #29
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;
        }
예제 #30
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();
        }
예제 #31
0
        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);
            }
        }
예제 #32
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();
        }
예제 #33
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));
        }
예제 #34
0
 public void SendPacket(SOEClient client, SOEPacket packet)
 {
     // Send the message
     UdpClient.Send(packet.GetRaw(), packet.GetLength(), client.Client);
 }
예제 #35
0
        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);
        }
예제 #36
0
 public SOEPendingPacket(SOEClient sender, byte[] packet)
 {
     Client = sender;
     Packet = packet;
 }
예제 #37
0
        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;
        }
예제 #38
0
        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;
            }
        }
예제 #39
0
 public void SendPacket(SOEClient client, SOEPacket packet)
 {
     // Send the message
     UdpClient.Send(packet.GetRaw(), packet.GetLength(), client.Client);
 }