wasSharpNET – Blame information for rev 10

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