public override async Task OnConnectedAsync(ConnectionContext connection) { if (_connectionLoops.ContainsKey(connection.RemoteEndPoint)) { _logger.LogWarning($"another inbound connection from a known peer: {connection.RemoteEndPoint.ToEndpointString()}. Ignoring"); return; } _logger.LogDebug($"New inbound connection from {connection.RemoteEndPoint.ToEndpointString()}"); var(descriptor, writeReceiver) = descriptorFactory.GetNewSocket(connection.Transport.Output); // TODO: using "BTC" here is not clean. var peerMan = PeerManagerProvider.GetPeerManager("BTC"); peerMan.NewInboundConnection(descriptor); Func <Task> cleanup = async() => { _connectionLoops.TryRemove(connection.RemoteEndPoint, out _); await _repository.RemoveRemoteEndPoint(connection.RemoteEndPoint); }; await _repository.SetRemoteEndPoint(connection.RemoteEndPoint); var conn = new ConnectionLoop(connection.Transport, descriptor, peerMan, writeReceiver, EventNotify.Writer, _loggerFactory.CreateLogger <ConnectionLoop>(), cleanup); _connectionLoops.TryAdd(connection.RemoteEndPoint, conn); conn.Start(connection.ConnectionClosed); await conn.ExecutionTask; }
private (ConnectionLoop, SocketDescriptor) CreateConnection(IDuplexPipe pipe) { var(socketDescriptor, writeReceiver) = _socketDescriptorFactory.GetNewSocket(pipe.Output); var conn = new ConnectionLoop(pipe, socketDescriptor, PeerManager, writeReceiver, EventNotify.Writer); return(conn, socketDescriptor); }
/// <summary> /// Returns `false` if the peer is already connected. otherwise return `true`. /// </summary> /// <param name="remoteEndPoint"></param> /// <param name="pubkey"></param> /// <param name="ct"></param> /// <returns>true if the peer is unknown</returns> public async ValueTask <bool> NewOutbound(EndPoint remoteEndPoint, PubKey pubkey, CancellationToken ct = default) { if (remoteEndPoint == null) { throw new ArgumentNullException(nameof(remoteEndPoint)); } if (pubkey == null) { throw new ArgumentNullException(nameof(pubkey)); } if (_connectionLoops.ContainsKey(remoteEndPoint)) { _logger.LogError($"We have already connected to: {remoteEndPoint.ToEndpointString()}."); return(false); } try { var connectionContext = await _connectionFactory.ConnectAsync(remoteEndPoint, ct); var(descriptor, writeReceiver) = descriptorFactory.GetNewSocket(connectionContext.Transport.Output); var peerMan = PeerManagerProvider.GetPeerManager("BTC"); var initialSend = peerMan.NewOutboundConnection(descriptor, pubkey.ToBytes()); await connectionContext.Transport.Output.WriteAsync(initialSend, ct); var flushResult = connectionContext.Transport.Output.FlushAsync(ct); if (!flushResult.IsCompleted) { await flushResult.ConfigureAwait(false); } Func <Task> cleanup = async() => { _connectionLoops.TryRemove(connectionContext.RemoteEndPoint, out _); await _repository.RemoveRemoteEndPoint(connectionContext.RemoteEndPoint, ct); }; await _repository.SetRemoteEndPoint(remoteEndPoint, ct); var conn = new ConnectionLoop(connectionContext.Transport, descriptor, peerMan, writeReceiver, EventNotify.Writer, _loggerFactory.CreateLogger <ConnectionLoop>(), cleanup); _connectionLoops.TryAdd(remoteEndPoint, conn); Task.Run(() => conn.Start(ct)); } catch (SocketException ex) when(ex.SocketErrorCode == SocketError.ConnectionRefused) { _logger.LogError($"{ex.Message}:{Environment.NewLine}{ex.StackTrace}"); return(false); } return(true); }