コード例 #1
0
ファイル: Manager.cs プロジェクト: ciprianp/dcomms
        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
        }
コード例 #2
0
ファイル: Manager.cs プロジェクト: ciprianp/dcomms
        /// <summary>
        /// receiver thread
        /// changes state of connected peer
        /// </summary>
        internal void ProcessReceivedHello(byte[] udpData, IPEndPoint remoteEndpoint, SocketWithReceiver socket, uint packetReceivedTimestamp32)
        {
            // enqueue into manager thread // reduce load of the receiver thread
            _actionsQueue.Enqueue(() =>
            {
                var helloPacket = new PeerHelloPacket(udpData);

                if (_localPeer.IpLocationScraper == null && !String.IsNullOrEmpty(helloPacket.RequestedFromIp))
                {
                    _localPeer.IpLocationScraper = new IpLocationScraper(helloPacket.RequestedFromIp, _localPeer);
                }

                if (helloPacket.ToPeerId == null)
                {
                    if (helloPacket.Status.IsSetupOrPing())
                    {
                        if (_localPeer.Configuration.RoleAsCoordinator)
                        {
                            ProcessReceivedHello_SetupRequestFromNewPeer(helloPacket, remoteEndpoint, socket, _localPeer.LocalPeerId, packetReceivedTimestamp32);
                        }
                        else
                        {
                            _localPeer.Firewall.OnUnauthenticatedReceivedPacket(remoteEndpoint);
                            PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
                        }
                    }
                    else
                    {
                        _localPeer.Firewall.OnUnauthenticatedReceivedPacket(remoteEndpoint);
                    }
                }
                else if (helloPacket.ToPeerId.Equals(_localPeer.LocalPeerId) == false)
                { // bad ToPeerId  // can happen if this peer restarts
                    _localPeer.Firewall.OnUnauthenticatedReceivedPacket(remoteEndpoint);
                    if (helloPacket.Status.IsSetupOrPing())
                    {
                        PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_tryCleanSetup, null, socket, remoteEndpoint);
                    }
                }
                else if (_pendingPeers.ContainsKey(remoteEndpoint))
                {// correct ToPeerId and remote endpoint is in _initiallyNotRespondedServers
                    ProcessReceivedHello_FromPendingPeer(helloPacket, remoteEndpoint, packetReceivedTimestamp32);
                }
                else
                {     // correct ToPeerId
                    if (_connectedPeers.TryGetValue(helloPacket.FromPeerId, out var connectedPeer))
                    { // packet from already connected peer
                        ProcessReceivedHello_FromExistingPeer(helloPacket, remoteEndpoint, socket, connectedPeer, packetReceivedTimestamp32);
                    }
                    else if (helloPacket.Status.IsSetupOrPing())
                    { // FromPeerId is unknown, ToPeerId is this one // request to set up connection from new peer
                        ProcessReceivedHello_SetupRequestFromNewPeer(helloPacket, remoteEndpoint, socket, null, packetReceivedTimestamp32);
                    }
                }
            }, "ProcessReceivedHello634569");
        }
