internal void AddPacket(RUDPIngoingPacket packet) { lock (_lock) { if (packet.PacketId < 0) { _list.AddLast(packet); return; } LinkedListNode<RUDPIngoingPacket> node = _list.Last; while (node != null && (node.Value.PacketId < 0 || packet.PacketId < node.Value.PacketId)) node = node.Previous; if (node == null) { _list.AddFirst(packet); return; } // If duplicated packet -> drop if (packet.PacketId == node.Value.PacketId) return; // Add _list.AddAfter(node, packet); } }
internal void OnReceive(RUDPIngoingPacket packet) { if (packet != null) { Interlocked.Exchange(ref _rwnd, _rwnd + packet.Payload.Length); } }
internal void AddPacket(RUDPIngoingPacket packet) { lock (_lock) { if (packet.PacketId < 0) { _list.AddLast(packet); return; } LinkedListNode <RUDPIngoingPacket> node = _list.Last; while (node != null && (node.Value.PacketId < 0 || packet.PacketId < node.Value.PacketId)) { node = node.Previous; } if (node == null) { _list.AddFirst(packet); return; } // If duplicated packet -> drop if (packet.PacketId == node.Value.PacketId) { return; } // Add _list.AddAfter(node, packet); } }
internal void AddPacket(RUDPIngoingPacket packet) { if (packet.PacketId < 0) { _lock.EnterWriteLock(); _list.AddLast(packet); _lock.ExitWriteLock(); return; } _lock.EnterUpgradeableReadLock(); try { LinkedListNode <RUDPIngoingPacket> node = _list.Last; while (node != null && (node.Value.PacketId < 0 || packet.PacketId < node.Value.PacketId)) { node = node.Previous; } if (node == null) { _lock.EnterWriteLock(); _list.AddFirst(packet); _lock.ExitWriteLock(); // Needed ? return; } // If duplicated packet -> drop if (packet.PacketId == node.Value.PacketId) { return; } // Add _lock.EnterWriteLock(); _list.AddAfter(node, packet); _lock.ExitWriteLock(); // Needed ? } finally { _lock.ExitUpgradeableReadLock(); } }
internal void AddPacket(RUDPIngoingPacket packet) { if (packet.PacketId < 0) { _lock.EnterWriteLock(); _list.AddLast(packet); _lock.ExitWriteLock(); return; } _lock.EnterUpgradeableReadLock(); try { LinkedListNode<RUDPIngoingPacket> node = _list.Last; while (node != null && (node.Value.PacketId < 0 || packet.PacketId < node.Value.PacketId)) node = node.Previous; if (node == null) { _lock.EnterWriteLock(); _list.AddFirst(packet); _lock.ExitWriteLock(); // Needed ? return; } // If duplicated packet -> drop if (packet.PacketId == node.Value.PacketId) return; // Add _lock.EnterWriteLock(); _list.AddAfter(node, packet); _lock.ExitWriteLock(); // Needed ? } finally { _lock.ExitUpgradeableReadLock(); } }
internal void OnReceiveProcessed(RUDPIngoingPacket packet) { Interlocked.Exchange(ref _rwnd, _rwnd - packet.Payload.Length); }
internal void OnReceive(RUDPIngoingPacket packet) { if (packet != null) Interlocked.Exchange(ref _rwnd, _rwnd + packet.Payload.Length); }
private static void HandlePacket(PhysicalSocket physical, IPEndPoint sender, RUDPPacketChannel channel, int packetId, int advertisedWindowSize, SACKSlot slot1, SACKSlot slot2, SACKSlot slot3, SACKSlot slot4, byte[] payload) { RUDPSocket rudp = null; //---- PING if (channel == RUDPPacketChannel.Ping || channel == RUDPPacketChannel.PingRendezVous) { rudp = HandlePing(physical, sender, packetId, channel); // Do not handle this message if (rudp == null) return; } //---- Search the socket if (rudp == null) { physical._connectedRDUPsLock.EnterReadLock(); physical._connectedRDUPs.TryGetValue(sender, out rudp); physical._connectedRDUPsLock.ExitReadLock(); } //---- Direct send of ACK, because socket can be shutdowned and removed if (channel == RUDPPacketChannel.TearDown) { byte[] packetPayload = MakePacketPayload(rudp, -1, RUDPPacketChannel.ACK, new SACKSlot(packetId, packetId), null, null, null, null, 0, 0); SocketSendACK(rudp, physical, sender, packetPayload); PayloadManager.Deallocate(RUDPPacketChannel.ACK, packetPayload); } //---- Released socket if (rudp == null) return; #if CONSOLE_TRACE if (packetId > -1) Trace("Handle packet (" + rudp.Handle + ")(" + channel + "):" + packetId); #endif //---- Advertised window rudp._controlWindow.OnReceiveAdvertisedWindow(advertisedWindowSize); //---- Handle ACKs HandleACKs(rudp, slot1, slot2, slot3, slot4); if (channel == RUDPPacketChannel.ACK) return; //---- Non reliable messages if (packetId < 0) { //-- Bandwidth if (channel == RUDPPacketChannel.Bandwidth01) { PushPacketToSend(rudp, false, RUDPPacketChannel.BandwidthResponse01, null, 0, 0); return; } else if (channel == RUDPPacketChannel.Bandwidth02) { PushPacketToSend(rudp, false, RUDPPacketChannel.BandwidthResponse02, payload, 0, 8); return; } else if (channel == RUDPPacketChannel.BandwidthResponse01) { rudp._bandwidthResponse01TS = HiResTimer.MicroSeconds; } else if (channel == RUDPPacketChannel.BandwidthResponse02) { //---- Calculate bandwidth // Bdw (Bytes / milli-sec) long now = HiResTimer.MicroSeconds; double delay = (now - rudp._bandwidthResponse01TS) / 1000; if (delay < 0.001) delay = 0.001; // Arrival Speed double arrivalSpeed = (RUDPHeaderLength + UDPHeaderLength) / delay; // RTT double currentRtt = (now - BinaryHelper.ReadInt(payload, 0)) / 1000; if (currentRtt < 0.001) currentRtt = 0.001; // BDP = Bandwidth(Byte / Ms) * RTT; double bandwidth = (long)(arrivalSpeed * currentRtt); rudp._bandwidth = (long)(rudp._bandwidth * 0.875f + bandwidth * 0.125f); } //-- MTU Tuning else if (channel == RUDPPacketChannel.MTUTuning) { rudp._pmtuDiscovery.OnReceiveProbe(payload.Length); return; } else if (channel == RUDPPacketChannel.MTUTuningACK) { rudp._pmtuDiscovery.OnReceiveProbeACK(payload); return; } //if ((rudp._incomingNonReliablePackets.Count * rudp._mtu) >= rudp._receiveSize) //return; RUDPIngoingPacket nonReliablePacket = new RUDPIngoingPacket(rudp, packetId, payload, channel, HiResTimer.MicroSeconds); rudp._incomingPackets.AddPacket(nonReliablePacket); rudp.HandleNextUserPacket(false); return; } //---- Do not process a duplicated packets bool isDuplicatedPacket; isDuplicatedPacket = (packetId <= rudp._incomingPackets.CurrentPacketId); if (!isDuplicatedPacket) isDuplicatedPacket = rudp._incomingPackets.ContainsPacket(packetId); //---- Can I receive the packet now ? bool canReceive = rudp._controlWindow.CanReceive(packetId, payload.Length); //---- Send the ACK if (channel != RUDPPacketChannel.Ping && channel != RUDPPacketChannel.PingRendezVous) if (canReceive || // Can receive, then we send ACK (!canReceive && isDuplicatedPacket)) // Is duplicated, then already in the list -> send another ACK rudp._sackWindow.OnReceivePacket(packetId); //---- Check if we can handle this message if (!canReceive || isDuplicatedPacket) return; //---- If we are not connected, we cannot hanlde messages ! We need a connection before. if (rudp._status != RUDPSocketStatus.Connected && channel == RUDPPacketChannel.UserPacket) return; //---- Check for Out of order packets if (rudp._incomingPackets.Count > 0) { int greaterPacketId = rudp._incomingPackets.LastPacketId; if (packetId != greaterPacketId + 1) { byte[] oooPayload = new byte[8]; // start packet BinaryHelper.WriteInt(greaterPacketId + 1, oooPayload, 0); // end packet BinaryHelper.WriteInt(packetId - 1, oooPayload, 4); PushPacketToSend(rudp, false, RUDPPacketChannel.OutOfOrder, oooPayload, 0, 8); } } //---- Receive Out of order notification if (channel == RUDPPacketChannel.OutOfOrder) { rudp._controlWindow.OnOutOfOrder(BinaryHelper.ReadInt(payload, 0), BinaryHelper.ReadInt(payload, 4)); } //---- TEAR DOWN if (channel == RUDPPacketChannel.TearDown) { // Initiate the close process if (rudp._status == RUDPSocketStatus.Connected) { // Notify control window rudp._controlWindow.OnReceive(null); // Start shutdown AsyncShutdown(rudp); } return; } //---- Add the packet to incoming list RUDPIngoingPacket packet = new RUDPIngoingPacket(rudp, packetId, payload, channel, HiResTimer.MicroSeconds); // Notify control window rudp._controlWindow.OnReceive(packet); rudp._incomingPackets.AddPacket(packet); //------ Handle the ordered ingoing packets rudp.HandleNextUserPacket(false); }
internal void HandleNextUserPacket(bool forceAsyncCall) { if (_asyncResultReceive == null) { return; } RUDPReceiveIAsyncResult asyncResult; RUDPIngoingPacket packet = null; lock (_handleNextUserPacketLock) { if (_incomingPackets.Count < 1) { return; } asyncResult = _asyncResultReceive; if (_asyncResultReceive == null) { return; } //-- Clean the list while (_incomingPackets.Count > 0) { // Get the current packet packet = _incomingPackets.RemoveNextPacket(); // No more packet if (packet == null) { return; } // Ordered packet if (packet.Channel != RUDPPacketChannel.UserPacket) { _controlWindow.OnReceiveProcessed(packet); } else { break; // It is the next message to process. } } //---- Check it is not null if (packet == null) { return; } _asyncResultReceive = null; } //---- Receive if (asyncResult != null) { _controlWindow.OnReceiveProcessed(packet); OnEndReceive(RUDPSocketError.Success, packet, forceAsyncCall, asyncResult); } }
internal void OnEndReceive(RUDPSocketError error, RUDPIngoingPacket packet, bool forceAsyncCall, RUDPReceiveIAsyncResult asyncResult) { asyncResult.Packet = packet; asyncResult.ForceAsyncCall = forceAsyncCall; asyncResult.SetAsCompleted(error, false); }