protected virtual void OnServerExceptionOccured(TcpServerExceptionEventArgs e) { try { this.ServerExceptionOccured?.Invoke(this, e); } catch (Exception ex) { var ue = new ExceptionEventArgs(ex); this.OnUnhandledException(ue); } }
/// <summary> /// Asynchronously starts the server that will run until <paramref name="cancellationToken" /> is cancelled /// </summary> /// <param name="cancellationToken">Cancellation token</param> /// <returns><see cref="Task" /></returns> public virtual async Task StartAsync(CancellationToken cancellationToken) { var tcpListener = this.CreateTcpListener(); this.Config.ConfigureTcpListenerCallback?.Invoke(tcpListener); try { tcpListener.Start(); } catch (Exception ex) { var e = new TcpServerExceptionEventArgs(ex); this.OnServerExceptionOccured(e); return; } try { await Task.WhenAll( this.ListenAsync(tcpListener, cancellationToken), Task.Run(() => this.OnServerStarted(new TcpServerStartedEventArgs() { ServerAddress = this.Config.IPAddress, ServerPort = this.Config.Port }))) .ConfigureAwait(false); } catch (Exception ex) { var e = new TcpServerExceptionEventArgs(ex); this.OnServerExceptionOccured(e); } finally { try { tcpListener.Stop(); } catch (Exception ex) { var e = new TcpServerExceptionEventArgs(ex); this.OnServerExceptionOccured(e); } this.OnServerStopped(new TcpServerStoppedEventArgs()); } }
// exploiting "async void" simplifies everything protected virtual async void HandleNewTcpClientAsync(TcpClient tcpClient, CancellationToken token) { try { await this.HandleNewTcpClientTask(tcpClient, token).ConfigureAwait(false); } catch (Exception ex) { var se = new TcpServerExceptionEventArgs(ex); this.OnServerExceptionOccured(se); } }
protected virtual async Task HandleNewTcpClientTask(TcpClient tcpClient, CancellationToken token) { using (tcpClient) { var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(token); // remote tcp peer controls linkedCts lifetime var sendQueue = this.CreateSendQueueActionBlock(linkedCts.Token); RemoteTcpPeer remoteTcpPeer; SslStream sslStream = null; try { if (this.Config.UseSsl && this.Config.X509Certificate != null) { sslStream = this.CreateSslStream(tcpClient); await this.AuthenticateSslStream(tcpClient, sslStream, linkedCts.Token) .ConfigureAwait(false); remoteTcpPeer = this.CreateRemoteTcpPeer(tcpClient, sslStream, sendQueue, linkedCts); } else { remoteTcpPeer = this.CreateRemoteTcpPeer(tcpClient, sendQueue, linkedCts); } } catch (AuthenticationException ex) { var e = new TcpServerExceptionEventArgs(ex); this.OnServerExceptionOccured(e); sendQueue.Complete(); sslStream?.Dispose(); linkedCts.Dispose(); return; } catch (Exception ex) { var e = new TcpServerExceptionEventArgs(ex); this.OnServerExceptionOccured(e); sendQueue.Complete(); linkedCts.Dispose(); return; } using (remoteTcpPeer) { this.AddRemoteTcpPeerToConnectedList(remoteTcpPeer); var connectionEstablishedEventArgs = new ConnectionEstablishedEventArgs(remoteTcpPeer); this.OnConnectionEstablished(connectionEstablishedEventArgs); await this.HandleRemotePeerAsync(remoteTcpPeer, linkedCts.Token).ConfigureAwait(false); sendQueue.Complete(); sslStream?.Dispose(); } } }