Example #1
0
        /// <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, GameMessageGroup group)
        {
            packetLog.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);
            }

            packetLog.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;
                }

                int availableSpace = ServerPacket.MaxPacketSize;

                // 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)
                    {
                        packetLog.DebugFormat("[{0}] Sending large fragment", session.LoggingIdentifier);
                        ServerPacketFragment spf = firstMessage.GetNextFragment();
                        packet.Fragments.Add(spf);
                        availableSpace -= 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);
                            if (packet.Data != null)
                            {
                                availableSpace -= (int)packet.Data.Length;
                            }
                        }

                        // Create a list to remove completed messages after iterator
                        List <MessageFragment> removeList = new List <MessageFragment>();

                        foreach (MessageFragment fragment in fragments)
                        {
                            bool fragmentSkipped = false;

                            // Is this a large fragment and does it have a tail that needs sending?
                            if (!fragment.TailSent && availableSpace >= fragment.TailSize)
                            {
                                packetLog.DebugFormat("[{0}] Sending tail fragment", session.LoggingIdentifier);
                                ServerPacketFragment spf = fragment.GetTailFragment();
                                packet.Fragments.Add(spf);
                                availableSpace -= spf.Length;
                            }
                            // Otherwise will this message fit in the remaining space?
                            else if (availableSpace >= fragment.NextSize)
                            {
                                packetLog.DebugFormat("[{0}] Sending small message", session.LoggingIdentifier);
                                ServerPacketFragment spf = fragment.GetNextFragment();
                                packet.Fragments.Add(spf);
                                availableSpace -= spf.Length;
                            }
                            else
                            {
                                fragmentSkipped = true;
                            }

                            // If message is out of data, set to remove it
                            if (fragment.DataRemaining <= 0)
                            {
                                removeList.Add(fragment);
                            }

                            // UIQueue messages must go out in order. Otherwise, you might see an NPC's tells in an order that doesn't match their defined emotes.
                            if (fragmentSkipped && group == GameMessageGroup.UIQueue)
                            {
                                break;
                            }
                        }

                        // Remove all completed messages
                        fragments.RemoveAll(x => removeList.Contains(x));
                    }
                }
                // If no messages, write optional headers
                else
                {
                    packetLog.DebugFormat("[{0}] No messages, just sending optional headers", session.LoggingIdentifier);
                    if (writeOptionalHeaders)
                    {
                        writeOptionalHeaders = false;
                        WriteOptionalHeaders(bundle, packet);
                        if (packet.Data != null)
                        {
                            availableSpace -= (int)packet.Data.Length;
                        }
                    }
                }
                EnqueueSend(packet);
            }
        }
Example #2
0
        public PacketHeaderOptional(BinaryReader payload, PacketHeader header)
        {
            Header = header;
            Size   = (uint)payload.BaseStream.Position;
            BinaryWriter writer = new BinaryWriter(headerBytes);

            if (header.HasFlag(PacketHeaderFlags.ServerSwitch)) // 0x100
            {
                writer.Write(payload.ReadBytes(8));
            }

            if (header.HasFlag(PacketHeaderFlags.RequestRetransmit)) // 0x1000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 4)
                {
                    IsValid = false; return;
                }
                uint retransmitCount = payload.ReadUInt32();
                writer.Write(retransmitCount);
                RetransmitData = new List <uint>();
                for (uint i = 0u; i < retransmitCount; i++)
                {
                    if (payload.BaseStream.Length < payload.BaseStream.Position + 4)
                    {
                        IsValid = false; return;
                    }
                    uint sequence = payload.ReadUInt32();
                    writer.Write(sequence);
                    RetransmitData.Add(sequence);
                }
            }

            if (header.HasFlag(PacketHeaderFlags.RejectRetransmit)) // 0x2000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 4)
                {
                    IsValid = false; return;
                }
                uint count = payload.ReadUInt32();
                writer.Write(count);
                for (int i = 0; i < count; i++)
                {
                    if (payload.BaseStream.Length < payload.BaseStream.Position + 4)
                    {
                        IsValid = false; return;
                    }
                    writer.Write(payload.ReadBytes(4));
                }
            }

            if (header.HasFlag(PacketHeaderFlags.AckSequence)) // 0x4000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 4)
                {
                    IsValid = false; return;
                }
                AckSequence = payload.ReadUInt32();
                writer.Write(AckSequence);
            }

            if (header.HasFlag(PacketHeaderFlags.LoginRequest)) // 0x10000
            {
                long position = payload.BaseStream.Position;
                long length   = payload.BaseStream.Length - position;
                if (length < 1)
                {
                    IsValid = false; return;
                }
                byte[] loginBytes = new byte[length];
                payload.BaseStream.Read(loginBytes, (int)position, (int)length);
                writer.Write(loginBytes);
                payload.BaseStream.Position = position;
            }

            if (header.HasFlag(PacketHeaderFlags.WorldLoginRequest)) // 0x20000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 8)
                {
                    IsValid = false; return;
                }
                long position = payload.BaseStream.Position;
                writer.Write(payload.ReadBytes(8));
                payload.BaseStream.Position = position;
            }

            if (header.HasFlag(PacketHeaderFlags.ConnectResponse)) // 0x80000
            {
                long position = payload.BaseStream.Position;
                if (payload.BaseStream.Length < payload.BaseStream.Position + 8)
                {
                    IsValid = false; return;
                }
                writer.Write(payload.ReadBytes(8));
                payload.BaseStream.Position = position;
            }

            if (header.HasFlag(PacketHeaderFlags.CICMDCommand)) // 0x400000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 8)
                {
                    IsValid = false; return;
                }
                writer.Write(payload.ReadBytes(8));
            }

            if (header.HasFlag(PacketHeaderFlags.TimeSync)) // 0x1000000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 8)
                {
                    IsValid = false; return;
                }
                TimeSynch = payload.ReadDouble();
                writer.Write(TimeSynch);
            }

            if (header.HasFlag(PacketHeaderFlags.EchoRequest)) // 0x2000000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 4)
                {
                    IsValid = false; return;
                }
                EchoRequestClientTime = payload.ReadSingle();
                writer.Write(EchoRequestClientTime);
            }

            if (header.HasFlag(PacketHeaderFlags.Flow)) // 0x8000000
            {
                if (payload.BaseStream.Length < payload.BaseStream.Position + 6)
                {
                    IsValid = false; return;
                }
                FlowBytes    = payload.ReadUInt32();
                FlowInterval = payload.ReadUInt16();
                writer.Write(FlowBytes);
                writer.Write(FlowInterval);
            }

            Size = (uint)payload.BaseStream.Position - Size;
        }
