private async Task AcceptConnections(CancellationToken token) { try { #region Start-Listeners foreach (Uri uri in _Settings.Uris) { _HttpListener.Prefixes.Add(uri.ToString()); } _HttpListener.Start(); #endregion #region Process-Requests while (_HttpListener.IsListening) { if (_RequestCount >= _Settings.IO.MaxRequests) { await Task.Delay(100, token).ConfigureAwait(false); continue; } HttpListenerContext listenerCtx = await _HttpListener.GetContextAsync().ConfigureAwait(false); Interlocked.Increment(ref _RequestCount); HttpContext ctx = null; Task unawaited = Task.Run(async() => { DateTime startTime = DateTime.Now; try { #region Build-Context Events.HandleConnectionReceived(this, new ConnectionEventArgs( listenerCtx.Request.RemoteEndPoint.Address.ToString(), listenerCtx.Request.RemoteEndPoint.Port)); ctx = new HttpContext(listenerCtx, _Settings, Events); Events.HandleRequestReceived(this, new RequestEventArgs(ctx)); if (_Settings.Debug.Requests) { Events.Logger?.Invoke( _Header + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } Statistics.IncrementRequestCounter(ctx.Request.Method); Statistics.IncrementReceivedPayloadBytes(ctx.Request.ContentLength); #endregion #region Check-Access-Control if (!_Settings.AccessControl.Permit(ctx.Request.Source.IpAddress)) { Events.HandleRequestDenied(this, new RequestEventArgs(ctx)); if (_Settings.Debug.AccessControl) { Events.Logger?.Invoke(_Header + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " denied due to access control"); } listenerCtx.Response.Close(); return; } #endregion #region Process-Preflight-Requests if (ctx.Request.Method == HttpMethod.OPTIONS) { if (_Routes.Preflight != null) { if (_Settings.Debug.Routing) { Events.Logger?.Invoke( _Header + "preflight route for " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } await _Routes.Preflight(ctx).ConfigureAwait(false); return; } } #endregion #region Pre-Routing-Handler bool terminate = false; if (_Routes.PreRouting != null) { terminate = await _Routes.PreRouting(ctx).ConfigureAwait(false); if (terminate) { if (_Settings.Debug.Routing) { Events.Logger?.Invoke( _Header + "prerouting terminated connection for " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } return; } } #endregion #region Content-Routes if (ctx.Request.Method == HttpMethod.GET || ctx.Request.Method == HttpMethod.HEAD) { if (_Routes.Content.Exists(ctx.Request.Url.RawWithoutQuery)) { if (_Settings.Debug.Routing) { Events.Logger?.Invoke( _Header + "content route for " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } await _Routes.ContentHandler.Process(ctx, token).ConfigureAwait(false); return; } } #endregion #region Static-Routes Func <HttpContext, Task> handler = _Routes.Static.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery); if (handler != null) { if (_Settings.Debug.Routing) { Events.Logger?.Invoke( _Header + "static route for " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } await handler(ctx).ConfigureAwait(false); return; } #endregion #region Dynamic-Routes handler = _Routes.Dynamic.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery); if (handler != null) { if (_Settings.Debug.Routing) { Events.Logger?.Invoke( _Header + "dynamic route for " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } await handler(ctx).ConfigureAwait(false); return; } #endregion #region Default-Route if (_Routes.Default != null) { if (_Settings.Debug.Routing) { Events.Logger?.Invoke( _Header + "default route for " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } await _Routes.Default(ctx).ConfigureAwait(false); return; } else { if (_Settings.Debug.Routing) { Events.Logger?.Invoke( _Header + "default route not found for " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " " + ctx.Request.Method.ToString() + " " + ctx.Request.Url.RawWithoutQuery); } ctx.Response.StatusCode = 404; ctx.Response.ContentType = Pages.Default404Page.ContentType; await ctx.Response.Send(Pages.Default404Page.Content).ConfigureAwait(false); return; } #endregion } catch (Exception eInner) { ctx.Response.StatusCode = 500; ctx.Response.ContentType = Pages.Default500Page.ContentType; await ctx.Response.Send(Pages.Default500Page.Content).ConfigureAwait(false); Events.HandleExceptionEncountered(this, new ExceptionEventArgs(ctx, eInner)); } finally { Interlocked.Decrement(ref _RequestCount); if (ctx != null && ctx.Response != null && ctx.Response.ResponseSent) { Events.HandleResponseSent(this, new ResponseEventArgs(ctx, TotalMsFrom(startTime))); Statistics.IncrementSentPayloadBytes(ctx.Response.ContentLength); } } }, token); } #endregion } catch (TaskCanceledException) { } catch (OperationCanceledException) { } catch (Exception e) { Events.HandleExceptionEncountered(this, new ExceptionEventArgs(null, e)); } finally { Events.HandleServerStopped(this, EventArgs.Empty); } }