wasSharpNET – Blame information for rev 20

Subversion Repositories:
Rev:
Rev Author Line No. Line
9 office 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. //
5 ///////////////////////////////////////////////////////////////////////////
6  
7 using System;
8 using System.Collections.Generic;
9 using System.Net;
10 using System.Threading;
11  
12 namespace wasSharpNET.Network.HTTP
13 {
15 office 14 public abstract class HTTPServer : IDisposable
9 office 15 {
16 private int activeRequests;
11 office 17  
20 office 18 private HttpListener HTTPListener;
11 office 19  
9 office 20 private int processedRequests;
21  
19 office 22 public AuthenticationSchemes AuthenticationSchemes { get; set; } =
23 AuthenticationSchemes.None;
9 office 24  
19 office 25 public bool IsRunning => HTTPListener != null && HTTPListener.IsListening;
9 office 26  
20 office 27 private readonly ManualResetEventSlim stopListen = new ManualResetEventSlim(false);
28  
29 public bool Start(List<string> prefixes)
10 office 30 {
20 office 31 HTTPListener = new HttpListener
19 office 32 {
33 AuthenticationSchemes = AuthenticationSchemes
34 };
9 office 35  
10 office 36 // Add all prefixes.
16 office 37 HTTPListener.Prefixes.Clear();
10 office 38 foreach (var prefix in prefixes)
39 {
40 HTTPListener.Prefixes.Add(prefix);
41 }
42  
9 office 43 // Do not bomb if the client disconnects.
44 HTTPListener.IgnoreWriteExceptions = true;
45 HTTPListener.Start();
20 office 46 return ThreadPool.QueueUserWorkItem(Listen, new HTTPServerCallbackState(HTTPListener));
9 office 47 }
48  
19 office 49 public void Stop()
9 office 50 {
20 office 51 stopListen.Set();
9 office 52 }
53  
54 private void Listen(object state)
55 {
20 office 56 HTTPServerCallbackState callbackState = (HTTPServerCallbackState)state;
9 office 57  
58 while (callbackState.Listener.IsListening)
59 {
60 callbackState.Listener.BeginGetContext(ContextCallback, callbackState);
20 office 61  
62 if (WaitHandle.WaitAny(new[] { callbackState.ContextRetrieved, stopListen.WaitHandle }) != 1)
63 continue;
64  
65 callbackState.Listener.Stop();
66 break;
9 office 67 }
68 }
69  
70 public abstract void ProcessHTTPContext(HttpListenerContext context);
71  
72 private void ContextCallback(IAsyncResult ar)
73 {
11 office 74 var callbackState = (HTTPServerCallbackState)ar.AsyncState;
20 office 75 HttpListenerContext httpContext;
9 office 76  
77 Interlocked.Increment(ref processedRequests);
78 Interlocked.Increment(ref activeRequests);
79  
80 try
81 {
82 httpContext = callbackState.Listener.EndGetContext(ar);
83 }
84 catch (Exception)
85 {
86 Interlocked.Decrement(ref activeRequests);
87 return;
88 }
89 finally
90 {
91 callbackState.ContextRetrieved.Set();
92 }
93  
94 try
95 {
96 ProcessHTTPContext(httpContext);
97 }
98 finally
99 {
100 Interlocked.Decrement(ref activeRequests);
101 }
102 }
103  
15 office 104 public void Dispose()
105 {
106 Stop();
107 }
108  
9 office 109 private class HTTPServerCallbackState
110 {
111 public HTTPServerCallbackState(HttpListener listener)
112 {
113 if (listener == null)
20 office 114 throw new ArgumentNullException(nameof(listener));
9 office 115 Listener = listener;
116 ContextRetrieved = new AutoResetEvent(false);
117 }
118  
119 public HttpListener Listener { get; }
120  
121 public AutoResetEvent ContextRetrieved { get; }
122 }
123 }
11 office 124 }