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()); } }
private void ReceiveFragment(SOEPacket packet) { // Setup a reader SOEReader reader = new SOEReader(packet); reader.ReadUInt16(); // Have we already started a fragmented packet? if (StartedFragmentedPacket) { // One less fragment till we need to acknowledge! FragmentsTillAck--; // Get our sequence number uint previousFragmentSequenceNumber = FragmentSequenceNumber; FragmentSequenceNumber = reader.ReadUInt16(); // Did we get a correct sequence number? if (FragmentSequenceNumber != previousFragmentSequenceNumber + 1) { // Out of order! ReceivedSequenceOutOfOrder(FragmentSequenceNumber); return; } // Append the rest of the packet to the fragmented data for (int i = 4; i < FragmentedData.Length; i++) { FragmentedData[ReceivedFragmentsSize] = reader.ReadByte(); ReceivedFragmentsSize++; } } else { // We're expecting the starting packet FragmentSequenceNumber = reader.ReadUInt16(); uint totalSize = reader.ReadUInt32(); // Is this a valid sequence number? if ((FragmentSequenceNumber != LastReceivedSequenceNumber + 1) && (FragmentSequenceNumber != 0)) { // Out of order! ReceivedSequenceOutOfOrder(FragmentSequenceNumber); return; } // Get the total size FragmentedData = new byte[totalSize]; // How many fragments till we need to acknowledge FragmentsTillAck = 4; // Append the rest of the packet to the fragmented data for (int i = 8; i < FragmentedData.Length; i++) { FragmentedData[ReceivedFragmentsSize] = reader.ReadByte(); ReceivedFragmentsSize++; } // Started a fragmented packet StartedFragmentedPacket = true; } // Are we finished with the fragmented data? if (ReceivedFragmentsSize >= FragmentedData.Length) { // Finish fragmented packet StartedFragmentedPacket = false; FragmentsTillAck = 0; // Handle the fragmented packet as a RELIABLE_DATA packet SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.RELIABLE_DATA); writer.AddBytes(FragmentedData); SOEPacket wholePacket = writer.GetFinalSOEPacket(Client, false, false); // Receive this packet! Receive(wholePacket); return; } // Do we need to acknowledge? if (FragmentsTillAck == 0) { Acknowledge(FragmentSequenceNumber); FragmentsTillAck = 5; } }