Example #3
0
 public ServerPacket()
 {
     Header     = new PacketHeader();
     Data       = new MemoryStream();
     BodyWriter = new BinaryWriter(Data);
 }
Example #4
0
        public PacketHeaderOptional(BinaryReader payload, PacketHeader header)
        {
            Size = (uint)payload.BaseStream.Position;
            BinaryWriter writer = new BinaryWriter(headerBytes);

            if (header.HasFlag(PacketHeaderFlags.ServerSwitch)) // 0x100
            {
                writer.Write(payload.ReadBytes(8));
            }

            if (header.HasFlag(PacketHeaderFlags.RequestRetransmit)) // 0x1000
            {
                uint retransmitCount = payload.ReadUInt32();
                writer.Write(retransmitCount);
                for (uint i = 0u; i < retransmitCount; i++)
                {
                    uint sequence = payload.ReadUInt32();
                    writer.Write(sequence);
                    RetransmitData.Add(sequence);
                }
            }

            if (header.HasFlag(PacketHeaderFlags.RejectRetransmit)) // 0x2000
            {
                uint count = payload.ReadUInt32();
                writer.Write(count);
                for (int i = 0; i < count; i++)
                {
                    writer.Write(payload.ReadBytes(4));
                }
            }

            if (header.HasFlag(PacketHeaderFlags.AckSequence)) // 0x4000
            {
                Sequence = payload.ReadUInt32();
                writer.Write(Sequence);
            }

            if (header.HasFlag(PacketHeaderFlags.LoginRequest)) // 0x10000
            {
                var    position   = payload.BaseStream.Position;
                var    length     = payload.BaseStream.Length - position;
                byte[] loginBytes = new byte[length];
                payload.BaseStream.Read(loginBytes, (int)position, (int)length);
                writer.Write(loginBytes);
                payload.BaseStream.Position = position;
            }

            if (header.HasFlag(PacketHeaderFlags.WorldLoginRequest)) // 0x20000
            {
                var position = payload.BaseStream.Position;
                writer.Write(payload.ReadBytes(8));
                payload.BaseStream.Position = position;
            }

            if (header.HasFlag(PacketHeaderFlags.ConnectResponse)) // 0x80000
            {
                var position = payload.BaseStream.Position;
                writer.Write(payload.ReadBytes(8));
                payload.BaseStream.Position = position;
            }

            if (header.HasFlag(PacketHeaderFlags.CICMDCommand)) // 0x400000
            {
                writer.Write(payload.ReadBytes(8));
            }

            if (header.HasFlag(PacketHeaderFlags.TimeSynch)) // 0x1000000
            {
                TimeSynch = payload.ReadDouble();
                writer.Write(TimeSynch);
            }

            if (header.HasFlag(PacketHeaderFlags.EchoRequest)) // 0x2000000
            {
                EchoRequestClientTime = payload.ReadSingle();
                writer.Write(EchoRequestClientTime);
            }

            if (header.HasFlag(PacketHeaderFlags.Flow)) // 0x8000000
            {
                writer.Write(payload.ReadBytes(6));
            }

            Size = (uint)payload.BaseStream.Position - Size;
        }