public async void New_AfterConnecting_FiresMessageReceivedWhenDataAvailable() { var versionMessage = new MsgVersion() { ProtocolVersion = 1 }; var versionMessageHeader = new MessageHeader(_currencyNet, MsgCommand.Version, versionMessage.Encode()); // Write the header + message to the READ stream, then reset the stream position. var writer = new BinaryWriter(_readStream); versionMessageHeader.Encode(writer); versionMessage.Encode(writer); _readStream.Position = 0; var subject = new Peer(_networkClientMock.Object, _currencyNet); await subject.ConnectAsync(); // Closure to capture the data passed to the raised event PeerMessageReceivedArgs eventArgs = null; var resetEvent = new ManualResetEvent(false); subject.MessageReceived += (sender, e) => { eventArgs = e; resetEvent.Set(); }; resetEvent.WaitOne(TimeSpan.FromSeconds(1)); Assert.True(eventArgs != null); Assert.Equal(versionMessageHeader.Checksum, (IEnumerable <byte>)eventArgs.Header.Checksum); }
private async Task ConnectAndHandshake(Peer peer, bool isIncoming) { // connect await peer.ConnectAsync(); if (!peer.IsConnected) { throw new Exception(); } // setup task to wait for verack var verAckTask = peer.Receiver.WaitForMessage(x => x.Command == "verack", HANDSHAKE_TIMEOUT_MS); // setup task to wait for version var versionTask = peer.Receiver.WaitForMessage(x => x.Command == "version", HANDSHAKE_TIMEOUT_MS); // start listening for messages after tasks have been setup peer.Receiver.Listen(); // send our local version var nodeId = random.NextUInt64(); //TODO should be generated and verified on version message var currentHeight = this.coreDaemon.CurrentChain.Height; await peer.Sender.SendVersion(Messaging.GetExternalIPEndPoint(), peer.RemoteEndPoint, nodeId, (UInt32)currentHeight); // wait for our local version to be acknowledged by the remote peer // wait for remote peer to send their version await Task.WhenAll(verAckTask, versionTask); //TODO shouldn't have to decode again var versionMessage = versionTask.Result; var versionPayload = NodeEncoder.DecodeVersionPayload(versionMessage.Payload.ToArray(), versionMessage.Payload.Length); var remoteAddressWithTime = new NetworkAddressWithTime ( Time: DateTime.UtcNow.ToUnixTime(), NetworkAddress: new NetworkAddress ( Services: versionPayload.LocalAddress.Services, IPv6Address: versionPayload.LocalAddress.IPv6Address, Port: versionPayload.LocalAddress.Port ) ); // acknowledge their version await peer.Sender.SendVersionAcknowledge(); if (isIncoming) { Interlocked.Increment(ref this.incomingCount); } this.pendingPeers.TryRemove(peer); this.connectedPeers.TryAdd(peer); peer.OnDisconnect += DisconnectPeer; RaisePeerConnected(peer); }
public async void ConnectAsync_WithMockNetworkClient_ConnectsAndSendsVersionMessage() { var versionMessage = new MsgVersion() { ProtocolVersion = 1 }; var versionMessageHeader = new MessageHeader(_currencyNet, MsgCommand.Version, versionMessage.Encode()); var expected = versionMessageHeader.Encode().Concat(versionMessage.Encode()).ToArray(); var subject = new Peer(_networkClientMock.Object, _currencyNet); await subject.ConnectAsync(); _networkClientMock.Verify(m => m.ConnectAsync(), Times.Once); // The data written to the stream should be the entire version message var actualBytesWritten = _writeStream.ToArray(); Assert.Equal(expected.Length, actualBytesWritten.Length); Assert.Equal(actualBytesWritten, (IEnumerable <byte>)expected); }
private async Task ConnectAndHandshake(Peer peer) { peer.OnDisconnect += DisconnectPeer; if (peer.IsIncoming) Interlocked.Increment(ref this.incomingCount); // connect await peer.ConnectAsync(); // notify peer is connected PeerConnected?.Invoke(peer); // setup task to wait for verack var verAckTask = peer.Receiver.WaitForMessage(x => x.Command == "verack", HANDSHAKE_TIMEOUT_MS); // setup task to wait for version var versionTask = peer.Receiver.WaitForMessage(x => x.Command == "version", HANDSHAKE_TIMEOUT_MS); // start listening for messages after tasks have been setup peer.Receiver.Listen(); // send our local version var nodeId = random.NextUInt64(); //TODO should be generated and verified on version message var currentHeight = this.coreDaemon.CurrentChain.Height; await peer.Sender.SendVersion(Messaging.GetExternalIPEndPoint(), peer.RemoteEndPoint, nodeId, (UInt32)currentHeight); // wait for our local version to be acknowledged by the remote peer // wait for remote peer to send their version await Task.WhenAll(verAckTask, versionTask); //TODO shouldn't have to decode again var versionMessage = versionTask.Result; var versionPayload = NetworkEncoder.DecodeVersionPayload(versionMessage.Payload.ToArray(), versionMessage.Payload.Length); var remoteAddressWithTime = new NetworkAddressWithTime ( Time: DateTimeOffset.Now, NetworkAddress: new NetworkAddress ( Services: versionPayload.LocalAddress.Services, IPv6Address: versionPayload.LocalAddress.IPv6Address, Port: versionPayload.LocalAddress.Port ) ); // acknowledge their version await peer.Sender.SendVersionAcknowledge(); }