コード例 #3
0
ファイル: Manager.cs プロジェクト: gvsurenderreddy/dcomms
        /// <summary>
        /// for both coordinatorServer and userPeer
        /// accepts connection, adds peer and/or stream to lists, responds with 'accepted'
        /// </summary>
        void ProcessReceivedHello_SetupRequestFromNewPeer(PeerHelloPacket helloPacket, IPEndPoint remoteEndpoint, SocketWithReceiver socket, PeerId localPeerIdForResponse)
        {
            if (_localPeer.Configuration.RoleAsCoordinator)
            {
                if (_connectedPeers.Count > LocalLogicConfiguration.CoordinatorPeer_MaxConnectedPeersToAccept)
                {
                    _localPeer.SysAdminFeedbackChannel.OnReachedMaxConnectedPeersAtThisCoordinatorServer();
                    PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_tryLater, null, socket, remoteEndpoint);
                    return;
                }
            }
            else if (_localPeer.Configuration.RoleAsSharedPassive)
            {
                if (_connectedPeers.Count > LocalLogicConfiguration.SharedPeer_MaxConnectedPeersToAccept)
                {
                    _localPeer.SysAdminFeedbackChannel.OnReachedMaxConnectedPeersAtThisSharedPeer();
                    _localPeer.WriteToLog(LogModules.Hello, $"rejecting request from {remoteEndpoint}: _connectedPeers.Count={_connectedPeers.Count} > LocalLogicConfiguration.SharedPeer_MaxConnectedPeersToAccept");
                    PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
                    return;
                }
            }
            else if (_localPeer.Configuration.RoleAsUser)
            {
                if (_connectedPeers.Count > LocalLogicConfiguration.UserPeer_MaxConnectedPeersToAccept)
                {
                    _localPeer.WriteToLog(LogModules.Hello, $"rejecting request from {remoteEndpoint}: _connectedPeers.Count={_connectedPeers.Count} > LocalLogicConfiguration.UserPeer_MaxConnectedPeersToAccept");
                    PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
                    return;
                }
            }

            if (!_connectedPeers.TryGetValue(helloPacket.FromPeerId, out var peer))
            {
                peer = new ConnectedPeer(_localPeer, helloPacket.FromPeerId)
                {
                    Type = ConnectedPeerType.fromPeerAccepted
                };
                lock (_connectedPeers)
                    _connectedPeers.Add(helloPacket.FromPeerId, peer);
            }

            if (peer.Streams.Count > LocalLogicConfiguration.ConnectedPeerMaxStreamsCount)
            {
                _localPeer.WriteToLog(LogModules.Hello, $"rejecting request from {remoteEndpoint}: peer.Streams.Count={peer.Streams.Count} > LocalLogicConfiguration.ConnectedPeerMaxStreamsCount");
                PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
            }
            else
            {
                var stream = peer.TryAddStream(socket, remoteEndpoint, helloPacket.StreamId);
                _localPeer.WriteToLog(LogModules.Hello, $"created new stream {stream} from new peer {peer}");

                PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.accepted, localPeerIdForResponse, socket, remoteEndpoint, _localPeer.Configuration.RoleAsUser);
            }
        }
コード例 #4
0
ファイル: Manager.cs プロジェクト: ciprianp/dcomms
        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());
            }
        }
コード例 #5
0
ファイル: Manager.cs プロジェクト: ciprianp/dcomms
        void ProcessReceivedHello_FromPendingPeer(PeerHelloPacket helloPacket, IPEndPoint remoteEndpoint, uint packetReceivedTime32)
        {
            var pendingPeer = _pendingPeers[remoteEndpoint];
            var stream      = pendingPeer.Streams.Values.Single(); // must be only 1 stream in the ConnectedPeer (as initially configured)

            if (!stream.StreamId.Equals(helloPacket.StreamId))
            {
                _localPeer.Firewall.OnUnauthenticatedReceivedPacket(remoteEndpoint);
                return;
            }

            switch (helloPacket.Status)
            {
            case PeerHelloRequestStatus.accepted:
            {
                _pendingPeers.Remove(remoteEndpoint);

                if (!_connectedPeers.TryGetValue(helloPacket.FromPeerId, out var alreadyRespondedPeer))
                {         // first-stream response from this server
                    pendingPeer.RemotePeerId = helloPacket.FromPeerId;
                    _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"received initial hello response from pending peer {pendingPeer}");
                    lock (_connectedPeers)
                        _connectedPeers.Add(helloPacket.FromPeerId, pendingPeer);
                    ProcessReceivedAcceptedHello_UpdateHelloLevelFields(pendingPeer, stream, helloPacket, packetReceivedTime32);
                }
                else
                {         // secondary streams response: move ConnectedPeerStream
                    _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"received secondary-stream hello response from {remoteEndpoint}, pending peer {alreadyRespondedPeer}");
                    if (!alreadyRespondedPeer.Streams.ContainsKey(stream.StreamId))
                    {
                        pendingPeer.RemoveStream(stream);
                        alreadyRespondedPeer.TryAddStream(stream.Socket, stream.RemoteEndPoint, stream.StreamId);

                        //  alreadyRespondedPeer.Streams.Add(stream.StreamId, stream);
                        //  foreach (var sx in stream.Extensions)
                        //       sx.Value.OnMovedToConnectedPeer();
                        ProcessReceivedAcceptedHello_UpdateHelloLevelFields(alreadyRespondedPeer, stream, helloPacket, packetReceivedTime32);
                    }
                    else
                    {
                        throw new Exception("alreadyRespondedPeer.Streams.ContainsKey(stream.StreamId)");
                    }
                }
            }
            break;

            case PeerHelloRequestStatus.rejected_dontTryLater:
            {
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"received {helloPacket.Status} hello response from pending peer {pendingPeer}");
                _pendingPeers.Remove(remoteEndpoint);
            }
            break;

            case PeerHelloRequestStatus.rejected_tryCleanSetup:
            {
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"received {helloPacket.Status} hello response from pending peer {pendingPeer}");
                stream.StreamId = _localPeer.Manager.CreateNewUniqueStreamId();
                _pendingPeers.Remove(remoteEndpoint);
            }
            break;
            }
        }
