/// <summary> /// Updates the state of the peer and sends packets if needed. /// </summary> internal void _Update(UDPHub Hub, double Time, out bool Remove) { UDPHubSettings settings = this._Settings; OutTerminal oterm = this._OutTerminal; // Handle waves this._WaveDelay -= Time; if (this._WaveDelay <= 0.0) { // Check acknowledgement and adjust wave size if (oterm.AcknowledgementNumber == oterm.SendNumber) { if (this._FullWave) { this._WaveSize++; this._FullWave = false; } } else { oterm.SendNumber = oterm.AcknowledgementNumber; if (this._WaveSize > 1) { this._WaveSize--; } } int chunksequencenumber = 0; byte[] chunkdata = null; bool chunkinitial = false; bool chunkfinal = false; int wavesize = 0; if (oterm.Process(ref chunksequencenumber, ref chunkdata, ref chunkinitial, ref chunkfinal)) { while (true) { // Send chunk wavesize++; Packet chunk = new Packet { SequenceNumber = chunksequencenumber, ChunkData = chunkdata, ChunkInitial = chunkinitial, ChunkFinal = chunkfinal }; this._FillAdditional(chunk); Hub.Send(chunk, this._EndPoint); // Check if wave is full if (wavesize == this._WaveSize) { this._FullWave = true; break; } // Get next chunk if (!oterm.Process(ref chunksequencenumber, ref chunkdata, ref chunkinitial, ref chunkfinal)) { break; } } // Reset delays this._WaveDelay = this._RoundTripTime + settings.WaveRate; this._KeepAliveDelay = settings.KeepAliveDelay; } } // Send keep alive if needed this._KeepAliveDelay -= Time; if (this._KeepAliveDelay <= 0.0) { Packet packet = new Packet { SequenceNumber = this._OutTerminal.SendNumber }; this._FillAdditional(packet); Hub.Send(packet, this.EndPoint); this._KeepAliveDelay = settings.KeepAliveDelay; } // Check for implicit disconnect Remove = false; this._ExpireDelay -= Time; if (this._ExpireDelay <= 0.0) { Remove = true; } }
/// <summary> /// Immediately sends a ping response packet of some sort. /// </summary> private void _SendPingResponse(UDPHub Hub) { byte[] data = null; bool initial = false; bool final = false; int sequencenumber = 0; Packet packet; if(this._OutTerminal.Process(ref sequencenumber, ref data, ref initial, ref final)) { packet = new Packet { SequenceNumber = sequencenumber, ChunkData = data, ChunkInitial = initial, ChunkFinal = final }; } else { packet = new Packet { SequenceNumber = this._OutTerminal.SendNumber }; } packet.PingResponse = true; Hub.Send(packet, this.EndPoint); }
/// <summary> /// Called when an (unvalidated) packet is received for this peer. /// </summary> internal void _Receive(UDPHubSettings Settings, UDPHub Hub, Packet Packet, out bool Remove) { Remove = false; // Validate if (!this._Valid(Packet.SequenceNumber)) return; // Disconnect? if (Packet.Disconnect) { Remove = true; return; } // Reset expire delay this._ExpireDelay = Settings.ExpireDelay; // Read additional information int ack; if (Packet.AcknowledgementNumber.TryGetValue(out ack)) { this._OutTerminal.AcknowledgementNumber = ack; } double rtt; if (Packet.RoundTripTime.TryGetValue(out rtt)) { this._RoundTripTime = rtt; } // Chunk? if (Packet.ChunkData != null) { this._Process(Packet.SequenceNumber, Packet.ChunkData, Packet.ChunkInitial, Packet.ChunkFinal); } // Ping? if (Packet.PingRequest) { this._SendPingResponse(Hub); } }