public static void HandleLoginRequest(SOEClient sender, SOEMessage message) { // Setup a reader SOEReader reader = new SOEReader(message); // Get the login details string clientToken = reader.ReadASCIIString(); reader.ReadUInt64(); string clientVersion = reader.ReadASCIIString(); // Correct client version? Log.DebugFormat("Received login request from client {0}, token: {1}, version: {2}", sender.GetClientID(), clientToken, clientVersion); string expectedClientVersion = Server.ApplicationConfiguration["ClientVersion"]; if (clientVersion != expectedClientVersion) { // Error! Log.ErrorFormat("Received login request from outdated client: {0}", clientVersion); SendLoginResponse(sender, false); sender.Disconnect((ushort)SOEDisconnectReasons.Application); return; } // Create a login request and enqueue it LoginRequest request = new LoginRequest(sender, clientToken, clientVersion); LoginQueue.Enqueue(request); }
public SOEReader(SOEMessage message) { Stream = new MemoryStream(message.GetRaw()); // Skip the message OpCode ReadHostInt16(); }
public SOEWriter(SOEMessage message) { // Message information Data = new List<byte>(message.GetRaw()); OpCode = message.GetOpCode(); // We're a message! IsMessage = true; }
public static void SendLoginResponse(SOEClient client, bool success) { // Login Reply SOEWriter writer = new SOEWriter((ushort)LoginMessages.LoginResponse, true); // Success? writer.AddBoolean(success); // Send the reply! SOEMessage reply = writer.GetFinalSOEMessage(client); client.SendMessage(reply); }
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 static void HandleEnqueueCommand(SOEClient sender, SOEMessage message) { // Is this client even authed? if (AccountManager.GetAccount(sender) == null) { Log.ErrorFormat("Unauthorized client tried enqueing command!"); sender.Disconnect((ushort)SOEDisconnectReasons.Terminated); return; } // Setup a reader SOEReader reader = new SOEReader(message); // Get the length bool hasLength = reader.ReadBoolean(); // assuming this even is "has length" or just a random 01 byte[] command = hasLength ? reader.ReadBlob() : reader.ReadToEnd(); // Handle command! HandleCommand(sender, command); }
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()); } }
public void SendMessage(SOEMessage message) { // Send the message through the data channel DataChannel.Send(message); // This client is still alive Interact(); }
private void SendMessage(SOEMessage message) { // Setup a writer SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.RELIABLE_DATA); // Sequence number ushort sequenceNumber = GetNextSequenceNumber(); writer.AddUInt16(sequenceNumber); // Add the message writer.AddMessage(message); // Get the final packet and send it! SOEPacket packet = writer.GetFinalSOEPacket(Client, true, true); Client.SendPacket(packet); // TODO repeat-till-acknowledged }
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()); } }
public void Send(SOEMessage message) { if (message.IsFragmented) { SendFragmentedMessage(message); } else { SendMessage(message); } }
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); } } }
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 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); }