private void _Receive(IPEndPoint From, Temporary<Data> Data) { Data data = Data; int size = (int)data.Size; UDPHubSettings settings = this._Settings; // Find the peer that sent this message UDPPeer peer; if (this._Peers.TryGetValue(From, out peer)) { bool remove; using (Disposable<InStream> str = data.Read()) { peer._Receive(settings, this, Packet.Read(str, size), out remove); } if (remove) { this._Disconnect(peer); this._Peers.Remove(From); } } // See if this packet is a connection request, or a response to one if (size >= 5) { using (Disposable<InStream> dstr = data.Read()) { InStream str = dstr; PacketFlags flags = (PacketFlags)str.ReadByte(); if (flags == PacketFlags.ConnectionRequest && size == 5) { // Connection requested int seq = str.ReadInt(); if (_ShouldAccept(From)) { int ack = settings.Random.Integer(); this._Connect(peer = UDPPeer._InitializeServer(settings, From, seq, ack)); if (this.Accepted != null) { this.Accepted(peer); } BufferOutStream bos = new BufferOutStream(settings.SendBuffer, 0); bos.WriteByte((byte)PacketFlags.ConnectionAccept); bos.WriteInt(seq); bos.WriteInt(ack); this._UDP.Send(From, DUIP.Data.FromBuffer(bos.Buffer, 0, bos.Position)); } else { BufferOutStream bos = new BufferOutStream(settings.SendBuffer, 0); bos.WriteByte((byte)PacketFlags.ConnectionRefuse); bos.WriteInt(seq); this._UDP.Send(From, DUIP.Data.FromBuffer(bos.Buffer, 0, bos.Position)); } } _ConnectionRequest cr; if (flags == PacketFlags.ConnectionAccept && size == 9 && this._ConnectionRequests.TryGetValue(From, out cr)) { // Connection accepted by client int ack = str.ReadInt(); int seq = str.ReadInt(); if (ack == cr.AcknowledgementNumber) { this._Connect(peer = UDPPeer._InitializeClient(settings, From, seq, ack, cr.Time)); cr.Query.Complete(peer); this._ConnectionRequests.Remove(From); } } if (flags == PacketFlags.ConnectionRefuse && size == 5 && this._ConnectionRequests.TryGetValue(From, out cr)) { // Connection explicitly refused by peer int ack = str.ReadInt(); if (ack == cr.AcknowledgementNumber) { cr.Query.Cancel(); this._ConnectionRequests.Remove(From); } } } } }
/// <summary> /// Updates the state of outgoing connection requests for this hub. /// </summary> private void _UpdateConnectionRequests(double Time) { UDPHubSettings settings = this.Settings; if (this._ConnectionRequests.Count > 0) { List<IPEndPoint> toremove = new List<IPEndPoint>(); foreach (KeyValuePair<IPEndPoint, _ConnectionRequest> req in this._ConnectionRequests) { IPEndPoint e = req.Key; _ConnectionRequest cr = req.Value; cr.Time += Time; cr.Remain -= Time; if (cr.Remain > 0.0) { double reqrate = settings.ConnectionRequestRate; cr.Delay -= Time; while (cr.Delay <= 0.0) { // Send request packet BufferOutStream bos = new BufferOutStream(settings.SendBuffer, 0); bos.WriteByte((byte)PacketFlags.ConnectionRequest); bos.WriteInt(cr.AcknowledgementNumber); this._UDP.Send(e, DUIP.Data.FromBuffer(bos.Buffer, 0, bos.Position)); cr.Delay += reqrate; } } else { cr.Query.Cancel(); toremove.Add(e); } } foreach (IPEndPoint r in toremove) { this._ConnectionRequests.Remove(r); } } }
/// <summary> /// Uses the connection and settings of this hub to send a packet to the given endpoint. /// </summary> public void Send(Packet Packet, IPEndPoint To) { BufferOutStream bos = new BufferOutStream(this._Settings.SendBuffer, 0); Packet.Write(Packet, bos); this._UDP.Send(To, Data.FromBuffer(bos.Buffer, 0, bos.Position)); }