コード例 #6
0
ファイル: Manager.cs プロジェクト: ciprianp/dcomms
        void ProcessReceivedHello_FromExistingPeer(PeerHelloPacket helloPacket, IPEndPoint remoteEndpoint, SocketWithReceiver socket, ConnectedPeer connectedPeer, uint packetReceivedTimestamp32)
        {
            // current situation:
            // received hello packet; this peer wants to accept connection
            // in hello packet FromPeerId matches to existing connected peer
            // there is already at least 1 stream in the existing peer; it could be request via this stream or via another stream
            // it could be request (ping) or response
            // it could be packet to new stream, or to existing stream
            // it could be packet from changed remote endpoint to same stream ID
            // it could be packet from wrong remote endpoint to new (non-existing locally) stream ID   ???????????????????????

            if (!connectedPeer.Streams.TryGetValue(helloPacket.StreamId, out var stream))
            { // received packet in new streamId
                if (helloPacket.Status.IsSetupOrPing())
                {
                    if (connectedPeer.Streams.Count > LocalLogicConfiguration.ConnectedPeerMaxStreamsCount)
                    {
                        _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"rejecting request from {remoteEndpoint}: connectedPeer.Streams.Count={connectedPeer.Streams.Count} > LocalLogicConfiguration.ConnectedPeerMaxStreamsCount");
                        PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
                        return;
                    }
                    stream = connectedPeer.TryAddStream(socket, remoteEndpoint, helloPacket.StreamId);
                    //   _localPeer.WriteToLog(LogModules.Hello, $"peer {connectedPeer} received hello from new stream {stream}");
                    if (stream == null)
                    {
                        throw new InvalidOperationException();
                    }
                }
                else
                {
                    _localPeer.Firewall.OnUnauthenticatedReceivedPacket(remoteEndpoint);
                    return;
                }
            }
            else
            {// received packet in existing streamId
                // check source endpoint
                if (!remoteEndpoint.Equals(stream.RemoteEndPoint))
                { // dont allow change of source ip/port within same stream
                    _localPeer.Firewall.OnUnauthenticatedReceivedPacket(remoteEndpoint);
                    if (helloPacket.Status.IsSetupOrPing())
                    {
                        PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_tryCleanSetup, null, socket, remoteEndpoint);
                    }
                    return;
                }
            }

            // current situation: we got connectedPeer, stream.  we handle request or response
            if (!RemoteVersionIsAcceptableForNewConnection(helloPacket))
            {
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"peer {connectedPeer} got response with too old version");
                connectedPeer.RemoveStream(stream);
                _connectedPeers.Remove(connectedPeer.RemotePeerId);
                return;
            }

            switch (helloPacket.Status)
            {
            case PeerHelloRequestStatus.setup:
            case PeerHelloRequestStatus.ping:
                var responseCpuDelayMs = (ushort)Math.Round(TimeSpan.FromTicks(unchecked (_localPeer.Time32 - packetReceivedTimestamp32)).TotalMilliseconds);
                PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.accepted, null, socket, remoteEndpoint, responseCpuDelayMs, _localPeer.Configuration.RoleAsUser, _localPeer.IpLocationScraper?.IpLocationData);
                break;

            case PeerHelloRequestStatus.accepted:
                ProcessReceivedAcceptedHello_UpdateHelloLevelFields(connectedPeer, stream, helloPacket, packetReceivedTimestamp32);
                break;

            case PeerHelloRequestStatus.rejected_tryCleanSetup:
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"peer {connectedPeer} received {helloPacket.Status} from stream {stream}");
                connectedPeer.RemoveStream(stream);
                AddToPendingPeers(connectedPeer.Type, remoteEndpoint, socket);
                break;

            case PeerHelloRequestStatus.rejected_dontTryLater:
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"peer {connectedPeer} received {helloPacket.Status} from stream {stream}");
                connectedPeer.RemoveStream(stream);
                break;

            case PeerHelloRequestStatus.rejected_tryLater:
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"peer {connectedPeer} received {helloPacket.Status} from stream {stream}");
                // it will try anyway on timer
                break;
            }
        }
