public NetworkPeer(NetworkAddress peerAddress, Network network, NetworkPeerConnectionParameters parameters, Socket socket, VersionPayload peerVersion, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) { this.RemoteSocketEndpoint = ((IPEndPoint)socket.RemoteEndPoint); this.RemoteSocketAddress = ((IPEndPoint)socket.RemoteEndPoint).Address; this.RemoteSocketPort = ((IPEndPoint)socket.RemoteEndPoint).Port; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType().FullName, $"[{this.RemoteSocketEndpoint}] "); this.logger.LogTrace("()"); this.dateTimeProvider = dateTimeProvider; this.Inbound = true; this.Behaviors = new NetworkPeerBehaviorsCollection(this); this.MyVersion = parameters.CreateVersion(peerAddress.Endpoint, network, this.dateTimeProvider.GetTimeOffset()); this.Network = network; this.PeerAddress = peerAddress; this.connection = new NetworkPeerConnection(this, socket, this.dateTimeProvider, this.loggerFactory); this.PeerVersion = peerVersion; this.LastSeen = peerAddress.Time.UtcDateTime; this.ConnectedAt = this.dateTimeProvider.GetUtcNow(); this.logger.LogTrace("Connected to advertised node '{0}'.", this.PeerAddress.Endpoint); this.State = NetworkPeerState.Connected; this.InitDefaultBehaviors(parameters); this.connection.BeginListen(); this.logger.LogTrace("(-)"); }
/// <summary> /// Adds client's connection to the list of active connections. /// </summary> /// <param name="connection">Client's connection to add.</param> private void AddClientConnection(NetworkPeerConnection connection) { this.logger.LogTrace("({0}.{1}:{2})", nameof(connection), nameof(connection.Id), connection.Id); this.connectionsById.AddOrReplace(connection.Id, connection); connection.ShutdownComplete.Task.ContinueWith(unused => this.RemoveConnectedClient(connection)); this.logger.LogTrace("(-)"); }
/// <summary> /// Dummy constructor for testing only. /// </summary> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Provider of time functions.</param> /// <remarks>TODO: Remove this constructor as soon as we can mock the node in tests.</remarks> public NetworkPeer(IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) { this.dateTimeProvider = dateTimeProvider; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.Behaviors = new NetworkPeerBehaviorsCollection(this); this.PeerAddress = new NetworkAddress(); this.Connection = new NetworkPeerConnection(null, this, new TcpClient(), 0, this.ProcessMessageAsync, this.dateTimeProvider, this.loggerFactory); }
/// <summary> /// Removes a connection from the list of active clients' connection. /// </summary> /// <param name="connection">Client to remove and disconnect.</param> private void RemoveConnectedClient(NetworkPeerConnection connection) { this.logger.LogTrace("({0}.{1}:{2})", nameof(connection), nameof(connection.Id), connection.Id); if (!this.connectionsById.TryRemove(connection.Id, out NetworkPeerConnection unused)) { this.logger.LogError("Internal data integration error."); } this.logger.LogTrace("(-)"); }
/// <summary> /// Dummy constructor for testing only. /// </summary> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Provider of time functions.</param> /// <remarks>TODO: Remove this constructor as soon as we can mock the node in tests.</remarks> public NetworkPeer(IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) { this.dateTimeProvider = dateTimeProvider; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.Behaviors = new NetworkPeerBehaviorsCollection(this); this.PeerEndPoint = new IPEndPoint(IPAddress.Loopback, 1); this.Connection = new NetworkPeerConnection(null, this, new TcpClient(), 0, this.ProcessMessageAsync, this.dateTimeProvider, this.loggerFactory); this.MessageReceived = new AsyncExecutionEvent <NetworkPeer, IncomingMessage>(); this.StateChanged = new AsyncExecutionEvent <NetworkPeer, NetworkPeerState>(); }
/// <summary> /// Initializes an instance of the object for outbound network peers. /// </summary> /// <param name="peerAddress">Information about the peer including its network address, protocol version, time of last contact.</param> /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="parameters">Various settings and requirements related to how the connections with peers are going to be established, or <c>null</c> to use default parameters.</param> /// <param name="networkPeerFactory">Factory for creating P2P network peers.</param> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Factory for creating loggers.</param> public NetworkPeer(NetworkAddress peerAddress, Network network, NetworkPeerConnectionParameters parameters, INetworkPeerFactory networkPeerFactory, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) : this(false, peerAddress, network, parameters, dateTimeProvider, loggerFactory) { NetworkPeerClient client = networkPeerFactory.CreateNetworkPeerClient(parameters); this.logger = loggerFactory.CreateLogger(this.GetType().FullName, $"[{client.Id}-{peerAddress.Endpoint}] "); this.logger.LogTrace("()"); this.Connection = new NetworkPeerConnection(this, client, this.dateTimeProvider, this.loggerFactory); this.logger.LogTrace("(-)"); }
/// <summary> /// Initializes an instance of the object for outbound network peers. /// </summary> /// <param name="peerAddress">Information about the peer including its network address, protocol version, time of last contact.</param> /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="parameters">Various settings and requirements related to how the connections with peers are going to be established, or <c>null</c> to use default parameters.</param> /// <param name="networkPeerFactory">Factory for creating P2P network peers.</param> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Factory for creating loggers.</param> public NetworkPeer(NetworkAddress peerAddress, Network network, NetworkPeerConnectionParameters parameters, INetworkPeerFactory networkPeerFactory, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) : this(false, peerAddress, network, parameters, dateTimeProvider, loggerFactory) { this.logger.LogTrace("()"); NetworkPeerClient client = networkPeerFactory.CreateNetworkPeerClient(parameters); this.Connection = new NetworkPeerConnection(this, client, this.dateTimeProvider, this.loggerFactory); this.ConnectAsync(parameters.ConnectCancellation).GetAwaiter().GetResult(); this.InitDefaultBehaviors(parameters); this.Connection.StartReceiveMessages(); this.logger.LogTrace("(-)"); }
/// <summary> /// Initializes an instance of the object for outbound network peers. /// </summary> /// <param name="peerEndPoint">IP address and port on the side of the peer.</param> /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="parameters">Various settings and requirements related to how the connections with peers are going to be established, or <c>null</c> to use default parameters.</param> /// <param name="networkPeerFactory">Factory for creating P2P network peers.</param> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Factory for creating loggers.</param> public NetworkPeer(IPEndPoint peerEndPoint, Network network, NetworkPeerConnectionParameters parameters, INetworkPeerFactory networkPeerFactory, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) : this(false, peerEndPoint, network, parameters, dateTimeProvider, loggerFactory) { TcpClient client = new TcpClient(AddressFamily.InterNetworkV6); client.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); client.Client.ReceiveBufferSize = parameters.ReceiveBufferSize; client.Client.SendBufferSize = parameters.SendBufferSize; this.Connection = networkPeerFactory.CreateNetworkPeerConnection(this, client, this.ProcessMessageAsync); this.logger = loggerFactory.CreateLogger(this.GetType().FullName, $"[{this.Connection.Id}-{peerEndPoint}] "); this.logger.LogTrace("()"); this.logger.LogTrace("(-)"); }
/// <summary> /// Initializes an instance of the object for inbound network peers with already established connection. /// </summary> /// <param name="peerAddress">Information about the peer including its network address, protocol version, time of last contact.</param> /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="parameters">Various settings and requirements related to how the connections with peers are going to be established, or <c>null</c> to use default parameters.</param> /// <param name="client">Already connected network client.</param> /// <param name="peerVersion">Version message payload received from the peer.</param> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Factory for creating loggers.</param> public NetworkPeer(NetworkAddress peerAddress, Network network, NetworkPeerConnectionParameters parameters, NetworkPeerClient client, VersionPayload peerVersion, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) : this(true, peerAddress, network, parameters, dateTimeProvider, loggerFactory) { this.logger.LogTrace("()"); this.RemoteSocketEndpoint = client.RemoteEndPoint; this.RemoteSocketAddress = this.RemoteSocketEndpoint.Address; this.RemoteSocketPort = this.RemoteSocketEndpoint.Port; this.PeerVersion = peerVersion; this.Connection = new NetworkPeerConnection(this, client, this.dateTimeProvider, this.loggerFactory); this.ConnectedAt = this.dateTimeProvider.GetUtcNow(); this.logger.LogTrace("Connected to advertised node '{0}'.", this.PeerAddress.Endpoint); this.State = NetworkPeerState.Connected; this.InitDefaultBehaviors(parameters); this.Connection.StartReceiveMessages(); this.logger.LogTrace("(-)"); }
/// <summary> /// Initializes an instance of the object for inbound network peers with already established connection. /// </summary> /// <param name="peerEndPoint">IP address and port on the side of the peer.</param> /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="parameters">Various settings and requirements related to how the connections with peers are going to be established, or <c>null</c> to use default parameters.</param> /// <param name="client">Already connected network client.</param> /// <param name="peerVersion">Version message payload received from the peer.</param> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Factory for creating loggers.</param> public NetworkPeer(IPEndPoint peerEndPoint, Network network, NetworkPeerConnectionParameters parameters, TcpClient client, IDateTimeProvider dateTimeProvider, INetworkPeerFactory networkPeerFactory, ILoggerFactory loggerFactory) : this(true, peerEndPoint, network, parameters, dateTimeProvider, loggerFactory) { this.Connection = networkPeerFactory.CreateNetworkPeerConnection(this, client, this.ProcessMessageAsync); this.logger = loggerFactory.CreateLogger(this.GetType().FullName, $"[{this.Connection.Id}-{peerEndPoint}] "); this.logger.LogTrace("()"); this.RemoteSocketEndpoint = this.PeerEndPoint; this.RemoteSocketAddress = this.RemoteSocketEndpoint.Address; this.RemoteSocketPort = this.RemoteSocketEndpoint.Port; this.ConnectedAt = this.dateTimeProvider.GetUtcNow(); this.logger.LogTrace("Connected to peer '{0}'.", this.PeerEndPoint); this.State = NetworkPeerState.Connected; this.InitDefaultBehaviors(this.Parameters); this.Connection.StartReceiveMessages(); this.logger.LogTrace("(-)"); }
public NetworkPeer(NetworkAddress peerAddress, Network network, NetworkPeerConnectionParameters parameters, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) { this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType().FullName, $"[{peerAddress.Endpoint}] "); this.logger.LogTrace("()"); this.dateTimeProvider = dateTimeProvider; parameters = parameters ?? new NetworkPeerConnectionParameters(); this.Inbound = false; this.Behaviors = new NetworkPeerBehaviorsCollection(this); this.MyVersion = parameters.CreateVersion(peerAddress.Endpoint, network, this.dateTimeProvider.GetTimeOffset()); this.Network = network; this.PeerAddress = peerAddress; this.LastSeen = peerAddress.Time.UtcDateTime; var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); this.connection = new NetworkPeerConnection(this, socket, this.dateTimeProvider, this.loggerFactory); socket.ReceiveBufferSize = parameters.ReceiveBufferSize; socket.SendBufferSize = parameters.SendBufferSize; try { using (var completedEvent = new ManualResetEvent(false)) { using (var nodeSocketEventManager = NodeSocketEventManager.Create(completedEvent, peerAddress.Endpoint)) { this.logger.LogTrace("Connecting to '{0}'.", peerAddress.Endpoint); // If the socket connected straight away (synchronously) unblock all threads. if (!socket.ConnectAsync(nodeSocketEventManager.SocketEvent)) { completedEvent.Set(); } // Otherwise wait for the socket connection to complete OR if the operation got cancelled. WaitHandle.WaitAny(new WaitHandle[] { completedEvent, parameters.ConnectCancellation.WaitHandle }); parameters.ConnectCancellation.ThrowIfCancellationRequested(); if (nodeSocketEventManager.SocketEvent.SocketError != SocketError.Success) { throw new SocketException((int)nodeSocketEventManager.SocketEvent.SocketError); } var remoteEndpoint = (IPEndPoint)(socket.RemoteEndPoint ?? nodeSocketEventManager.SocketEvent.RemoteEndPoint); this.RemoteSocketAddress = remoteEndpoint.Address; this.RemoteSocketEndpoint = remoteEndpoint; this.RemoteSocketPort = remoteEndpoint.Port; this.State = NetworkPeerState.Connected; this.ConnectedAt = this.dateTimeProvider.GetUtcNow(); this.logger.LogTrace("Outbound connection to '{0}' established.", peerAddress.Endpoint); } } } catch (OperationCanceledException) { this.logger.LogTrace("Connection to '{0}' cancelled.", peerAddress.Endpoint); Utils.SafeCloseSocket(socket); this.State = NetworkPeerState.Offline; throw; } catch (Exception ex) { this.logger.LogTrace("Exception occurred: {0}", ex.ToString()); Utils.SafeCloseSocket(socket); this.DisconnectReason = new NetworkPeerDisconnectReason() { Reason = "Unexpected exception while connecting to socket", Exception = ex }; this.State = NetworkPeerState.Failed; throw; } this.InitDefaultBehaviors(parameters); this.connection.BeginListen(); this.logger.LogTrace("(-)"); }