예제 #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);
            }
        }
예제 #2
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);
            }
        }
예제 #3
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());
        }
예제 #4
0
        private void SendFragmentedMessage(SOEMessage message)
        {
            // Are we already busy?
            if (BusySendingFragmentedPacket)
            {
                // The already-busy thread will pick up our message..
                FragmentedQueue.Enqueue(message);
                return;
            }

            // Set that we're busy IMMEDIATELY! (thread-safe)
            BusySendingFragmentedPacket = true;

            // Setup the for loop
            SOEWriter writer;
            SOEPacket packet;
            ushort    sequenceNumber;
            bool      sentInitial = false;

            // The rest aren't any different
            for (int i = 0; i < message.GetFragmentCount(); i++)
            {
                // Setup a new writer
                writer = new SOEWriter((ushort)SOEOPCodes.FRAGMENTED_RELIABLE_DATA);

                // Are we the first packet?
                if (!sentInitial)
                {
                    // Add the total message length
                    writer.AddUInt32((uint)message.GetLength());
                    sentInitial = true;
                }

                // Sequence number
                sequenceNumber = GetNextSequenceNumber();
                writer.AddUInt16(sequenceNumber);

                // Add the message fragment
                writer.AddBytes(message.GetFragment(i));

                // Get the final packet and send it!
                packet = writer.GetFinalSOEPacket(Client, true, true);
                Client.SendPacket(packet);
            }

            // Did any other thread add a fragmented packet?
            if (FragmentedQueue.Count > 0)
            {
                BusySendingFragmentedPacket = false;
                SendFragmentedMessage(FragmentedQueue.Dequeue());
            }
        }
예제 #5
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());
        }
예제 #6
0
        public static void HandleLoginRequest(LoginRequest request)
        {
            // Get variables
            string  loginServer = Server.ApplicationConfiguration["LoginServer"];
            string  apiRequest  = loginServer + "consumeToken/";
            JObject response    = null;

            using (var client = new WebClient {
                Proxy = null
            })
            {
                var values = new NameValueCollection();
                values["token"] = request.Token;

                var responseRaw    = client.UploadValues(apiRequest, values);
                var responseString = Encoding.ASCII.GetString(responseRaw);
                try
                {
                    response = JObject.Parse(responseString);
                }
                catch (Exception)
                {
                    Log.Fatal("Received bad response from login server!");
                    Environment.Exit(0);
                }
            }

            if (response != null)
            {
                bool success = response["success"].ToObject <bool>();

                if (success)
                {
                    // Get the account!
                    Account userAccount = response["account"].ToObject <Account>();

                    // Is the user banned?
                    if (userAccount.Banned)
                    {
                        // Report the attempt and disconnect them
                        Log.ErrorFormat("Received successful login for client {0} but this user is banned!",
                                        request.Client.GetClientID());
                        SendLoginResponse(request.Client, false);

                        request.Client.Disconnect((ushort)SOEDisconnectReasons.Application);
                    }
                    else
                    {
                        // Check if they're allowed to be on this server
                        if (userAccount.AccessLevel < (int)Server.ApplicationConfiguration["MinimumAccessLevel"])
                        {
                            // Log the attempt
                            Log.ErrorFormat("Received successful login for client {0} but this user doesn't meet the required minimum access level!",
                                            request.Client.GetClientID());
                            SendLoginResponse(request.Client, false);

                            // Disconnect them
                            request.Client.Disconnect((ushort)SOEDisconnectReasons.Application);
                            return;
                        }

                        // Send the succesful login response!
                        Log.Info("Successful login!");
                        SendLoginResponse(request.Client, true);

                        // Manage the account on the gateway
                        AccountManager.AddAccount(request.Client, userAccount);

                        // Send the connection to the world server
                        // Server.InternalManager.GetConnection("World").RouteConnection(request.Client, response.ToString());
                        // Gateway.InternalWorldConnection.RouteConnection(request.Client, response.ToString());

                        // The world server will then do a: 'Which internal connection is managing this connection?',
                        // assign the client a world-clientID, map clients to internal servers, and then send packets
                        // to us with a tagged "reciever". "reciever" will be the clientId on our side..

                        // Gateway1 -> { Client, 0x01 } -> World { Client, Gateway1, 0x01, 0x04 }
                        // Client (0x01) <- Gateway1 <- { 0x01, data } <- World { 0x04 -> 0x01 (Gateway1) }

                        // TODO: ^

                        // The world server would then send the client the Environment, World, Character, etc..
                        // For now, send that stuff from the gateway:

                        // Environment
                        SOEWriter commandWriter = new SOEWriter(0xA6, true);
                        commandWriter.AddASCIIString("live");
                        byte[] environmentCommand = commandWriter.GetRaw();

                        SOEWriter writer = new SOEWriter((ushort)GatewayMessages.EnqueueCommand, true);
                        writer.AddBoolean(true);
                        writer.AddHostUInt32((uint)environmentCommand.Length);
                        writer.AddBytes(environmentCommand);
                        SOEMessage environmentMessage = writer.GetFinalSOEMessage(request.Client);

                        // ZoneInfo
                        commandWriter = new SOEWriter(0x2B, true);
                        commandWriter.AddASCIIString("FabledRealms");
                        commandWriter.AddHostUInt32(2);
                        commandWriter.AddHostUInt32(0);
                        commandWriter.AddHostUInt32(0);
                        commandWriter.AddUInt32(5);
                        commandWriter.AddHostUInt32(0);
                        commandWriter.AddBoolean(false);
                        byte[] worldCommand = commandWriter.GetRaw();

                        writer = new SOEWriter((ushort)GatewayMessages.EnqueueCommand, true);
                        writer.AddBoolean(true);
                        writer.AddHostUInt32((uint)worldCommand.Length);
                        writer.AddBytes(worldCommand);
                        SOEMessage worldMessage = writer.GetFinalSOEMessage(request.Client);

                        // Send!
                        request.Client.SendMessage(environmentMessage);
                        request.Client.SendMessage(worldMessage);
                    }
                }
                else
                {
                    // Send an unsucessful login response
                    Log.ErrorFormat("Received invalid token from client {0}!", request.Client.GetClientID());
                    SendLoginResponse(request.Client, false);

                    // Disconnect the requesting Client
                    request.Client.Disconnect((ushort)SOEDisconnectReasons.Application);
                }
            }
        }