コード例 #7
0
ファイル: Manager.cs プロジェクト: ciprianp/dcomms
        /// <summary>
        /// for both coordinatorServer and userPeer
        /// accepts connection, adds peer and/or stream to lists, responds with 'accepted'
        /// </summary>
        void ProcessReceivedHello_SetupRequestFromNewPeer(PeerHelloPacket helloPacket, IPEndPoint remoteEndpoint, SocketWithReceiver socket, PeerId localPeerIdForResponse, uint requestReceivedTimestamp32)
        {
            if (_localPeer.Configuration.RoleAsCoordinator)
            {
                if (_connectedPeers.Count > LocalLogicConfiguration.CoordinatorPeer_MaxConnectedPeersToAccept)
                {
                    _localPeer.SysAdminFeedbackChannel.OnReachedMaxConnectedPeersAtThisCoordinatorServer();
                    PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_tryLater, null, socket, remoteEndpoint);
                    return;
                }
            }
            else if (_localPeer.Configuration.RoleAsSharedPassive)
            {
                if (_connectedPeers.Count > LocalLogicConfiguration.SharedPeer_MaxConnectedPeersToAccept)
                {
                    _localPeer.SysAdminFeedbackChannel.OnReachedMaxConnectedPeersAtThisSharedPeer();
                    _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"rejecting request from {remoteEndpoint}: _connectedPeers.Count={_connectedPeers.Count} > LocalLogicConfiguration.SharedPeer_MaxConnectedPeersToAccept");
                    PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
                    return;
                }
            }
            else if (_localPeer.Configuration.RoleAsUser)
            {
                if (_connectedPeers.Count > LocalLogicConfiguration.UserPeer_MaxConnectedPeersToAccept)
                {
                    _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"rejecting request from {remoteEndpoint}: _connectedPeers.Count={_connectedPeers.Count} > LocalLogicConfiguration.UserPeer_MaxConnectedPeersToAccept");
                    PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
                    return;
                }
                if (!RemoteVersionIsAcceptableForNewConnection(helloPacket))
                {
                    _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"rejecting request from {remoteEndpoint}: old version");
                    PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
                    return;
                }
            }

            if (!_connectedPeers.TryGetValue(helloPacket.FromPeerId, out var peer))
            {
                peer = new ConnectedPeer(_localPeer, helloPacket.FromPeerId, ConnectedPeerType.fromPeerAccepted, remoteEndpoint.Address);
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"accepted initial hello from peer {peer}");
                lock (_connectedPeers)
                    _connectedPeers.Add(helloPacket.FromPeerId, peer);
            }

            if (peer.Streams.Count > LocalLogicConfiguration.ConnectedPeerMaxStreamsCount)
            {
                _localPeer.WriteToLog_deepDetail(LogModules.Hello, $"rejecting request from {remoteEndpoint}: peer.Streams.Count={peer.Streams.Count} > LocalLogicConfiguration.ConnectedPeerMaxStreamsCount");
                PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.rejected_dontTryLater, null, socket, remoteEndpoint);
            }
            else
            {
                var stream = peer.TryAddStream(socket, remoteEndpoint, helloPacket.StreamId);
                //  _localPeer.WriteToLog(LogModules.Hello, $"created new stream {stream} from new peer {peer}");

                var responseCpuDelayMs = (ushort)Math.Round(TimeSpan.FromTicks(unchecked (_localPeer.Time32 - requestReceivedTimestamp32)).TotalMilliseconds);
                PeerHelloPacket.Respond(helloPacket, PeerHelloRequestStatus.accepted, localPeerIdForResponse, socket, remoteEndpoint,
                                        responseCpuDelayMs,
                                        _localPeer.Configuration.RoleAsUser);
            }
        }
コード例 #8
0
ファイル: Manager.cs プロジェクト: ciprianp/dcomms
 bool RemoteVersionIsAcceptableForNewConnection(PeerHelloPacket remoteHello)
 {
     return(MiscProcedures.Uint32secondsToDateTime(remoteHello.LibraryVersion) > MiscProcedures.MinPeerCompilationDateTimeUtcExclusive);
 }
コード例 #9
0
ファイル: Manager.cs プロジェクト: gvsurenderreddy/dcomms
        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());
            }
        }