wasSharpNET – Blame information for rev 22

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);
22 office 28 private readonly ManualResetEventSlim listenStop = new ManualResetEventSlim(false);
20 office 29  
30 public bool Start(List<string> prefixes)
10 office 31 {
20 office 32 HTTPListener = new HttpListener
19 office 33 {
34 AuthenticationSchemes = AuthenticationSchemes
35 };
9 office 36  
10 office 37 // Add all prefixes.
16 office 38 HTTPListener.Prefixes.Clear();
10 office 39 foreach (var prefix in prefixes)
40 {
41 HTTPListener.Prefixes.Add(prefix);
42 }
43  
9 office 44 // Do not bomb if the client disconnects.
45 HTTPListener.IgnoreWriteExceptions = true;
46 HTTPListener.Start();
20 office 47 return ThreadPool.QueueUserWorkItem(Listen, new HTTPServerCallbackState(HTTPListener));
9 office 48 }
49  
22 office 50 public bool Stop(int timeout)
9 office 51 {
20 office 52 stopListen.Set();
22 office 53 return listenStop.Wait(timeout);
9 office 54 }
55  
56 private void Listen(object state)
57 {
20 office 58 HTTPServerCallbackState callbackState = (HTTPServerCallbackState)state;
9 office 59  
60 while (callbackState.Listener.IsListening)
61 {
22 office 62 callbackState.Listener?.BeginGetContext(ContextCallback, callbackState);
20 office 63  
64 if (WaitHandle.WaitAny(new[] { callbackState.ContextRetrieved, stopListen.WaitHandle }) != 1)
65 continue;
66  
22 office 67 try
68 {
69 callbackState.Listener.Stop();
70 callbackState.Listener.Close();
71 }
72 finally
73 {
74 listenStop.Set();
75 }
20 office 76 break;
9 office 77 }
78 }
79  
80 public abstract void ProcessHTTPContext(HttpListenerContext context);
81  
82 private void ContextCallback(IAsyncResult ar)
83 {
11 office 84 var callbackState = (HTTPServerCallbackState)ar.AsyncState;
20 office 85 HttpListenerContext httpContext;
9 office 86  
87 Interlocked.Increment(ref processedRequests);
88 Interlocked.Increment(ref activeRequests);
89  
90 try
91 {
92 httpContext = callbackState.Listener.EndGetContext(ar);
93 }
94 catch (Exception)
95 {
96 Interlocked.Decrement(ref activeRequests);
97 return;
98 }
99 finally
100 {
101 callbackState.ContextRetrieved.Set();
102 }
103  
104 try
105 {
106 ProcessHTTPContext(httpContext);
107 }
108 finally
109 {
110 Interlocked.Decrement(ref activeRequests);
111 }
112 }
113  
15 office 114 public void Dispose()
115 {
22 office 116 stopListen.Set();
15 office 117 }
118  
9 office 119 private class HTTPServerCallbackState
120 {
121 public HTTPServerCallbackState(HttpListener listener)
122 {
123 if (listener == null)
20 office 124 throw new ArgumentNullException(nameof(listener));
9 office 125 Listener = listener;
126 ContextRetrieved = new AutoResetEvent(false);
127 }
128  
129 public HttpListener Listener { get; }
130  
131 public AutoResetEvent ContextRetrieved { get; }
132 }
133 }
11 office 134 }