public void BeginListen() { this.logger.LogTrace("()"); this.Disconnected = new ManualResetEvent(false); this.Cancel = new CancellationTokenSource(); new Thread(() => { this.logger.LogTrace("()"); SentMessage processing = null; Exception unhandledException = null; try { using (var completedEvent = new ManualResetEvent(false)) { using (var socketEventManager = NodeSocketEventManager.Create(completedEvent)) { socketEventManager.SocketEvent.SocketFlags = SocketFlags.None; foreach (SentMessage kv in this.Messages.GetConsumingEnumerable(this.Cancel.Token)) { processing = kv; Payload payload = kv.Payload; var message = new Message { Magic = this.Peer.Network.Magic, Payload = payload }; this.logger.LogTrace("Sending message: '{0}'", message); using (MemoryStream ms = new MemoryStream()) { message.ReadWrite(new BitcoinStream(ms, true) { ProtocolVersion = this.Peer.Version, TransactionOptions = this.Peer.SupportedTransactionOptions }); byte[] bytes = ms.ToArrayEfficient(); socketEventManager.SocketEvent.SetBuffer(bytes, 0, bytes.Length); this.Peer.Counter.AddWritten(bytes.Length); } completedEvent.Reset(); if (!this.Socket.SendAsync(socketEventManager.SocketEvent)) { Utils.SafeSet(completedEvent); } WaitHandle.WaitAny(new WaitHandle[] { completedEvent, this.Cancel.Token.WaitHandle }, -1); if (!this.Cancel.Token.IsCancellationRequested) { if (socketEventManager.SocketEvent.SocketError != SocketError.Success) { throw new SocketException((int)socketEventManager.SocketEvent.SocketError); } processing.Completion.SetResult(true); processing = null; } } } } } catch (OperationCanceledException) { this.logger.LogTrace("Sending cancelled."); } catch (Exception ex) { this.logger.LogTrace("Exception occurred: '{0}'", ex.ToString()); unhandledException = ex; } if (processing != null) { this.Messages.Add(processing); } foreach (SentMessage pending in this.Messages) { this.logger.LogTrace("Connection terminated before message '{0}' could be sent.", pending.Payload?.Command); pending.Completion.SetException(new OperationCanceledException("The peer has been disconnected")); } this.Messages = new BlockingCollection <SentMessage>(new ConcurrentQueue <SentMessage>()); this.logger.LogDebug("Terminating sending thread."); this.EndListen(unhandledException); this.logger.LogTrace("(-)"); }).Start(); new Thread(() => { this.logger.LogTrace("()"); this.ListenerThreadId = Thread.CurrentThread.ManagedThreadId; this.logger.LogTrace("Start listenting."); Exception unhandledException = null; byte[] buffer = this.Peer.ReuseBuffer ? new byte[1024 * 1024] : null; try { using (var stream = new NetworkStream(this.Socket, false)) { while (!this.Cancel.Token.IsCancellationRequested) { PerformanceCounter counter; Message message = Message.ReadNext(stream, this.Peer.Network, this.Peer.Version, this.Cancel.Token, buffer, out counter); this.logger.LogTrace("Receiving message: '{0}'", message); this.Peer.LastSeen = this.dateTimeProvider.GetUtcNow(); this.Peer.Counter.Add(counter); this.Peer.OnMessageReceived(new IncomingMessage() { Message = message, Socket = this.Socket, Length = counter.ReadBytes, NetworkPeer = this.Peer }); } } } catch (OperationCanceledException) { this.logger.LogTrace("Listening cancelled."); } catch (Exception ex) { this.logger.LogTrace("Exception occurred: {0}", ex); unhandledException = ex; } this.logger.LogDebug("Terminating listening thread."); this.EndListen(unhandledException); this.logger.LogTrace("(-)"); }).Start(); this.logger.LogTrace("(-)"); }
/// <summary> /// Starts two threads, one is responsible for receiving incoming messages from the peer /// and the other is responsible for sending node's message, which are waiting in a queue, to the peer. /// </summary> public void BeginListen() { this.logger.LogTrace("()"); this.Disconnected = new ManualResetEvent(false); this.Cancel = new CancellationTokenSource(); // This is sending thread. new Thread(() => { this.logger.LogTrace("()"); SentMessage processing = null; Exception unhandledException = null; try { foreach (SentMessage messageToSend in this.Messages.GetConsumingEnumerable(this.Cancel.Token)) { processing = messageToSend; Payload payload = messageToSend.Payload; var message = new Message { Magic = this.Peer.Network.Magic, Payload = payload }; this.logger.LogTrace("Sending message: '{0}'", message); using (MemoryStream ms = new MemoryStream()) { message.ReadWrite(new BitcoinStream(ms, true) { ProtocolVersion = this.Peer.Version, TransactionOptions = this.Peer.SupportedTransactionOptions }); byte[] bytes = ms.ToArray(); this.Client.SendAsync(bytes, this.Cancel.Token).GetAwaiter().GetResult(); this.Peer.Counter.AddWritten(bytes.Length); processing.Completion.SetResult(true); processing = null; } } } catch (OperationCanceledException) { this.logger.LogTrace("Sending cancelled."); } catch (Exception ex) { this.logger.LogTrace("Exception occurred: '{0}'", ex.ToString()); unhandledException = ex; } if (processing != null) { this.Messages.Add(processing); } foreach (SentMessage pending in this.Messages) { this.logger.LogTrace("Connection terminated before message '{0}' could be sent.", pending.Payload?.Command); pending.Completion.SetException(new OperationCanceledException("The peer has been disconnected")); } this.Messages = new BlockingCollection <SentMessage>(new ConcurrentQueue <SentMessage>()); this.logger.LogDebug("Terminating sending thread."); this.EndListen(unhandledException); this.logger.LogTrace("(-)"); }).Start(); // This is receiving thread. new Thread(() => { this.logger.LogTrace("()"); this.logger.LogTrace("Start listenting."); Exception unhandledException = null; byte[] buffer = new byte[1024 * 1024]; try { while (!this.Cancel.Token.IsCancellationRequested) { PerformanceCounter counter; Message message = Message.ReadNext(this.Client.Stream, this.Peer.Network, this.Peer.Version, this.Cancel.Token, buffer, out counter); this.logger.LogTrace("Receiving message: '{0}'", message); this.Peer.LastSeen = this.dateTimeProvider.GetUtcNow(); this.Peer.Counter.Add(counter); this.Peer.OnMessageReceived(new IncomingMessage() { Message = message, Client = this.Client, Length = counter.ReadBytes, NetworkPeer = this.Peer }); } } catch (OperationCanceledException) { this.logger.LogTrace("Listening cancelled."); } catch (Exception ex) { this.logger.LogTrace("Exception occurred: {0}", ex); unhandledException = ex; } this.logger.LogDebug("Terminating listening thread."); this.EndListen(unhandledException); this.logger.LogTrace("(-)"); }).Start(); this.logger.LogTrace("(-)"); }