public ServerPacketFragment(GameMessageOnChannel message) { Opcode = message.Opcode; Data = message.Data; Payload = new BinaryWriter(Data); Header = new PacketFragmentHeader() { Group = (ushort)message.Channel }; }
public ServerPacketFragment(ushort group, GameMessage message) { Opcode = message.Opcode; Data = message.Data; Payload = new BinaryWriter(Data); Header = new PacketFragmentHeader() { Group = group }; }
public ServerPacketFragment(ushort group, GameMessageOpcode opcode = GameMessageOpcode.None) { Opcode = opcode; Data = new MemoryStream((int)MaxFragmentDataSize); Payload = new BinaryWriter(Data); Header = new PacketFragmentHeader() { Group = group }; if (opcode != GameMessageOpcode.None) { Payload.Write((uint)opcode); } }
public ServerPacketFragment() { Header = new PacketFragmentHeader(); }
/// <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); } }
public ClientPacketFragment(BinaryReader payload) { Header = new PacketFragmentHeader(payload); Data = new MemoryStream(payload.ReadBytes((int)(Header.Size - PacketFragmentHeader.HeaderSize))); Payload = new BinaryReader(Data); }
public ServerPacketFragment(byte[] data) { Header = new PacketFragmentHeader(); Data = data; }
public ClientPacketFragment(BinaryReader payload) { Header = new PacketFragmentHeader(payload); Data = payload.ReadBytes((int)(Header.Size - PacketFragmentHeader.HeaderSize)); }