void SendHelloRequestToPeer(DateTime now, ConnectedPeer peer, ConnectedPeerStream stream, bool requestIpLocation) { var data = new PeerHelloPacket(_localPeer, peer, stream, stream.LastTimeReceivedAccepted.HasValue ? PeerHelloRequestStatus.ping : PeerHelloRequestStatus.setup, requestIpLocation).Encode(); stream.LastTimeSentRequest = now; stream.Socket.UdpSocket.Send(data, data.Length, stream.RemoteEndPoint); // send from all local sockets to all remote sockets to open P2P connection in the NAT }
/// <summary> /// the only procedure which creates/adds streams /// manager thread /// this will initiate hello-level packets to remote peer /// </summary> /// <param name="streamId"> /// if null, it generates random ID, using optional notAllowedStreamIds /// </param> /// <returns> /// null is stream with this StreamId already exists /// </returns> internal ConnectedPeerStream TryAddStream(SocketWithReceiver socket, IPEndPoint remoteEP, StreamId streamId = null, IEnumerable <StreamId> notAllowedStreamIds = null) { if (streamId == null) { _retry: streamId = _localPeer.Manager.CreateNewUniqueStreamId(); if (Streams.ContainsKey(streamId)) { goto _retry; } if (notAllowedStreamIds != null) { if (notAllowedStreamIds.Any(x => x.Equals(streamId))) { goto _retry; } } } else { if (_localPeer.Manager.IsItUniqueStreamId(streamId) == false) { return(null); } } var r = new ConnectedPeerStream(_localPeer, this, streamId, remoteEP, socket); lock (Streams) Streams.Add(streamId, r); socket.OnCreatedDestroyedStream(r, true); return(r); }
/// <summary> /// the only procedure which removes/destroys streams /// </summary> internal void RemoveStream(ConnectedPeerStream stream) { lock (Streams) Streams.Remove(stream.StreamId); stream.Socket.OnCreatedDestroyedStream(stream, false); foreach (var streamExtension in stream.Extensions.Values) { streamExtension.OnDestroyed(); } }
/// <summary> /// is executed by manager thread /// passes the stream to receiver thread and updates streams hash table of this receiver /// </summary> internal void OnCreatedDestroyedStream(ConnectedPeerStream stream, bool createdOrDestroyed) { _actionsQueue.Enqueue(() => { if (createdOrDestroyed) { _streams.Add(stream.StreamId, stream); // todo can be exception of duplicate key in rare cases? } else { _streams.Remove(stream.StreamId); } }); }
void ProcessReceivedAcceptedHello_UpdateHelloLevelFields(ConnectedPeer connectedPeer, ConnectedPeerStream stream, PeerHelloPacket helloResponsePacket, uint responseReceivedTime32) { var rtt = TimeSpan.FromTicks(unchecked (responseReceivedTime32 - helloResponsePacket.RequestTime32)) - TimeSpan.FromMilliseconds(helloResponsePacket.ResponseCpuDelayMs ?? 0); if (rtt < TimeSpan.Zero) { rtt = TimeSpan.Zero; // avoid abnormal measurements } stream.LatestHelloRtt = rtt; stream.LocalPeerPublicIp = helloResponsePacket.RequestedFromIp; stream.LastTimeReceivedAccepted = _localPeer.DateTimeNowUtc; connectedPeer.ProtocolVersion = helloResponsePacket.ProtocolVersion; connectedPeer.LibraryVersion = MiscProcedures.Uint32secondsToDateTime(helloResponsePacket.LibraryVersion); connectedPeer.TotalHelloAcceptedPacketsReceived++; stream.TotalHelloAcceptedPacketsReceived++; stream.RemotePeerRoleIsUser = helloResponsePacket.RoleFlagIsUser; if (helloResponsePacket.IpLocationData != null && connectedPeer.RemoteIpLocationData == null) { _localPeer.WriteToLog_higherLevelDetail(LogModules.Hello, $"got IP location from peer {connectedPeer}: {helloResponsePacket.IpLocationData}"); connectedPeer.RemoteIpLocationData = helloResponsePacket.IpLocationData; } if (helloResponsePacket.ExtensionIds != null && helloResponsePacket.ExtensionIds.Length != 0) { connectedPeer.LatestReceivedRemoteExtensionIds = new HashSet <string>(helloResponsePacket.ExtensionIds.Distinct()); } }
void ProcessReceivedAcceptedHello_UpdateHelloLevelFields(ConnectedPeer connectedPeer, ConnectedPeerStream stream, PeerHelloPacket helloPacket) { stream.LatestHelloRtt = TimeSpan.FromTicks(unchecked (_localPeer.Time32 - helloPacket.RequestTime32)); stream.LastTimeReceivedAccepted = _localPeer.DateTimeNowUtc; connectedPeer.ProtocolVersion = helloPacket.ProtocolVersion; connectedPeer.LibraryVersion = CompilationInfo.ToDateTime(helloPacket.LibraryVersion); connectedPeer.TotalHelloAcceptedPacketsReceived++; stream.TotalHelloAcceptedPacketsReceived++; stream.RemotePeerRoleIsUser = helloPacket.RoleFlagIsUser; if (helloPacket.ExtensionIds != null && helloPacket.ExtensionIds.Length != 0) { connectedPeer.LatestReceivedRemoteExtensionIds = new HashSet <string>(helloPacket.ExtensionIds.Distinct()); } }