<commit_before>﻿using System;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
using log4net;

namespace Merlion.Server.Web
{
	sealed class HttpServer
	{
		static readonly ILog log = LogManager.GetLogger(typeof(HttpServer));

		IPEndPoint endpoint;
		bool listening = false;
		TcpListener tcp;
		Thread listenThread;
		readonly ConcurrentQueue<HttpServerContext> queue = 
			new ConcurrentQueue<HttpServerContext>();
		readonly EventWaitHandle queueEvent = 
			new EventWaitHandle (false, EventResetMode.AutoReset);

		public HttpServer (IPEndPoint endpoint)
		{
			this.endpoint = endpoint;
		}

		public void Start()
		{
			if (listening)
				return;

			// Empty the queue
			HttpServerContext ctx;
			while (queue.TryDequeue(out ctx)) { }

			tcp = new TcpListener (endpoint);
			tcp.Start ();

			listenThread = new Thread (Listen);
			listenThread.Name = "HttpSever Listener";
			listenThread.Start ();
			listening = true;
		}

		public void Stop()
		{
			if (!listening)
				return;

			tcp.Stop ();
			tcp = null;
			listenThread.Join ();
			listenThread = null;
			listening = false;
		}

		void Listen()
		{
			while (true) {
				try {
					var client = tcp.AcceptTcpClient ();
					client.ReceiveTimeout = 5000;
					client.SendTimeout = 5000;

					var ctx = new HttpServerContext (client);
					new Task (() => {
						try {
							ctx.Request.EnsurePopulated();
							queue.Enqueue(ctx);
							queueEvent.Set();
						} catch (HttpRequestHeaderException ex) {
							ctx.Response.StatusCode = ex.Code;
							try {
								ctx.Dispose();
							} catch (Exception ex2) {
								log.ErrorFormat("Unknown exception while returning error. Ignoring.", ex2);
							}
						} catch (Exception ex) {
							ctx.Response.StatusCode = 500;
							log.ErrorFormat("Unknown exception while handling request.", ex);
							try {
								ctx.Dispose();
							} catch (Exception ex2) {
								log.ErrorFormat("Unknown exception while returning error. Ignoring.", ex2);
							}
						}
					}).Start ();
				} catch (SocketException) {
					// Aborted.
					return;
				}
			}
		}

		public HttpServerContext GetContext()
		{
			HttpServerContext context;
			while (!queue.TryDequeue(out context)) {
				if (!listening) {
					throw new InvalidOperationException ("Not listening.");
				}
				queueEvent.WaitOne ();
			}
			return context;<commit_msg>Http server now reports exceptions<commit_after>﻿using System;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
using log4net;

namespace Merlion.Server.Web
{
	sealed class HttpServer
	{
		static readonly ILog log = LogManager.GetLogger(typeof(HttpServer));

		IPEndPoint endpoint;
		bool listening = false;
		TcpListener tcp;
		Thread listenThread;
		readonly ConcurrentQueue<HttpServerContext> queue = 
			new ConcurrentQueue<HttpServerContext>();
		readonly EventWaitHandle queueEvent = 
			new EventWaitHandle (false, EventResetMode.AutoReset);

		public HttpServer (IPEndPoint endpoint)
		{
			this.endpoint = endpoint;
		}

		public void Start()
		{
			if (listening)
				return;

			// Empty the queue
			HttpServerContext ctx;
			while (queue.TryDequeue(out ctx)) { }

			tcp = new TcpListener (endpoint);
			tcp.Start ();

			listenThread = new Thread (Listen);
			listenThread.Name = "HttpSever Listener";
			listenThread.Start ();
			listening = true;
		}

		public void Stop()
		{
			if (!listening)
				return;

			tcp.Stop ();
			tcp = null;
			listenThread.Join ();
			listenThread = null;
			listening = false;
		}

		void Listen()
		{
			while (true) {
				try {
					var client = tcp.AcceptTcpClient ();
					client.ReceiveTimeout = 5000;
					client.SendTimeout = 5000;

					var ctx = new HttpServerContext (client);
					new Task (() => {
						try {
							ctx.Request.EnsurePopulated();
							queue.Enqueue(ctx);
							queueEvent.Set();
						} catch (HttpRequestHeaderException ex) {
							ctx.Response.StatusCode = ex.Code;
							try {
								ctx.Dispose();
							} catch (Exception ex2) {
								log.Error("Unknown exception while returning error. Ignoring.", ex2);
							}
						} catch (Exception ex) {
							ctx.Response.StatusCode = 500;
							log.Error("Unknown exception while handling request.", ex);
							try {
								ctx.Dispose();
							} catch (Exception ex2) {
								log.Error("Unknown exception while returning error. Ignoring.", ex2);
							}
						}
					}).Start ();
				} catch (SocketException) {
					// Aborted.
					return;
				}
			}
		}

		public HttpServerContext GetContext()
		{
			HttpServerContext context;
			while (!queue.TryDequeue(out context)) {
				if (!listening) {
					throw new InvalidOperationException ("Not listening.");
				}
				queueEvent.WaitOne ();
			}
			return context;
{'fraction_non_alphanumeric': 0.10929177352535016, 'fraction_numerical': 0.006312882225290984, 'mean_word_length': 2.8438210765731613, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3493561', 'n_tokens_mistral': 2044, 'n_tokens_neox': 1480, 'n_words': 375}