wasSharpNET – Blame information for rev 20
?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 | |
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 | } |