wasSharpNET – Blame information for rev 9

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 {
14 public abstract class HTTPServer
15 {
16 private int activeRequests;
17 private readonly HttpListener HTTPListener = new HttpListener();
18 private int processedRequests;
19  
20 private readonly ManualResetEvent stopEvent = new ManualResetEvent(false);
21  
22 public HashSet<string> Prefixes { get; set; } = new HashSet<string>();
23  
24 public AuthenticationSchemes AuthenticationSchemes { get; set; } = AuthenticationSchemes.None;
25  
26 public bool IsRunning => HTTPListener.IsListening;
27  
28 public bool Start()
29 {
30 foreach (var prefix in Prefixes)
31 {
32 if (!HTTPListener.Prefixes.Contains(prefix))
33 HTTPListener.Prefixes.Add(prefix);
34 }
35  
36 // Set up HTTP listener.
37 HTTPListener.AuthenticationSchemes = AuthenticationSchemes;
38  
39 // Do not start the HTTP server if it is already running.
40 if (HTTPListener.IsListening)
41 return false;
42  
43 // Do not bomb if the client disconnects.
44 HTTPListener.IgnoreWriteExceptions = true;
45 HTTPListener.Start();
46 var state = new HTTPServerCallbackState(HTTPListener);
47 ThreadPool.QueueUserWorkItem(Listen, state);
48 return true;
49 }
50  
51 public bool Stop()
52 {
53 return stopEvent.Set();
54 }
55  
56 private void Listen(object state)
57 {
58 var callbackState = (HTTPServerCallbackState) state;
59  
60 while (callbackState.Listener.IsListening)
61 {
62 callbackState.Listener.BeginGetContext(ContextCallback, callbackState);
63 var n = WaitHandle.WaitAny(new WaitHandle[] {callbackState.ContextRetrieved, stopEvent});
64  
65 if (n.Equals(1))
66 {
67 callbackState.Listener.Stop();
68 break;
69 }
70 }
71 }
72  
73 public abstract void ProcessHTTPContext(HttpListenerContext context);
74  
75 private void ContextCallback(IAsyncResult ar)
76 {
77 var callbackState = (HTTPServerCallbackState) ar.AsyncState;
78 HttpListenerContext httpContext = null;
79  
80 Interlocked.Increment(ref processedRequests);
81 Interlocked.Increment(ref activeRequests);
82  
83 try
84 {
85 httpContext = callbackState.Listener.EndGetContext(ar);
86 }
87 catch (Exception)
88 {
89 Interlocked.Decrement(ref activeRequests);
90 return;
91 }
92 finally
93 {
94 callbackState.ContextRetrieved.Set();
95 }
96  
97 if (httpContext == null)
98 return;
99  
100 try
101 {
102 ProcessHTTPContext(httpContext);
103 }
104 finally
105 {
106 Interlocked.Decrement(ref activeRequests);
107 }
108 }
109  
110 private class HTTPServerCallbackState
111 {
112 public HTTPServerCallbackState(HttpListener listener)
113 {
114 if (listener == null)
115 throw new ArgumentNullException("listener");
116 Listener = listener;
117 ContextRetrieved = new AutoResetEvent(false);
118 }
119  
120 public HttpListener Listener { get; }
121  
122 public AutoResetEvent ContextRetrieved { get; }
123 }
124 }
125 }