//ProcessAck in packet public void ProcessAck(NetPacket packet) { ushort ackWindowStart = packet.Sequence; //check relevance if (NetUtils.RelativeSequenceNumber(ackWindowStart, _localWindowStart) <= -_windowSize) { _peer.DebugWrite("[PA]Old acks"); return; } byte[] acksData = packet.RawData; _peer.DebugWrite("[PA]AcksStart: {0}", ackWindowStart); int startByte = NetConstants.SequencedHeaderSize; _pendingPacketsAccess.WaitOne(); for (int i = 0; i < _windowSize; i++) { int ackSequence = (ackWindowStart + i) % NetConstants.MaxSequence; if (NetUtils.RelativeSequenceNumber(ackSequence, _localWindowStart) < 0) { continue; } int currentByte = startByte + i / BitsInByte; int currentBit = i % BitsInByte; if ((acksData[currentByte] & (1 << currentBit)) == 0) { continue; } if (ackSequence == _localWindowStart) { _localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence; } int storeIdx = ackSequence % _windowSize; if (_pendingPackets[storeIdx].NotEmpty) { NetPacket removed = _pendingPackets[storeIdx].GetAndClear(); _peer.Recycle(removed); _peer.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", ackSequence); } else { _peer.DebugWrite("[PA]Removing reliableInOrder ack: {0} - false", ackSequence); } } _pendingPacketsAccess.Set(); }
public bool Clear(NetPeer peer) { if (_packet != null) { peer.Recycle(_packet); _packet = null; return(true); } return(false); }
public void Abort() { stopwatch.Stop(); for (int i = 0; i < packets.Length; ++i) { if (packets[i] != null) { peer.Recycle(packets[i]); } } }
public void SendNextPackets() { lock (_outgoingPackets) { while (_outgoingPackets.Count > 0) { NetPacket packet = _outgoingPackets.Dequeue(); _localSequence = (_localSequence + 1) % NetConstants.MaxSequence; packet.Sequence = (ushort)_localSequence; _peer.SendRawData(packet); _peer.Recycle(packet); } } }
internal bool SendNextPacket() { NetPacket packet; lock (_outgoingPackets) { if (_outgoingPackets.Count == 0) { return(false); } packet = _outgoingPackets.Dequeue(); } _peer.SendRawData(packet); _peer.Recycle(packet); return(true); }
public bool SendNextPackets() { NetPacket packet; lock (_outgoingPackets) { while (_outgoingPackets.Count > 0) { packet = _outgoingPackets.Dequeue(); _peer.SendRawData(packet); _peer.Recycle(packet); } } return(true); }
public bool SendNextPacket() { NetPacket packet; lock (_outgoingPackets) { if (_outgoingPackets.Count == 0) { return(false); } packet = _outgoingPackets.Dequeue(); } _localSequence = (_localSequence + 1) % NetConstants.MaxSequence; packet.Sequence = (ushort)_localSequence; _peer.SendRawData(packet); _peer.Recycle(packet); return(true); }
public bool SendNextPacket() { if (_outgoingPackets.Count == 0) { return(false); } _localSequence++; NetPacket packet; lock (_outgoingPackets) { packet = _outgoingPackets.Dequeue(); } packet.Sequence = _localSequence; _peer.SendRawData(packet.RawData); _peer.Recycle(packet); return(true); }
//ProcessAck in packet public void ProcessAck(NetPacket packet) { if (packet.Size != _outgoingAcks.Size) { NetUtils.DebugWrite("[PA]Invalid acks packet size"); return; } ushort ackWindowStart = packet.Sequence; if (ackWindowStart > NetConstants.MaxSequence) { NetUtils.DebugWrite("[PA]Bad window start"); return; } //check relevance if (NetUtils.RelativeSequenceNumber(ackWindowStart, _localWindowStart) <= -_windowSize) { NetUtils.DebugWrite("[PA]Old acks"); return; } byte[] acksData = packet.RawData; Monitor.Enter(_pendingPackets); PendingPacket pendingPacket = _headPendingPacket; PendingPacket prevPacket = null; while (pendingPacket != null) { int seq = pendingPacket.Packet.Sequence; int rel = NetUtils.RelativeSequenceNumber(seq, ackWindowStart); if (rel < 0 || rel >= _windowSize) { prevPacket = pendingPacket; pendingPacket = pendingPacket.Next; continue; } int idx = seq % _windowSize; int currentByte = NetConstants.SequencedHeaderSize + idx / BitsInByte; int currentBit = idx % BitsInByte; if ((acksData[currentByte] & (1 << currentBit)) == 0) { #if STATS_ENABLED || DEBUG _peer.Statistics.PacketLoss++; #endif //Skip false ack prevPacket = pendingPacket; pendingPacket = pendingPacket.Next; continue; } if (seq == _localWindowStart) { //Move window _localWindowStart = (_localWindowStart + _ackedPackets) % NetConstants.MaxSequence; _ackedPackets = 1; } else { _ackedPackets++; } if (_headPendingPacket == pendingPacket) { _headPendingPacket = _headPendingPacket.Next; } var packetToClear = pendingPacket; //move forward pendingPacket = pendingPacket.Next; if (prevPacket != null) { prevPacket.Next = pendingPacket; } //clear acked packet _peer.Recycle(packetToClear.Packet); packetToClear.Clear(); NetUtils.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", seq); } Monitor.Exit(_pendingPackets); }
protected override void ReceiveFromSocket(byte[] reusableBuffer, int count, NetEndPoint remoteEndPoint) { //Parse packet //Peer null when P2P connection packets NetPacket packet = _peer == null ? new NetPacket() : _peer.GetPacketFromPool(init: false); if (!packet.FromBytes(reusableBuffer, count)) { if (_peer != null) { _peer.Recycle(packet); } return; } //Check P2P mode if (PeerToPeerMode && packet.Property == PacketProperty.ConnectRequest) { NetUtils.DebugWrite(ConsoleColor.Cyan, "[NC] Received peer connect request"); string peerKey = Encoding.UTF8.GetString(packet.RawData, 9, packet.RawData.Length - 9); if (peerKey != _connectKey) { NetUtils.DebugWrite(ConsoleColor.Cyan, "[NC] Peer connect reject. Invalid key: " + peerKey); return; } NetUtils.DebugWrite(ConsoleColor.Cyan, "[NC] Peer connect accepting"); //Make initial packet and put id from received packet var connectPacket = NetPacket.CreateRawPacket(PacketProperty.ConnectAccept, 8); Buffer.BlockCopy(packet.RawData, 1, connectPacket, 1, 8); //Check our peer and create if (_peer == null) { //Create connect id for proper connection Connect(remoteEndPoint); } //Send raw _peer.SendRawData(connectPacket); //clean incoming packet _peer.Recycle(packet); //We connected ProcessConnectAccept(); return; } //Check peer if (_peer == null) { return; } //Check endpoint if (!_peer.EndPoint.Equals(remoteEndPoint)) { NetUtils.DebugWriteForce(ConsoleColor.DarkCyan, "[NC] Bad EndPoint " + remoteEndPoint); return; } if (packet.Property == PacketProperty.Disconnect) { NetUtils.DebugWrite(ConsoleColor.Cyan, "[NC] Received disconnection"); CloseConnection(true); var disconnectEvent = CreateEvent(NetEventType.Disconnect); disconnectEvent.AdditionalInfo = "Received disconnection from server"; EnqueueEvent(disconnectEvent); return; } if (packet.Property == PacketProperty.ConnectAccept) { if (_connected) { return; } //check connection id if (BitConverter.ToUInt64(packet.RawData, 1) != _connectId) { return; } //connection things ProcessConnectAccept(); return; } //Process income packet _peer.ProcessPacket(packet); }
//ProcessAck in packet public void ProcessAck(NetPacket packet) { int validPacketSize = (_windowSize - 1) / BitsInByte + 1 + NetConstants.SequencedHeaderSize; if (packet.Size != validPacketSize) { NetUtils.DebugWrite("[PA]Invalid acks packet size"); return; } ushort ackWindowStart = packet.Sequence; if (ackWindowStart > NetConstants.MaxSequence) { NetUtils.DebugWrite("[PA]Bad window start"); return; } //check relevance if (NetUtils.RelativeSequenceNumber(ackWindowStart, _localWindowStart) <= -_windowSize) { NetUtils.DebugWrite("[PA]Old acks"); return; } byte[] acksData = packet.RawData; NetUtils.DebugWrite("[PA]AcksStart: {0}", ackWindowStart); int startByte = NetConstants.SequencedHeaderSize; Monitor.Enter(_pendingPackets); for (int i = 0; i < _windowSize; i++) { int ackSequence = (ackWindowStart + i) % NetConstants.MaxSequence; if (NetUtils.RelativeSequenceNumber(ackSequence, _localWindowStart) < 0) { //NetUtils.DebugWrite(ConsoleColor.Cyan, "[PA] SKIP OLD: " + ackSequence); //Skip old ack continue; } int currentByte = startByte + i / BitsInByte; int currentBit = i % BitsInByte; if ((acksData[currentByte] & (1 << currentBit)) == 0) { #if STATS_ENABLED || DEBUG if (_pendingPackets[ackSequence % _windowSize].TimeStamp.HasValue) { _peer.Statistics.PacketLoss++; } #endif //NetUtils.DebugWrite(ConsoleColor.Cyan, "[PA] SKIP FALSE: " + ackSequence); //Skip false ack continue; } if (ackSequence == _localWindowStart) { //Move window _localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence; } PendingPacket pendingPacket = _pendingPackets[ackSequence % _windowSize]; if (pendingPacket.Packet != null) { if (pendingPacket == _headPendingPacket) { _headPendingPacket = _headPendingPacket.Prev; } _peer.Recycle(pendingPacket.Packet); pendingPacket.Clear(); NetUtils.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", ackSequence); } else { NetUtils.DebugWrite("[PA]Removing reliableInOrder ack: {0} - false", ackSequence); } } Monitor.Exit(_pendingPackets); }
private void DataReceived(byte[] reusableBuffer, int count, NetEndPoint remoteEndPoint) { #if STATS_ENABLED PacketsReceived++; BytesReceived += (uint)count; #endif //Try get packet property PacketProperty property; if (!NetPacket.GetPacketProperty(reusableBuffer, out property)) { return; } //Check unconnected switch (property) { case PacketProperty.DiscoveryRequest: if (DiscoveryEnabled) { var netEvent = CreateEvent(NetEventType.DiscoveryRequest); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(NetPacket.GetUnconnectedData(reusableBuffer, count)); EnqueueEvent(netEvent); } return; case PacketProperty.DiscoveryResponse: { var netEvent = CreateEvent(NetEventType.DiscoveryResponse); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(NetPacket.GetUnconnectedData(reusableBuffer, count)); EnqueueEvent(netEvent); } return; case PacketProperty.UnconnectedMessage: if (UnconnectedMessagesEnabled) { var netEvent = CreateEvent(NetEventType.ReceiveUnconnected); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(NetPacket.GetUnconnectedData(reusableBuffer, count)); EnqueueEvent(netEvent); } return; case PacketProperty.NatIntroduction: case PacketProperty.NatIntroductionRequest: case PacketProperty.NatPunchMessage: { if (NatPunchEnabled) { NatPunchModule.ProcessMessage(remoteEndPoint, property, NetPacket.GetUnconnectedData(reusableBuffer, count)); } return; } } //Check normal packets NetPacket packet; NetPeer netPeer; //Check peers Monitor.Enter(_peers); int peersCount = _peers.Count; if (_peers.TryGetValue(remoteEndPoint, out netPeer)) { Monitor.Exit(_peers); packet = netPeer.GetPacketFromPool(init: false); //Bad packet check if (!packet.FromBytes(reusableBuffer, 0, count)) { netPeer.Recycle(packet); return; } //Send if (packet.Property == PacketProperty.Disconnect) { if (BitConverter.ToInt64(packet.RawData, 1) != netPeer.ConnectId) { //Old or incorrect disconnect netPeer.Recycle(packet); return; } var netEvent = CreateEvent(NetEventType.Disconnect); netEvent.Peer = netPeer; netEvent.DataReader.SetSource(packet.RawData, 5, packet.RawData.Length - 5); netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose; EnqueueEvent(netEvent); lock (_peersToRemove) { _peersToRemove.Enqueue(netPeer.EndPoint); } //do not recycle because no sense) } else if (packet.Property == PacketProperty.ConnectAccept) { if (netPeer.ProcessConnectAccept(packet)) { var connectEvent = CreateEvent(NetEventType.Connect); connectEvent.Peer = netPeer; EnqueueEvent(connectEvent); } netPeer.Recycle(packet); } else { netPeer.ProcessPacket(packet); } return; } try { //Else add new peer packet = new NetPacket(); if (!packet.FromBytes(reusableBuffer, 0, count)) { //Bad packet return; } if (peersCount < _maxConnections && packet.Property == PacketProperty.ConnectRequest) { int protoId = BitConverter.ToInt32(packet.RawData, 1); if (protoId != NetConstants.ProtocolId) { NetUtils.DebugWrite(ConsoleColor.Cyan, "[NS] Peer connect reject. Invalid protocol ID: " + protoId); return; } string peerKey = Encoding.UTF8.GetString(packet.RawData, 13, packet.RawData.Length - 13); if (peerKey != _connectKey) { NetUtils.DebugWrite(ConsoleColor.Cyan, "[NS] Peer connect reject. Invalid key: " + peerKey); return; } //Getting new id for peer long connectionId = BitConverter.ToInt64(packet.RawData, 5); //response with id NetUtils.DebugWrite(ConsoleColor.Cyan, "[NS] Received peer connect request Id: {0}, EP: {1}", netPeer.ConnectId, remoteEndPoint); netPeer = new NetPeer(this, remoteEndPoint, connectionId); //clean incoming packet netPeer.Recycle(packet); _peers.Add(remoteEndPoint, netPeer); var netEvent = CreateEvent(NetEventType.Connect); netEvent.Peer = netPeer; EnqueueEvent(netEvent); } } finally { Monitor.Exit(_peers); } }
//ProcessAck in packet public void ProcessAck(NetPacket packet) { int validPacketSize = (_windowSize - 1) / BitsInByte + 1 + NetConstants.SequencedHeaderSize; if (packet.RawData.Length != validPacketSize) { _peer.DebugWriteForce("[PA]Invalid acks packet size"); return; } ushort ackWindowStart = packet.Sequence; if (ackWindowStart > NetConstants.MaxSequence) { _peer.DebugWrite("[PA]Bad window start"); return; } //check relevance if (NetUtils.RelativeSequenceNumber(ackWindowStart, _localWindowStart) <= -_windowSize) { _peer.DebugWrite("[PA]Old acks"); return; } byte[] acksData = packet.RawData; _peer.DebugWrite("[PA]AcksStart: {0}", ackWindowStart); int startByte = NetConstants.SequencedHeaderSize; Monitor.Enter(_pendingPacketsAccess); for (int i = 0; i < _windowSize; i++) { int ackSequence = (ackWindowStart + i) % NetConstants.MaxSequence; if (NetUtils.RelativeSequenceNumber(ackSequence, _localWindowStart) < 0) { //Skip old ack continue; } int currentByte = startByte + i / BitsInByte; int currentBit = i % BitsInByte; if ((acksData[currentByte] & (1 << currentBit)) == 0) { //Skip false ack continue; } if (ackSequence == _localWindowStart) { //Move window _localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence; } int storeIdx = ackSequence % _windowSize; if (_pendingPackets[storeIdx].NotEmpty) { NetPacket removed = _pendingPackets[storeIdx].GetAndClear(); _peer.Recycle(removed); _peer.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", ackSequence); } else { _peer.DebugWrite("[PA]Removing reliableInOrder ack: {0} - false", ackSequence); } } Monitor.Exit(_pendingPacketsAccess); }