public static async void HandleConnectResponse(ClientPacket packet, Session session) { ulong check = packet.Payload.ReadUInt64(); // 13626398284849559039 - sent in previous packet var result = await DatabaseManager.Character.SelectPreparedStatementAsync(CharacterPreparedStatement.CharacterListSelect, session.Id); CharacterListSelectCallback(result, session); // looks like account settings/info, expansion information ect? (this is needed for world entry) var packet75e5 = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var packet75e5Fragment = new ServerPacketFragment(5, FragmentOpcode.Unknown75E5); packet75e5Fragment.Payload.Write(1ul); packet75e5Fragment.Payload.Write(1ul); packet75e5Fragment.Payload.Write(1ul); packet75e5Fragment.Payload.Write(2ul); packet75e5Fragment.Payload.Write(0ul); packet75e5Fragment.Payload.Write(1ul); packet75e5.Fragments.Add(packet75e5Fragment); NetworkManager.SendPacket(ConnectionType.Login, packet75e5, session); var patchStatus = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); patchStatus.Fragments.Add(new ServerPacketFragment(5, FragmentOpcode.PatchStatus)); NetworkManager.SendPacket(ConnectionType.Login, patchStatus, session); }
public static async void CharacterDelete(ClientPacketFragment fragment, Session session) { string account = fragment.Payload.ReadString16L(); uint characterSlot = fragment.Payload.ReadUInt32(); if (account != session.Account) { session.SendCharacterError(CharacterError.Delete); return; } var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.SlotId == characterSlot); if (cachedCharacter == null) { session.SendCharacterError(CharacterError.Delete); return; } // TODO: check if character is already pending removal var characterDelete = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var characterDeleteFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterDelete); characterDelete.Fragments.Add(characterDeleteFragment); NetworkManager.SendPacket(ConnectionType.Login, characterDelete, session); DatabaseManager.Character.DeleteOrRestore(WorldManager.GetUnixTime() + 3600ul, cachedCharacter.Guid.Low); var result = await DatabaseManager.Character.GetByAccount(session.Id); AuthenticationHandler.CharacterListSelectCallback(result, session); }
public void SendCharacterError(CharacterError error) { var characterError = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var characterErrorFragment = new ServerPacketFragment(0x09, GameMessageOpcode.CharacterError); characterErrorFragment.Payload.Write((uint)error); characterError.Fragments.Add(characterErrorFragment); NetworkManager.SendPacket(ConnectionType.Login, characterError, this); }
private ServerPacketFragment CreateServerFragment(ushort index) { log.DebugFormat("Creating ServerFragment for index {0}", index); if (index >= Count) { throw new ArgumentOutOfRangeException("index", index, "Passed index is greater then computed count"); } var position = index * ServerPacketFragment.MaxFragmentDataSize; if (position > DataLength) { throw new ArgumentOutOfRangeException("index", index, "Passed index computes to invalid position size"); } if (DataRemaining <= 0) { throw new InvalidOperationException("There is no data remaining"); } var dataToSend = DataLength - position; if (dataToSend > ServerPacketFragment.MaxFragmentDataSize) { dataToSend = ServerPacketFragment.MaxFragmentDataSize; } if (DataRemaining < dataToSend) { throw new InvalidOperationException("More data to send then data remaining!"); } // Read data starting at position reading dataToSend bytes Message.Data.Seek(position, SeekOrigin.Begin); byte[] data = new byte[dataToSend]; Message.Data.Read(data, 0, (int)dataToSend); // Build ServerPacketFragment structure ServerPacketFragment fragment = new ServerPacketFragment(data); fragment.Header.Sequence = Sequence; fragment.Header.Id = 0x80000000; fragment.Header.Count = Count; fragment.Header.Index = index; fragment.Header.Group = (ushort)Message.Group; DataRemaining -= dataToSend; log.DebugFormat("Done creating ServerFragment for index {0}. After reading {1} DataRemaining {2}", index, dataToSend, DataRemaining); return(fragment); }
private static void SendCharacterCreateResponse(Session session, CharacterGenerationVerificationResponse response, ObjectGuid guid = null, string charName = "") { var charCreateResponse = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var charCreateFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterCreateResponse); charCreateFragment.Payload.Write((uint)response); if (response == CharacterGenerationVerificationResponse.Ok) { charCreateFragment.Payload.WriteGuid(guid); charCreateFragment.Payload.WriteString16L(charName); charCreateFragment.Payload.Write(0u); } charCreateResponse.Fragments.Add(charCreateFragment); NetworkManager.SendPacket(ConnectionType.Login, charCreateResponse, session); }
public static void SendServerMessage(Session session, string message, ChatMessageType chatMessageType) { var textboxString = new ServerPacket(0x18, PacketHeaderFlags.EncryptedChecksum); var textboxStringFragment = new ServerPacketFragment(0x09, GameMessageOpcode.ServerMessage); textboxStringFragment.Payload.WriteString16L(message); textboxStringFragment.Payload.Write((int)chatMessageType); textboxString.Fragments.Add(textboxStringFragment); if (session == null) { // TODO: broadcast } else { NetworkManager.SendPacket(ConnectionType.World, textboxString, session); } }
private static void SendCharacterCreateResponse(Session session, uint responseCode, uint guid = 0, string charName = null) { var charCreateResponse = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var charCreateFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterCreateResponse); if (responseCode == 1) { charCreateFragment.Payload.Write(responseCode); charCreateFragment.Payload.Write(guid); charCreateFragment.Payload.WriteString16L(charName); charCreateFragment.Payload.Write(0u); } else { charCreateFragment.Payload.Write(responseCode); } charCreateResponse.Fragments.Add(charCreateFragment); NetworkManager.SendPacket(ConnectionType.Login, charCreateResponse, session); }
public static void CharacterListSelectCallback(MySqlResult result, Session session) { var characterList = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var characterFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterList); characterFragment.Payload.Write(0u); characterFragment.Payload.Write(result.Count); session.CachedCharacters.Clear(); for (byte i = 0; i < result.Count; i++) { uint lowGuid = result.Read <uint>(i, "guid"); string name = result.Read <string>(i, "name"); characterFragment.Payload.Write(lowGuid); characterFragment.Payload.WriteString16L(name); ulong deleteTime = result.Read <ulong>(i, "deleteTime"); characterFragment.Payload.Write(deleteTime != 0ul ? (uint)(WorldManager.GetUnixTime() - deleteTime) : 0u); session.CachedCharacters.Add(new CachedCharacter(lowGuid, i, name)); } characterFragment.Payload.Write(0u); characterFragment.Payload.Write(11u /*slotCount*/); characterFragment.Payload.WriteString16L(session.Account); characterFragment.Payload.Write(0u /*useTurbineChat*/); characterFragment.Payload.Write(0u /*hasThroneOfDestiny*/); characterList.Fragments.Add(characterFragment); NetworkManager.SendPacket(ConnectionType.Login, characterList, session); var serverName = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var serverNameFragment = new ServerPacketFragment(9, FragmentOpcode.ServerName); serverNameFragment.Payload.Write(0u); serverNameFragment.Payload.Write(0u); serverNameFragment.Payload.WriteString16L(ConfigManager.Config.Server.WorldName); serverName.Fragments.Add(serverNameFragment); NetworkManager.SendPacket(ConnectionType.Login, serverName, session); }
public static void CharacterRestore(ClientPacketFragment fragment, Session session) { ObjectGuid guid = fragment.Payload.ReadGuid(); var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full); if (cachedCharacter == null) { return; } DatabaseManager.Character.DeleteOrRestore(0, guid.Low); var characterRestore = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var characterRestoreFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterRestoreResponse); characterRestoreFragment.Payload.Write(1u /* Verification OK flag */); characterRestoreFragment.Payload.WriteGuid(guid); characterRestoreFragment.Payload.WriteString16L(cachedCharacter.Name); characterRestoreFragment.Payload.Write(0u /* secondsGreyedOut */); characterRestore.Fragments.Add(characterRestoreFragment); NetworkManager.SendPacket(ConnectionType.Login, characterRestore, session); }
public static void CharacterListSelectCallback(List <CachedCharacter> characters, Session session) { var characterList = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var characterFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterList); characterFragment.Payload.Write(0u); characterFragment.Payload.Write(characters.Count); session.CachedCharacters.Clear(); foreach (var character in characters) { characterFragment.Payload.Write(character.LowGuid); characterFragment.Payload.WriteString16L(character.Name); characterFragment.Payload.Write(character.DeleteTime != 0ul ? (uint)(WorldManager.GetUnixTime() - character.DeleteTime) : 0u); session.CachedCharacters.Add(character); } characterFragment.Payload.Write(0u); characterFragment.Payload.Write(11u /*slotCount*/); characterFragment.Payload.WriteString16L(session.Account); characterFragment.Payload.Write(0u /*useTurbineChat*/); characterFragment.Payload.Write(0u /*hasThroneOfDestiny*/); characterList.Fragments.Add(characterFragment); NetworkManager.SendPacket(ConnectionType.Login, characterList, session); var serverName = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var serverNameFragment = new ServerPacketFragment(9, FragmentOpcode.ServerName); serverNameFragment.Payload.Write(0u); serverNameFragment.Payload.Write(0u); serverNameFragment.Payload.WriteString16L(ConfigManager.Config.Server.WorldName); serverName.Fragments.Add(serverNameFragment); NetworkManager.SendPacket(ConnectionType.Login, serverName, session); }
// TODO: packet pipe really needs a rework... private static bool ConstructPacket(out byte[] buffer, ConnectionType type, ServerPacket packet, Session session, bool useHeaders = false) { var connectionData = (type == ConnectionType.Login ? session.LoginConnection : session.WorldConnection); using (var packetStream = new MemoryStream()) { using (var packetWriter = new BinaryWriter(packetStream)) { packetWriter.Seek((int)PacketHeader.HeaderSize, SeekOrigin.Begin); packetWriter.Write(packet.Data.ToArray()); if (packet.Fragments.Count > 0) { packet.Header.Flags |= PacketHeaderFlags.BlobFragments; for (int i = 0; i < packet.Fragments.Count; i++) { var fragment = (ServerPacketFragment)packet.Fragments[i]; uint fragmentsRequired = ((uint)fragment.Data.Length / PacketFragment.MaxFragmentDataSize); if ((fragment.Data.Length % PacketFragment.MaxFragmentDataSize) != 0) { fragmentsRequired++; } if (fragmentsRequired > 1u) { fragment.Data.Seek(0L, SeekOrigin.Begin); uint dataToSend = (uint)fragment.Data.Length; uint fragmentSeq = connectionData.FragmentSequence++; for (uint j = 0u; j < fragmentsRequired; j++) { uint fragmentSize = dataToSend > PacketFragment.MaxFragmentDataSize ? PacketFragment.MaxFragmentDataSize : dataToSend; byte[] data = new byte[fragmentSize]; fragment.Data.Read(data, 0, (int)fragmentSize); var newPacket = new ServerPacket(packet.Header.Id, PacketHeaderFlags.EncryptedChecksum | PacketHeaderFlags.BlobFragments); var newFragment = new ServerPacketFragment(fragment.Header.Group); newFragment.Header.Sequence = fragmentSeq; newFragment.Header.Id = 0x80000000; newFragment.Header.Count = (ushort)fragmentsRequired; newFragment.Header.Index = (ushort)j; newFragment.Data.Write(data, 0, (int)fragmentSize); newPacket.Fragments.Add(newFragment); SendPacket(type, newPacket, session, true); dataToSend -= fragmentSize; } buffer = null; return(false); } fragment.Header.Size = (ushort)(PacketFragmentHeader.HeaderSize + fragment.Payload.BaseStream.Length); if (!useHeaders) { fragment.Header.Sequence = connectionData.FragmentSequence++; fragment.Header.Id = 0x80000000; // this seems to be a global incremental value fragment.Header.Count = 1; fragment.Header.Index = (ushort)i; } packetWriter.Write(fragment.Header.GetRaw()); packetWriter.Write(fragment.Data.ToArray()); } } if (packet.Header.HasFlag(PacketHeaderFlags.EncryptedChecksum) && connectionData.PacketSequence < 2) { connectionData.PacketSequence = 2; } packet.Header.Sequence = connectionData.PacketSequence++; packet.Header.Size = (ushort)(packetWriter.BaseStream.Length - PacketHeader.HeaderSize); packet.Header.Table = 0x14; packet.Header.Time = (ushort)connectionData.ServerTime; uint issacXor; packet.Header.Checksum = packet.CalculateChecksum(session, type, 0u, out issacXor); packetWriter.Seek(0, SeekOrigin.Begin); packetWriter.Write(packet.Header.GetRaw()); if (type == ConnectionType.World && packet.Header.Sequence >= 2u) { session.CachedPackets.TryAdd(packet.Header.Sequence, new CachedPacket(issacXor, packet)); } buffer = packetStream.ToArray(); return(true); } } }
/// <summary> /// This function handles turning a bundle of messages (representing all messages accrued in a timeslice), /// into 1 or more packets, combining multiple messages into one packet or spliting large message across /// several packets as needed. /// /// 1 Create Packet /// 2 If first packet for this bundle, fill any optional headers /// 3 Append messages that will fit /// 4 If we have more messages, create additional packets. /// 5 If any packet is greater than the max packet size, split it across two fragments /// </summary> /// <param name="bundle"></param> private void SendBundle(NetworkBundle bundle) { bool firstPacket = true; MessageFragment carryOverMessage = null; while (firstPacket || carryOverMessage != null || bundle.Messages.Count > 0) { ServerPacket packet = new ServerPacket(); PacketHeader packetHeader = packet.Header; if (bundle.EncryptedChecksum) { packetHeader.Flags |= PacketHeaderFlags.EncryptedChecksum; } uint availableSpace = Packet.MaxPacketDataSize; if (firstPacket) { firstPacket = false; if (bundle.SendAck) //0x4000 { packetHeader.Flags |= PacketHeaderFlags.AckSequence; packet.BodyWriter.Write(lastReceivedSequence); } if (bundle.TimeSync) //0x1000000 { packetHeader.Flags |= PacketHeaderFlags.TimeSynch; packet.BodyWriter.Write(ConnectionData.ServerTime); } if (bundle.ClientTime != -1f) //0x4000000 { packetHeader.Flags |= PacketHeaderFlags.EchoResponse; packet.BodyWriter.Write(bundle.ClientTime); packet.BodyWriter.Write((float)ConnectionData.ServerTime - bundle.ClientTime); } availableSpace -= (uint)packet.Data.Length; } if (carryOverMessage != null || bundle.Messages.Count > 0) { packetHeader.Flags |= PacketHeaderFlags.BlobFragments; int fragmentCount = 0; while (carryOverMessage != null || bundle.Messages.Count > 0) { MessageFragment currentMessageFragment; if (carryOverMessage != null) // If we have a carryOverMessage, use that { currentMessageFragment = carryOverMessage; carryOverMessage = null; } else // If we don't have a carryOverMessage, go ahead and dequeue next message from the bundle { currentMessageFragment = new MessageFragment(bundle.Messages.Dequeue()); } var currentGameMessage = currentMessageFragment.message; availableSpace -= PacketFragmentHeader.HeaderSize; // Account for fragment header // Compute amount of data to send based on the total length and current position uint dataToSend = (uint)currentGameMessage.Data.Length - currentMessageFragment.position; if (dataToSend > availableSpace) // Message is too large to fit in packet { carryOverMessage = currentMessageFragment; if (fragmentCount == 0) // If this is first message in packet, this is just a really large message, so proceed with splitting it { dataToSend = availableSpace; } else // Otherwise there are other messages already, so we'll break and come back and see if the message will fit { break; } } if (currentMessageFragment.count == 0) // Compute number of fragments if we have not already { uint remainingData = (uint)currentGameMessage.Data.Length - dataToSend; currentMessageFragment.count = (ushort)(Math.Ceiling((double)remainingData / PacketFragment.MaxFragmentDataSize) + 1); } // Set sequence, if new, pull next sequence from ConnectionData, if it is a carryOver, reuse that sequence currentMessageFragment.sequence = currentMessageFragment.sequence == 0 ? ConnectionData.FragmentSequence++ : currentMessageFragment.sequence; // Build ServerPacketFragment structure ServerPacketFragment fragment = new ServerPacketFragment(); PacketFragmentHeader fragmentHeader = fragment.Header; fragmentHeader.Sequence = currentMessageFragment.sequence; fragmentHeader.Id = 0x80000000; fragmentHeader.Count = currentMessageFragment.count; fragmentHeader.Index = currentMessageFragment.index; fragmentHeader.Group = (ushort)currentMessageFragment.message.Group; // Read data starting at current position reading dataToSend bytes currentGameMessage.Data.Seek(currentMessageFragment.position, SeekOrigin.Begin); fragment.Content = new byte[dataToSend]; currentGameMessage.Data.Read(fragment.Content, 0, (int)dataToSend); // Increment position and index currentMessageFragment.position = currentMessageFragment.position + dataToSend; currentMessageFragment.index++; // Add fragment to packet packet.AddFragment(fragment); fragmentCount++; // Deduct consumed space availableSpace -= dataToSend; // Smallest message I am aware of requires HeaderSize + 4 bytes, so if we have less space then that, go ahead and break if (availableSpace <= PacketFragmentHeader.HeaderSize + 4) { break; } } } PacketQueue.Enqueue(packet); } }
/// <summary> /// This function handles turning a bundle of messages (representing all messages accrued in a timeslice), /// into 1 or more packets, combining multiple messages into one packet or spliting large message across /// several packets as needed. /// /// 1 Create Packet /// 2 If first packet for this bundle, fill any optional headers /// 3 Append fragments that will fit /// 3.1 Check each fragment to see if it is a partial fit /// 4 If we have a partial message remaining or more messages, create additional packets. /// </summary> /// <param name="bundle"></param> private void SendBundle(NetworkBundle bundle) { bool firstPacket = true; MessageFragment carryOverMessage = null; while (firstPacket || carryOverMessage != null || bundle.Messages.Count > 0) { ServerPacket packet = new ServerPacket(); PacketHeader packetHeader = packet.Header; if (bundle.encryptedChecksum) { packetHeader.Flags |= PacketHeaderFlags.EncryptedChecksum; } uint availableSpace = Packet.MaxPacketDataSize; if (firstPacket) { firstPacket = false; if (bundle.SendAck) //0x4000 { packetHeader.Flags |= PacketHeaderFlags.AckSequence; packet.BodyWriter.Write(lastReceivedSequence); } if (bundle.TimeSync) //0x1000000 { packetHeader.Flags |= PacketHeaderFlags.TimeSynch; packet.BodyWriter.Write(ConnectionData.ServerTime); } if (bundle.ClientTime != -1f) //0x4000000 { packetHeader.Flags |= PacketHeaderFlags.EchoResponse; packet.BodyWriter.Write(bundle.ClientTime); packet.BodyWriter.Write((float)ConnectionData.ServerTime - bundle.ClientTime); } availableSpace -= (uint)packet.Data.Length; } if (carryOverMessage != null || bundle.Messages.Count > 0) { packetHeader.Flags |= PacketHeaderFlags.BlobFragments; while (carryOverMessage != null || bundle.Messages.Count > 0) { if (availableSpace <= PacketFragmentHeader.HeaderSize + 4) { break; } MessageFragment currentMessageFragment; if (carryOverMessage != null) { currentMessageFragment = carryOverMessage; carryOverMessage = null; currentMessageFragment.index++; } else { currentMessageFragment = new MessageFragment(bundle.Messages.Dequeue()); } var currentGameMessage = currentMessageFragment.message; ServerPacketFragment fragment = new ServerPacketFragment(); PacketFragmentHeader fragmentHeader = fragment.Header; availableSpace -= PacketFragmentHeader.HeaderSize; currentMessageFragment.sequence = currentMessageFragment.sequence == 0 ? ConnectionData.FragmentSequence++ : currentMessageFragment.sequence; uint dataToSend = (uint)currentGameMessage.Data.Length - currentMessageFragment.position; if (dataToSend > availableSpace) { dataToSend = availableSpace; carryOverMessage = currentMessageFragment; } if (currentMessageFragment.count == 0) { uint remainingData = (uint)currentGameMessage.Data.Length - dataToSend; currentMessageFragment.count = (ushort)(Math.Ceiling((double)remainingData / PacketFragment.MaxFragmentDataSize) + 1); } fragmentHeader.Sequence = currentMessageFragment.sequence; fragmentHeader.Id = 0x80000000; fragmentHeader.Count = currentMessageFragment.count; fragmentHeader.Index = currentMessageFragment.index; fragmentHeader.Group = (ushort)currentMessageFragment.message.Group; currentGameMessage.Data.Seek(currentMessageFragment.position, SeekOrigin.Begin); fragment.Content = new byte[dataToSend]; currentGameMessage.Data.Read(fragment.Content, 0, (int)dataToSend); currentMessageFragment.position = currentMessageFragment.position + dataToSend; availableSpace -= dataToSend; packet.AddFragment(fragment); //break; } } PacketQueue.Enqueue(packet); } }
/// <summary> /// This function handles turning a bundle of messages (representing all messages accrued in a timeslice), /// into 1 or more packets, combining multiple messages into one packet or spliting large message across /// several packets as needed. /// </summary> /// <param name="bundle"></param> private void SendBundle(NetworkBundle bundle) { log.DebugFormat("[{0}] Sending Bundle", session.LoggingIdentifier); bool writeOptionalHeaders = true; List <MessageFragment> fragments = new List <MessageFragment>(); // Pull all messages out and create MessageFragment objects while (bundle.HasMoreMessages) { var message = bundle.Dequeue(); var fragment = new MessageFragment(message, ConnectionData.FragmentSequence++); fragments.Add(fragment); } log.DebugFormat("[{0}] Bundle Fragment Count: {1}", session.LoggingIdentifier, fragments.Count); // Loop through while we have fragements while (fragments.Count > 0 || writeOptionalHeaders) { ServerPacket packet = new ServerPacket(); PacketHeader packetHeader = packet.Header; if (fragments.Count > 0) { packetHeader.Flags |= PacketHeaderFlags.BlobFragments; } if (bundle.EncryptedChecksum) { packetHeader.Flags |= PacketHeaderFlags.EncryptedChecksum; } uint availableSpace = Packet.MaxPacketDataSize; // Pull first message and see if it is a large one var firstMessage = fragments.FirstOrDefault(); if (firstMessage != null) { // If a large message send only this one, filling the whole packet if (firstMessage.DataRemaining >= availableSpace) { log.DebugFormat("[{0}] Sending large fragment", session.LoggingIdentifier); ServerPacketFragment spf = firstMessage.GetNextFragment(); packet.Fragments.Add(spf); availableSpace -= (uint)spf.Length; if (firstMessage.DataRemaining <= 0) { fragments.Remove(firstMessage); } } // Otherwise we'll write any optional headers and process any small messages that will fit else { if (writeOptionalHeaders) { writeOptionalHeaders = false; WriteOptionalHeaders(bundle, packet); availableSpace -= (uint)packet.Data.Length; } // Create a list to remove completed messages after iterator List <MessageFragment> removeList = new List <MessageFragment>(); foreach (MessageFragment fragment in fragments) { // Is this a large fragment and does it have a tail that needs sending? if (!fragment.TailSent && availableSpace >= fragment.TailSize) { log.DebugFormat("[{0}] Sending tail fragment", session.LoggingIdentifier); ServerPacketFragment spf = fragment.GetTailFragment(); packet.Fragments.Add(spf); availableSpace -= (uint)spf.Length; } // Otherwise will this message fit in the remaining space? else if (availableSpace >= fragment.NextSize) { log.DebugFormat("[{0}] Sending small message", session.LoggingIdentifier); ServerPacketFragment spf = fragment.GetNextFragment(); packet.Fragments.Add(spf); availableSpace -= (uint)spf.Length; } // If message is out of data, set to remove it if (fragment.DataRemaining <= 0) { removeList.Add(fragment); } } // Remove all completed messages fragments.RemoveAll(x => removeList.Contains(x)); } } // If no messages, write optional headers else { log.DebugFormat("[{0}] No messages, just sending optional headers", session.LoggingIdentifier); if (writeOptionalHeaders) { writeOptionalHeaders = false; WriteOptionalHeaders(bundle, packet); availableSpace -= (uint)packet.Data.Length; } } EnqueueSend(packet); } }
public void AddFragment(ServerPacketFragment fragment) { fragments.Add(fragment); }