//Process incoming packet internal void ProcessPacket(NetPacket packet) { //not initialized if (_connectionState == ConnectionState.Outgoing) { _packetPool.Recycle(packet); return; } if (packet.ConnectionNumber != _connectNum && packet.Property != PacketProperty.ShutdownOk) //without connectionNum { NetDebug.Write(NetLogLevel.Trace, "[RR]Old packet"); _packetPool.Recycle(packet); return; } _timeSinceLastPacket = 0; NetDebug.Write("[RR]PacketProperty: {0}", packet.Property); switch (packet.Property) { case PacketProperty.Merged: int pos = NetConstants.HeaderSize; while (pos < packet.Size) { ushort size = BitConverter.ToUInt16(packet.RawData, pos); pos += 2; NetPacket mergedPacket = _packetPool.GetPacket(size, false); if (!mergedPacket.FromBytes(packet.RawData, pos, size)) { _packetPool.Recycle(packet); break; } pos += size; ProcessPacket(mergedPacket); } break; //If we get ping, send pong case PacketProperty.Ping: if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pongPacket.Sequence) > 0) { NetDebug.Write("[PP]Ping receive, send pong"); FastBitConverter.GetBytes(_pongPacket.RawData, 3, DateTime.UtcNow.Ticks); _pongPacket.Sequence = packet.Sequence; NetManager.SendRaw(_pongPacket, EndPoint); } _packetPool.Recycle(packet); break; //If we get pong, calculate ping time and rtt case PacketProperty.Pong: if (packet.Sequence == _pingPacket.Sequence) { _pingTimer.Stop(); int elapsedMs = (int)_pingTimer.ElapsedMilliseconds; _remoteDelta = BitConverter.ToInt64(packet.RawData, 3) + (elapsedMs * TimeSpan.TicksPerMillisecond) / 2 - DateTime.UtcNow.Ticks; UpdateRoundTripTime(elapsedMs); NetManager.ConnectionLatencyUpdated(this, elapsedMs / 2); NetDebug.Write("[PP]Ping: {0} - {1} - {2}", packet.Sequence, elapsedMs, _remoteDelta); } _packetPool.Recycle(packet); break; case PacketProperty.Ack: case PacketProperty.Channeled: if (packet.ChannelId > _channels.Length) { _packetPool.Recycle(packet); break; } var channel = _channels[packet.ChannelId] ?? (packet.Property == PacketProperty.Ack ? null : CreateChannel(packet.ChannelId)); if (channel != null) { if (!channel.ProcessPacket(packet)) { _packetPool.Recycle(packet); } } break; //Simple packet without acks case PacketProperty.Unreliable: AddIncomingPacket(packet); return; case PacketProperty.MtuCheck: case PacketProperty.MtuOk: ProcessMtuPacket(packet); break; case PacketProperty.ShutdownOk: if (_connectionState == ConnectionState.ShutdownRequested) { _connectionState = ConnectionState.Disconnected; } _packetPool.Recycle(packet); break; default: NetDebug.WriteError("Error! Unexpected packet type: " + packet.Property); break; } }
internal void Update(int deltaTime) { if (_connectionState == ConnectionState.Disconnected) { return; } _timeSinceLastPacket += deltaTime; if (_connectionState == ConnectionState.InProgress) { _connectTimer += deltaTime; if (_connectTimer > _peerListener.ReconnectDelay) { _connectTimer = 0; _connectAttempts++; if (_connectAttempts > _peerListener.MaxConnectAttempts) { _connectionState = ConnectionState.Disconnected; return; } //else send connect again SendConnectRequest(); } return; } //Get current flow mode int maxSendPacketsCount = _peerListener.GetPacketsPerSecond(_currentFlowMode); int currentMaxSend; if (maxSendPacketsCount > 0) { int availableSendPacketsCount = maxSendPacketsCount - _sendedPacketsCount; currentMaxSend = Math.Min(availableSendPacketsCount, (maxSendPacketsCount * deltaTime) / NetConstants.FlowUpdateTime); } else { currentMaxSend = int.MaxValue; } //DebugWrite("[UPDATE]Delta: {0}ms, MaxSend: {1}", deltaTime, currentMaxSend); //Pending acks _reliableOrderedChannel.SendAcks(); _reliableUnorderedChannel.SendAcks(); //ResetFlowTimer _flowTimer += deltaTime; if (_flowTimer >= NetConstants.FlowUpdateTime) { NetUtils.DebugWrite("[UPDATE]Reset flow timer, _sendedPackets - {0}", _sendedPacketsCount); _sendedPacketsCount = 0; _flowTimer = 0; } //Send ping _pingSendTimer += deltaTime; if (_pingSendTimer >= _peerListener.PingInterval) { NetUtils.DebugWrite("[PP] Send ping..."); //reset timer _pingSendTimer = 0; //send ping CreateAndSend(PacketProperty.Ping, _pingSequence); //reset timer _pingTimeStart = DateTime.UtcNow; } //RTT - round trip time _rttResetTimer += deltaTime; if (_rttResetTimer >= RttResetDelay) { _rttResetTimer = 0; //Rtt update _rtt = _avgRtt; _ping = _avgRtt; _peerListener.ConnectionLatencyUpdated(this, _ping); _rttCount = 1; } //MTU - Maximum transmission unit if (!_finishMtu) { _mtuCheckTimer += deltaTime; if (_mtuCheckTimer >= MtuCheckDelay) { _mtuCheckTimer = 0; _mtuCheckAttempts++; if (_mtuCheckAttempts >= MaxMtuCheckAttempts) { _finishMtu = true; } else { lock (_mtuMutex) { //Send increased packet if (_mtuIdx < NetConstants.PossibleMtu.Length - 1) { int newMtu = NetConstants.PossibleMtu[_mtuIdx + 1] - NetConstants.HeaderSize; var p = _packetPool.Get(PacketProperty.MtuCheck, newMtu); p.RawData[1] = (byte)(_mtuIdx + 1); SendPacket(p); } } } } } //MTU - end //Pending send lock (_flushLock) { SendQueuedPackets(currentMaxSend); } }
internal void Update(int deltaTime) { _timeSinceLastPacket += deltaTime; switch (_connectionState) { case ConnectionState.Connected: if (_timeSinceLastPacket > _netManager.DisconnectTimeout) { NetUtils.DebugWrite( "[UPDATE] Disconnect by timeout: {0} > {1}", _timeSinceLastPacket, _netManager.DisconnectTimeout); _netManager.DisconnectPeerForce(this, DisconnectReason.Timeout, 0, null); return; } break; case ConnectionState.ShutdownRequested: if (_timeSinceLastPacket > _netManager.DisconnectTimeout) { _connectionState = ConnectionState.Disconnected; } else { _shutdownTimer += deltaTime; if (_shutdownTimer >= ShutdownDelay) { _shutdownTimer = 0; _netManager.SendRaw(_shutdownPacket, _remoteEndPoint); } } return; case ConnectionState.Outcoming: _connectTimer += deltaTime; if (_connectTimer > _netManager.ReconnectDelay) { _connectTimer = 0; _connectAttempts++; if (_connectAttempts > _netManager.MaxConnectAttempts) { _netManager.DisconnectPeerForce(this, DisconnectReason.ConnectionFailed, 0, null); return; } //else send connect again _netManager.SendRaw(_connectRequestPacket, _remoteEndPoint); } return; case ConnectionState.Disconnected: case ConnectionState.Incoming: return; } //Send ping _pingSendTimer += deltaTime; if (_pingSendTimer >= _netManager.PingInterval) { NetUtils.DebugWrite("[PP] Send ping..."); //reset timer _pingSendTimer = 0; //send ping _pingPacket.Sequence = _pingSequence; _netManager.SendRaw(_pingPacket, _remoteEndPoint); //reset timer _pingTimeStart = DateTime.UtcNow; } //RTT - round trip time _rttResetTimer += deltaTime; if (_rttResetTimer >= RttResetDelay) { _rttResetTimer = 0; //Rtt update _rtt = _avgRtt; _ping = _avgRtt; _netManager.ConnectionLatencyUpdated(this, _ping); _rttCount = 1; } UpdateMtuLogic(deltaTime); //Pending send Flush(); }
internal void Update(int deltaTime) { if (_connectionState == ConnectionState.Connected && _timeSinceLastPacket > _netManager.DisconnectTimeout) { NetUtils.DebugWrite( "[UPDATE] Disconnect by timeout: {0} > {1}", _timeSinceLastPacket, _netManager.DisconnectTimeout); _netManager.DisconnectPeer(this, DisconnectReason.Timeout, 0, true, null, 0, 0); return; } if (_connectionState == ConnectionState.ShutdownRequested) { if (_timeSinceLastPacket > _netManager.DisconnectTimeout) { _connectionState = ConnectionState.Disconnected; } else { _netManager.SendRaw(_shutdownPacket.RawData, 0, _shutdownPacket.Size, _remoteEndPoint); } return; } if (_connectionState == ConnectionState.Disconnected) { return; } _timeSinceLastPacket += deltaTime; if (_connectionState == ConnectionState.InProgress) { _connectTimer += deltaTime; if (_connectTimer > _netManager.ReconnectDelay) { _connectTimer = 0; _connectAttempts++; if (_connectAttempts > _netManager.MaxConnectAttempts) { _netManager.DisconnectPeer(this, DisconnectReason.ConnectionFailed, 0, true, null, 0, 0); return; } //else send connect again SendConnectRequest(); } return; } //Send ping _pingSendTimer += deltaTime; if (_pingSendTimer >= _netManager.PingInterval) { NetUtils.DebugWrite("[PP] Send ping..."); //reset timer _pingSendTimer = 0; //send ping CreateAndSend(PacketProperty.Ping, _pingSequence); //reset timer _pingTimeStart = DateTime.UtcNow; } //RTT - round trip time _rttResetTimer += deltaTime; if (_rttResetTimer >= RttResetDelay) { _rttResetTimer = 0; //Rtt update _rtt = _avgRtt; _ping = _avgRtt; _netManager.ConnectionLatencyUpdated(this, _ping); _rttCount = 1; } //MTU - Maximum transmission unit if (!_finishMtu) { _mtuCheckTimer += deltaTime; if (_mtuCheckTimer >= MtuCheckDelay) { _mtuCheckTimer = 0; _mtuCheckAttempts++; if (_mtuCheckAttempts >= MaxMtuCheckAttempts) { _finishMtu = true; } else { lock (_mtuMutex) { //Send increased packet if (_mtuIdx < NetConstants.PossibleMtu.Length - 1) { int newMtu = NetConstants.PossibleMtu[_mtuIdx + 1] - NetConstants.HeaderSize; var p = _packetPool.Get(PacketProperty.MtuCheck, newMtu); p.RawData[1] = (byte)(_mtuIdx + 1); SendPacket(p); } } } } } //MTU - end //Pending send Flush(); }
internal void Update(int deltaTime) { if (_connectionState == ConnectionState.Disconnected) { return; } if (_connectionState == ConnectionState.InProgress) { _connectTimer += deltaTime; if (_connectTimer > _peerListener.ReconnectDelay) { _connectTimer = 0; _connectAttempts++; if (_connectAttempts > _peerListener.MaxConnectAttempts) { _connectionState = ConnectionState.Disconnected; return; } //else send connect again SendConnectRequest(); } return; } //Get current flow mode int maxSendPacketsCount = _peerListener.GetPacketsPerSecond(_currentFlowMode); int currentMaxSend; if (maxSendPacketsCount > 0) { int availableSendPacketsCount = maxSendPacketsCount - _sendedPacketsCount; currentMaxSend = Math.Min(availableSendPacketsCount, (maxSendPacketsCount * deltaTime) / NetConstants.FlowUpdateTime); } else { currentMaxSend = int.MaxValue; } DebugWrite("[UPDATE]Delta: {0}ms, MaxSend: {1}", deltaTime, currentMaxSend); //Pending acks _reliableOrderedChannel.SendAcks(); _reliableUnorderedChannel.SendAcks(); //Pending send int currentSended = 0; while (currentSended < currentMaxSend) { //Get one of packets if (_reliableOrderedChannel.SendNextPacket() || _reliableUnorderedChannel.SendNextPacket() || _sequencedChannel.SendNextPacket() || _simpleChannel.SendNextPacket()) { currentSended++; } else { //no outgoing packets break; } } //Increase counter _sendedPacketsCount += currentSended; //ResetFlowTimer _flowTimer += deltaTime; if (_flowTimer >= NetConstants.FlowUpdateTime) { DebugWrite("[UPDATE]Reset flow timer, _sendedPackets - {0}", _sendedPacketsCount); _sendedPacketsCount = 0; _flowTimer = 0; } //Send ping _pingSendTimer += deltaTime; if (_pingSendTimer >= _peerListener.PingInterval) { DebugWrite("[PP] Send ping..."); //reset timer _pingSendTimer = 0; //send ping CreateAndSend(PacketProperty.Ping, _pingSequence); //reset timer _pingTimeStart = DateTime.UtcNow; } //RTT - round trip time _rttResetTimer += deltaTime; if (_rttResetTimer >= RttResetDelay) { _rttResetTimer = 0; //Rtt update _rtt = _avgRtt; _ping = _avgRtt; _peerListener.ConnectionLatencyUpdated(this, _ping); _rttCount = 1; } //MTU - Maximum transmission unit if (!_finishMtu) { _mtuCheckTimer += deltaTime; if (_mtuCheckTimer >= MtuCheckDelay) { _mtuCheckTimer = 0; _mtuCheckAttempts++; if (_mtuCheckAttempts >= MaxMtuCheckAttempts) { _finishMtu = true; } else { lock (_mtuMutex) { //Send increased packet if (_mtuIdx < NetConstants.PossibleMtu.Length - 1) { int newMtu = NetConstants.PossibleMtu[_mtuIdx + 1] - NetConstants.HeaderSize; var p = GetPacketFromPool(PacketProperty.MtuCheck, newMtu); p.RawData[1] = (byte)(_mtuIdx + 1); SendPacket(p); } } } } } //MTU - end //Flush if (_mergePos > 0) { if (_mergeCount > 1) { DebugWrite("Send merged: " + _mergePos + ", count: " + _mergeCount); _peerListener.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, _remoteEndPoint); } else { //Send without length information and merging _peerListener.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, _remoteEndPoint); } _mergePos = 0; _mergeCount = 0; } }
internal void Update(int deltaTime) { if (_connectionState == ConnectionState.Connected && _timeSinceLastPacket > _netManager.DisconnectTimeout) { NetUtils.DebugWrite( "[UPDATE] Disconnect by timeout: {0} > {1}", _timeSinceLastPacket, _netManager.DisconnectTimeout); _netManager.DisconnectPeer(this, DisconnectReason.Timeout, 0, true, null, 0, 0); return; } if (_connectionState == ConnectionState.ShutdownRequested) { if (_timeSinceLastPacket > _netManager.DisconnectTimeout) { _connectionState = ConnectionState.Disconnected; } else { _netManager.SendRaw(_shutdownPacket.RawData, 0, _shutdownPacket.Size, _remoteEndPoint); } return; } if (_connectionState == ConnectionState.Disconnected) { return; } _timeSinceLastPacket += deltaTime; if (_connectionState == ConnectionState.InProgress) { _connectTimer += deltaTime; if (_connectTimer > _netManager.ReconnectDelay) { _connectTimer = 0; _connectAttempts++; if (_connectAttempts > _netManager.MaxConnectAttempts) { _netManager.DisconnectPeer(this, DisconnectReason.ConnectionFailed, 0, true, null, 0, 0); return; } //else send connect again SendConnectRequest(); } return; } //Send ping _pingSendTimer += deltaTime; if (_pingSendTimer >= _netManager.PingInterval) { NetUtils.DebugWrite("[PP] Send ping..."); //reset timer _pingSendTimer = 0; //send ping CreateAndSend(PacketProperty.Ping, _pingSequence); //reset timer _pingTimeStart = DateTime.UtcNow; } //RTT - round trip time _rttResetTimer += deltaTime; if (_rttResetTimer >= RttResetDelay) { _rttResetTimer = 0; //Rtt update _rtt = _avgRtt; _ping = _avgRtt; _netManager.ConnectionLatencyUpdated(this, _ping); _rttCount = 1; } //Pending send Flush(); }