wasSharpNET – Blame information for rev 16
?pathlinks?
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 | |
15 | office | 18 | private HttpListener HTTPListener = new HttpListener() |
10 | office | 19 | { |
20 | AuthenticationSchemes = AuthenticationSchemes.None |
||
21 | }; |
||
11 | office | 22 | |
9 | office | 23 | private int processedRequests; |
24 | |||
10 | office | 25 | public AuthenticationSchemes AuthenticationSchemes |
9 | office | 26 | { |
10 | office | 27 | get |
9 | office | 28 | { |
10 | office | 29 | return HTTPListener.AuthenticationSchemes; |
9 | office | 30 | } |
10 | office | 31 | set |
32 | { |
||
33 | HTTPListener.AuthenticationSchemes = value; |
||
34 | } |
||
35 | } |
||
9 | office | 36 | |
10 | office | 37 | public bool IsRunning => HTTPListener.IsListening; |
9 | office | 38 | |
10 | office | 39 | public bool Start(IEnumerable<string> prefixes) |
40 | { |
||
9 | office | 41 | // Do not start the HTTP server if it is already running. |
42 | if (HTTPListener.IsListening) |
||
43 | return false; |
||
44 | |||
10 | office | 45 | // Add all prefixes. |
16 | office | 46 | HTTPListener.Prefixes.Clear(); |
10 | office | 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 | { |
||
16 | office | 61 | HTTPListener.Stop(); |
10 | office | 62 | return true; |
9 | office | 63 | } |
64 | |||
65 | private void Listen(object state) |
||
66 | { |
||
11 | office | 67 | var callbackState = (HTTPServerCallbackState)state; |
9 | office | 68 | |
69 | while (callbackState.Listener.IsListening) |
||
70 | { |
||
71 | callbackState.Listener.BeginGetContext(ContextCallback, callbackState); |
||
16 | office | 72 | callbackState.ContextRetrieved.WaitOne(); |
9 | office | 73 | } |
74 | } |
||
75 | |||
76 | public abstract void ProcessHTTPContext(HttpListenerContext context); |
||
77 | |||
78 | private void ContextCallback(IAsyncResult ar) |
||
79 | { |
||
11 | office | 80 | var callbackState = (HTTPServerCallbackState)ar.AsyncState; |
9 | office | 81 | HttpListenerContext httpContext = null; |
82 | |||
83 | Interlocked.Increment(ref processedRequests); |
||
84 | Interlocked.Increment(ref activeRequests); |
||
85 | |||
86 | try |
||
87 | { |
||
88 | httpContext = callbackState.Listener.EndGetContext(ar); |
||
89 | } |
||
90 | catch (Exception) |
||
91 | { |
||
92 | Interlocked.Decrement(ref activeRequests); |
||
93 | return; |
||
94 | } |
||
95 | finally |
||
96 | { |
||
97 | callbackState.ContextRetrieved.Set(); |
||
98 | } |
||
99 | |||
100 | if (httpContext == null) |
||
101 | return; |
||
102 | |||
103 | try |
||
104 | { |
||
105 | ProcessHTTPContext(httpContext); |
||
106 | } |
||
107 | finally |
||
108 | { |
||
109 | Interlocked.Decrement(ref activeRequests); |
||
110 | } |
||
111 | } |
||
112 | |||
15 | office | 113 | public void Dispose() |
114 | { |
||
115 | Stop(); |
||
116 | HTTPListener = null; |
||
117 | } |
||
118 | |||
9 | office | 119 | private class HTTPServerCallbackState |
120 | { |
||
121 | public HTTPServerCallbackState(HttpListener listener) |
||
122 | { |
||
123 | if (listener == null) |
||
124 | throw new ArgumentNullException("listener"); |
||
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 | } |