Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
        }