/// <summary> /// Add a reliable wrapper to a packet /// </summary> /// <param name="packet">Message Packet</param> /// <returns>New message packet</returns> public Byte[] GetReliablePacket(Byte[] packet) { // Create a new reliable packet ReliablePacket reliablePacket = new ReliablePacket(); // Set the packet data reliablePacket.TransactionId = m_nTransactionId; reliablePacket.Message = packet; reliablePacket.TimeStamp = TimeSpan.FromMilliseconds(Environment.TickCount); // Increment the transaction identifier m_nTransactionId++; // Lock the mutex if (m_mutex.WaitOne(500, false)) { // Add the reliable packet to the list to be acknowleged m_reliableList.Add(reliablePacket.TransactionId, reliablePacket); // release the mutex m_mutex.ReleaseMutex(); } // return the packet data return(reliablePacket.Packet); }
public override ChanneledPacket CreateOutgoingMessage(byte[] payload, int offset, int length) { ReliablePacket message = new ReliablePacket(++_lastOutboundSequenceNumber, payload, offset, length); _outgoingPendingMessages.Add(message.Sequence, message); return(message); }
/// <summary> /// Sends a packet to the connection. /// </summary> /// <param name="packet">The packet to send.</param> public void SendPacket(NetOutboundPacket packet) { if (packet.HasId) { throw new NetException( "Cannot send packet twice, please create a new packet or clone this one before sending another time."); } // Remove the packets padding packet.RemovePadding(); // Setup the packet and make it ready for sending SetupOutboundPacket(packet); // Write the packet's header and set it's Id WriteOutboundPacketHeader(packet); // Check if this packet needs to be split into a partial if (MTU > 0 && packet.Length > MTU && !packet.isPartial) { // Split the packet into partials NetOutboundPacket[] partials = SplitPacketIntoPartials(packet); for (int i = 0; i < partials.Length; i++) { // Send the partials as seperate packets SendPacket(partials[i]); } // Stop handling the too large packet return; } // Handle the sending based on delivery method if (packet.DeliveryMethod == NetDeliveryMethod.Unreliable) { // No extra work needed, just place in outbound queue AddPacketToChunkQueue(packet); } else if (packet.DeliveryMethod == NetDeliveryMethod.Reliable) { // Create the reliable packet handler and add it to the reliable queue ReliablePacket reliablePacket = new ReliablePacket(packet); if (!reliableOutboundPacketQueue.TryAdd(packet.Id, reliablePacket)) { NetLogger.LogError("Failed to add packet to the reliable outbound queue. Id: {0}, Type: {1}, DeliveryMethod: {2}", packet.Id, packet.Type, packet.DeliveryMethod); } // Attempt first send AddPacketToChunkQueue(packet); } else if (packet.DeliveryMethod == NetDeliveryMethod.ReliableOrdered) { // Create the reliable packet handler and add it to the ordered reliable queue ReliablePacket reliablePacket = new ReliablePacket(packet); reliableOrderedOutboundPacketQueue.Enqueue(reliablePacket); } }
public void ServerRoomManageAnswer() { MvsAServer t = new MvsAServer(socket, end, dataLenght, 4, 3); t.CreateRoom(); ReliablePacket p = new ReliablePacket(5); p.command = (int)Command.DEATH; p.end = t.CurrentEndPoint; t.rooms[0].reliablePackets.Add(p); t.rooms[0].ManageAnswer((int)Command.DEATH); Assert.That(t.rooms[0].reliablePackets.Count, Is.EqualTo(0)); }
public override ChanneledPacket HandleIncomingMessagePoll(byte[] buffer, int size, out bool hasMore) { // Reliable has one message in equal no more than one out. hasMore = false; ReliablePacket packet = new ReliablePacket(); packet.Read(buffer, size); if (packet.Sequence <= _incomingLowestAckedSequence || _incomingAckedPackets.ContainsKey(packet.Sequence)) { // They didnt get our ack. // TODO: Send ack return(null); } else if (packet.Sequence == _incomingLowestAckedSequence + 1) { // This is the "next" packet do { // Remove previous _incomingAckedPackets.Remove(_incomingLowestAckedSequence); _incomingLowestAckedSequence++; }while (packet.Sequence == _incomingLowestAckedSequence + 1); // TODO: Send ack return(packet); } else if (SequencingUtils.Distance(packet.Sequence, _incomingLowestAckedSequence, sizeof(ushort)) > 0 && !_incomingAckedPackets.ContainsKey(packet.Sequence)) { // This is a future packet _incomingAckedPackets.Add(packet.Sequence, packet); // TODO: Send ack return(packet); } return(null); }
/// <summary> /// Receive a packet from the server /// </summary> /// <returns>Received packet data</returns> public Byte[] ReceivePacket() { ReliablePacket pReliablePacket = new ReliablePacket(); AcknowlegePacket pAckPacket = new AcknowlegePacket(); Byte[] pData = new Byte[0]; ClusteredPacket pClusteredPacket = new ClusteredPacket(); ChunkBodyPacket pChunkBodyPacket = new ChunkBodyPacket(); ChunkTailPacket pChunkTailPacket = new ChunkTailPacket(); LargeChunkPacket pLargeChunkPacket = new LargeChunkPacket(); // Check if there are any elements on the queue if (m_pReceiveQueue.Count > 0) { // Get the next element from the receive queue pData = (Byte[])(m_pReceiveQueue.Dequeue()); if (pData != null) { // Write the data to the packet loggers m_packetLogger(PacketDirection.Receive, pData); // Check if the message is reliable if (pData[0] == 0x00) { switch (pData[1]) { case 0x03: // Set the packet information pReliablePacket.Packet = pData; // Extract the message pData = pReliablePacket.Message; // Increment the reliable receive counter m_nReliablePacketsReceived++; // Set the acknowlege transaction identifier and transmit pAckPacket.TransactionId = pReliablePacket.TransactionId; TransmitPacket(pAckPacket.Packet); break; case 0x04: // Set the acknowlegement packet data pAckPacket.Packet = pData; // Handle the Acknowlege packet m_reliableMessageHandler.HandleAcknowlegement(pAckPacket.TransactionId); break; } // Check if the packet is a chunk body packet if ((pData[0] == 0x00) && (pData[1] == 0x08)) { // Set the chunk data packet pChunkBodyPacket.Packet = pData; // Get the message packet from the buffer pData = pChunkBodyPacket.Message; // Append the data to the buffer m_chunkBuffer.Write(pData, 0, pData.Length); // Clear the returned data pData = new Byte[0]; } // Check if the packet is a chunk tail packet else if ((pData[0] == 0x00) && (pData[1] == 0x09)) { // Set the chunk data packet pChunkTailPacket.Packet = pData; // Get the message packet from the buffer pData = pChunkTailPacket.Message; // Append the data to the chunk buffer m_chunkBuffer.Write(pData, 0, pData.Length); // return the full data packet pData = m_chunkBuffer.ToArray(); // Clear the chunk buffer m_chunkBuffer.Position = 0; } // Check if the packet is a large chunk packet else if ((pData[0] == 0x00) && (pData[1] == 0x0A)) { // Set the large chunk packet pLargeChunkPacket.Packet = pData; // Get the message packet from the buffer pData = pLargeChunkPacket.Message; // Append the message to the large buffer m_largeBuffer.Write(pData, 0, pData.Length); // Check if the packet is complete if (m_largeBuffer.Length == pLargeChunkPacket.TotalLength) { // return the full data packet pData = m_largeBuffer.ToArray(); // Clear the chunk buffer m_largeBuffer.Position = 0; } else { // Clear the returned data pData = new Byte[0]; } } // Check if the packet is a clustered packet else if ((pData[0] == 0x00) && (pData[1] == 0x0E)) { // Set the clustered packet data pClusteredPacket.Packet = pData; // Get the enumerator for the packet list IEnumerator pEnum = pClusteredPacket.Packets.GetEnumerator(); while (pEnum.MoveNext()) { // Add the next element to the receive queue m_pReceiveQueue.Enqueue((Byte[])pEnum.Current); } // Clear the returned data pData = new Byte[0]; } } } } return(pData); }