/// <summary> /// Listens to incoming connections and calls the spawner method for each new connection /// </summary> /// <returns>Awaitable task.</returns> /// <param name="addr">The address to listen to.</param> /// <param name="usessl">A flag indicating if the socket listens for SSL requests</param> /// <param name="stoptoken">The stoptoken.</param> /// <param name="config">The server configuration</param> /// <param name="spawner">The method handling the new connection.</param> private static async Task ListenToSocketInternalAsync(IPEndPoint addr, bool usessl, CancellationToken stoptoken, ServerConfig config, Action <TcpClient, EndPoint, string, RunnerControl> spawner) { var rc = new RunnerControl(stoptoken, usessl, config); var listener = new TcpListener(addr); listener.Start(config.SocketBacklog); var taskid = SetLoggingSocketHandlerID(); while (!stoptoken.IsCancellationRequested) { // Wait if there are too many active config.DebugLogHandler?.Invoke("Waiting for throttle", taskid, null); await rc.ThrottleTask; config.DebugLogHandler?.Invoke("Waiting for socket", taskid, null); var ls = listener.AcceptTcpClientAsync(); if (await Task.WhenAny(rc.StopTask, ls) == ls) { config.DebugLogHandler?.Invoke("Re-waiting for socket", taskid, null); var client = await ls; var newtaskid = SetLoggingTaskHandlerID(); try { int wt, cpt; ThreadPool.GetAvailableThreads(out wt, out cpt); config.DebugLogHandler?.Invoke(string.Format("Threadpool says {0}, {1}", wt, cpt), taskid, newtaskid); config.DebugLogHandler?.Invoke(string.Format("Spawning runner with id: {0}", newtaskid), taskid, newtaskid); // Read the endpoint here to avoid crashes when invoking the spawner var ep = client.Client.RemoteEndPoint; ThreadPool.QueueUserWorkItem(x => spawner(client, ep, newtaskid, rc)); } catch (Exception ex) { config.DebugLogHandler?.Invoke("Failed to listen to socket", taskid, ex); } } } config.DebugLogHandler?.Invoke("Stopping", taskid, null); listener.Stop(); rc.Stop(taskid); config.DebugLogHandler?.Invoke("Socket stopped, waiting for workers ...", taskid, null); await rc.FinishedTask; config.DebugLogHandler?.Invoke("Stopped", taskid, null); }
/// <summary> /// Listens to incoming connections and calls the spawner method for each new connection /// </summary> /// <returns>Awaitable task.</returns> /// <param name="acceptAsync">Method that returns an accepted socket.</param> /// <param name="usessl">A flag indicating if the socket listens for SSL requests</param> /// <param name="stoptoken">The stoptoken.</param> /// <param name="config">The server configuration</param> /// <param name="spawner">The method handling the new connection.</param> private static async Task ListenToSocketInternalAsync(Func <CancellationToken, Task <KeyValuePair <long, EndPoint> > > acceptAsync, bool usessl, CancellationToken stoptoken, ServerConfig config, Action <long, EndPoint, string, RunnerControl> spawner) { if (acceptAsync == null) { throw new ArgumentNullException(nameof(acceptAsync)); } var rc = new RunnerControl(stoptoken, usessl, config); var taskid = SetLoggingSocketHandlerID(); while (!stoptoken.IsCancellationRequested) { // Wait if there are too many active config.DebugLogHandler?.Invoke("Waiting for throttle", taskid, null); await rc.ThrottleTask; config.DebugLogHandler?.Invoke("Waiting for socket", taskid, null); var ls = acceptAsync(stoptoken); if (await Task.WhenAny(rc.StopTask, ls) == ls) { config.DebugLogHandler?.Invoke("Re-waiting for socket", taskid, null); var client = await ls; var newtaskid = SetLoggingTaskHandlerID(); try { int wt, cpt; ThreadPool.GetAvailableThreads(out wt, out cpt); config.DebugLogHandler?.Invoke(string.Format("Threadpool says {0}, {1}", wt, cpt), taskid, newtaskid); config.DebugLogHandler?.Invoke(string.Format("Spawning runner with id: {0}", newtaskid), taskid, newtaskid); ThreadPool.QueueUserWorkItem(x => spawner(client.Key, client.Value, newtaskid, rc)); } catch (Exception ex) { config.DebugLogHandler?.Invoke("Failed to listen to socket", taskid, ex); } } } config.DebugLogHandler?.Invoke("Stopping", taskid, null); rc.Stop(taskid); config.DebugLogHandler?.Invoke("Socket stopped, waiting for workers ...", taskid, null); await rc.FinishedTask; config.DebugLogHandler?.Invoke("Stopped", taskid, null); }