Winify – Diff between revs 48 and 50

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 48 Rev 50
1 using System; 1 using System;
2 using System.Drawing; 2 using System.Drawing;
3 using System.IO; 3 using System.IO;
-   4 using System.Net;
4 using System.Net.Http; 5 using System.Net.Http;
5 using System.Net.Http.Headers; 6 using System.Net.Http.Headers;
6 using System.Net.Security; 7 using System.Net.Security;
-   8 using System.Security.Authentication;
7 using System.Security.Cryptography.X509Certificates; 9 using System.Security.Cryptography.X509Certificates;
8 using System.Text; 10 using System.Text;
9 using System.Threading; 11 using System.Threading;
10 using System.Threading.Tasks; 12 using System.Threading.Tasks;
11 using Newtonsoft.Json; 13 using Newtonsoft.Json;
12 using Serilog; 14 using Serilog;
13 using Servers; 15 using Servers;
14 using WebSocketSharp; 16 using WebSocketSharp;
-   17 using WebSocketSharp.Net;
-   18 using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
15 using Configuration = Configuration.Configuration; 19 using Configuration = Configuration.Configuration;
16 using ErrorEventArgs = WebSocketSharp.ErrorEventArgs; 20 using ErrorEventArgs = WebSocketSharp.ErrorEventArgs;
-   21 using NetworkCredential = System.Net.NetworkCredential;
17   22  
18 namespace Winify.Gotify 23 namespace Winify.Gotify
19 { 24 {
20 public class GotifyConnection : IDisposable 25 public class GotifyConnection : IDisposable
21 { 26 {
22 #region Public Events & Delegates 27 #region Public Events & Delegates
23   28  
24 public event EventHandler<GotifyNotificationEventArgs> GotifyNotification; 29 public event EventHandler<GotifyNotificationEventArgs> GotifyNotification;
25   30  
26 #endregion 31 #endregion
27   32  
28 #region Private Delegates, Events, Enums, Properties, Indexers and Fields 33 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
29   34  
30 private readonly Server _server; 35 private readonly Server _server;
31   36  
32 private CancellationToken _cancellationToken; 37 private CancellationToken _cancellationToken;
33   38  
34 private CancellationTokenSource _cancellationTokenSource; 39 private CancellationTokenSource _cancellationTokenSource;
35   40  
36 private Task _runTask; 41 private Task _runTask;
37   42  
38 private HttpClient _httpClient; 43 private HttpClient _httpClient;
39   44  
40 private readonly Uri _webSocketsUri; 45 private readonly Uri _webSocketsUri;
41   46  
42 private readonly Uri _httpUri; 47 private readonly Uri _httpUri;
43 private WebSocket _webSocketSharp; 48 private WebSocket _webSocketSharp;
44 private readonly global::Configuration.Configuration _configuration; 49 private readonly global::Configuration.Configuration _configuration;
45   50  
46 #endregion 51 #endregion
47   52  
48 #region Constructors, Destructors and Finalizers 53 #region Constructors, Destructors and Finalizers
49   54  
50 private GotifyConnection() 55 private GotifyConnection()
51 { 56 {
52   57  
53 } 58 }
54   59  
55 public GotifyConnection(Server server, global::Configuration.Configuration configuration) : this() 60 public GotifyConnection(Server server, global::Configuration.Configuration configuration) : this()
56 { 61 {
57 _server = server; 62 _server = server;
58 _configuration = configuration; 63 _configuration = configuration;
59   64  
-   65 var httpClientHandler = new HttpClientHandler()
-   66 {
-   67 SslProtocols = SslProtocols.Tls12
-   68 };
60 var httpClientHandler = new HttpClientHandler(); 69  
61 _httpClient = new HttpClient(httpClientHandler); 70 _httpClient = new HttpClient(httpClientHandler);
62 if (_configuration.IgnoreSelfSignedCertificates) 71 if (_configuration.IgnoreSelfSignedCertificates)
63 { 72 {
64 httpClientHandler.ServerCertificateCustomValidationCallback = 73 httpClientHandler.ServerCertificateCustomValidationCallback =
65 (httpRequestMessage, cert, cetChain, policyErrors) => true; 74 (httpRequestMessage, cert, cetChain, policyErrors) => true;
66 } 75 }
-   76  
-   77 if (_configuration.Proxy.Enable)
-   78 {
-   79 httpClientHandler.Proxy = new WebProxy(_configuration.Proxy.Url, false, new string[] { },
-   80 new NetworkCredential(_configuration.Proxy.Username, _configuration.Proxy.Password));
-   81 }
67   82  
68 _httpClient = new HttpClient(httpClientHandler); 83 _httpClient = new HttpClient(httpClientHandler);
69 if (!string.IsNullOrEmpty(_server.Username) && !string.IsNullOrEmpty(_server.Password)) 84 if (!string.IsNullOrEmpty(_server.Username) && !string.IsNullOrEmpty(_server.Password))
70 { 85 {
71 _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", 86 _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
72 Convert.ToBase64String(Encoding.Default.GetBytes($"{_server.Username}:{_server.Password}"))); 87 Convert.ToBase64String(Encoding.Default.GetBytes($"{_server.Username}:{_server.Password}")));
73 } 88 }
74   89  
75 if (!Uri.TryCreate(_server.Url, UriKind.Absolute, out _httpUri)) 90 if (!Uri.TryCreate(_server.Url, UriKind.Absolute, out _httpUri))
76 { 91 {
77 Log.Error($"No HTTP URL could be built out of the supplied server URI {_server.Url}."); 92 Log.Error($"No HTTP URL could be built out of the supplied server URI {_server.Url}.");
78 return; 93 return;
79 } 94 }
80   95  
81 // Build the web sockets URI. 96 // Build the web sockets URI.
82 var webSocketsUriBuilder = new UriBuilder(_httpUri); 97 var webSocketsUriBuilder = new UriBuilder(_httpUri);
83 switch (webSocketsUriBuilder.Scheme.ToUpperInvariant()) 98 switch (webSocketsUriBuilder.Scheme.ToUpperInvariant())
84 { 99 {
85 case "HTTP": 100 case "HTTP":
86 webSocketsUriBuilder.Scheme = "ws"; 101 webSocketsUriBuilder.Scheme = "ws";
87 break; 102 break;
88 case "HTTPS": 103 case "HTTPS":
89 webSocketsUriBuilder.Scheme = "wss"; 104 webSocketsUriBuilder.Scheme = "wss";
90 break; 105 break;
91 } 106 }
92   107  
93 try 108 try
94 { 109 {
95 webSocketsUriBuilder.Path = Path.Combine(webSocketsUriBuilder.Path, "stream"); 110 webSocketsUriBuilder.Path = Path.Combine(webSocketsUriBuilder.Path, "stream");
96 } 111 }
97 catch (ArgumentException exception) 112 catch (ArgumentException exception)
98 { 113 {
99 Log.Error($"No WebSockets URL could be built from the provided URL {_server.Url} due to {exception.Message}."); 114 Log.Error($"No WebSockets URL could be built from the provided URL {_server.Url} due to {exception.Message}.");
100 } 115 }
101   116  
102 _webSocketsUri = webSocketsUriBuilder.Uri; 117 _webSocketsUri = webSocketsUriBuilder.Uri;
103 } 118 }
104   119  
105 public void Dispose() 120 public void Dispose()
106 { 121 {
107 if (_cancellationTokenSource != null) 122 if (_cancellationTokenSource != null)
108 { 123 {
109 _cancellationTokenSource.Dispose(); 124 _cancellationTokenSource.Dispose();
110 _cancellationTokenSource = null; 125 _cancellationTokenSource = null;
111 } 126 }
112   127  
113 if (_webSocketSharp != null) 128 if (_webSocketSharp != null)
114 { 129 {
115 _webSocketSharp.Close(); 130 _webSocketSharp.Close();
116 _webSocketSharp = null; 131 _webSocketSharp = null;
117 } 132 }
118   133  
119 if (_httpClient != null) 134 if (_httpClient != null)
120 { 135 {
121 _httpClient.Dispose(); 136 _httpClient.Dispose();
122 _httpClient = null; 137 _httpClient = null;
123 } 138 }
124 } 139 }
125   140  
126 #endregion 141 #endregion
127   142  
128 #region Public Methods 143 #region Public Methods
129   144  
130 public void Start() 145 public void Start()
131 { 146 {
132 if (_webSocketsUri == null || _httpUri == null) 147 if (_webSocketsUri == null || _httpUri == null)
133 { 148 {
134 Log.Error("Could not start connection to server due to unreadable URLs."); 149 Log.Error("Could not start connection to server due to unreadable URLs.");
135 return; 150 return;
136 } 151 }
137   152  
138 _cancellationTokenSource = new CancellationTokenSource(); 153 _cancellationTokenSource = new CancellationTokenSource();
139 _cancellationToken = _cancellationTokenSource.Token; 154 _cancellationToken = _cancellationTokenSource.Token;
140   155  
141 Connect(); 156 Connect();
142   157  
143 _runTask = Run(_cancellationToken); 158 _runTask = Run(_cancellationToken);
144 } 159 }
145   160  
146 private void Connect() 161 private void Connect()
147 { 162 {
148 _webSocketSharp = new WebSocket(_webSocketsUri.AbsoluteUri); 163 _webSocketSharp = new WebSocket(_webSocketsUri.AbsoluteUri);
-   164 _webSocketSharp.SslConfiguration = new ClientSslConfiguration(_webSocketsUri.Host,
-   165 new X509CertificateCollection(new X509Certificate[] { }), SslProtocols.Tls12, false);
-   166 if (_configuration.Proxy.Enable)
-   167 {
-   168 _webSocketSharp.SetProxy(_configuration.Proxy.Url, _configuration.Proxy.Username, _configuration.Proxy.Password);
-   169 }
-   170  
149 if (!string.IsNullOrEmpty(_server.Username) && !string.IsNullOrEmpty(_server.Password)) 171 if (!string.IsNullOrEmpty(_server.Username) && !string.IsNullOrEmpty(_server.Password))
150 { 172 {
151 _webSocketSharp.SetCredentials(_server.Username, _server.Password, true); 173 _webSocketSharp.SetCredentials(_server.Username, _server.Password, true);
152 } 174 }
153   175  
154 if (_configuration.IgnoreSelfSignedCertificates) 176 if (_configuration.IgnoreSelfSignedCertificates)
155 { 177 {
156 _webSocketSharp.SslConfiguration.ServerCertificateValidationCallback += 178 _webSocketSharp.SslConfiguration.ServerCertificateValidationCallback +=
157 (sender, certificate, chain, errors) => true; 179 (sender, certificate, chain, errors) => true;
158 } 180 }
159   181  
160 _webSocketSharp.OnMessage += WebSocketSharp_OnMessage; 182 _webSocketSharp.OnMessage += WebSocketSharp_OnMessage;
161 _webSocketSharp.OnError += WebSocketSharp_OnError; 183 _webSocketSharp.OnError += WebSocketSharp_OnError;
162 _webSocketSharp.OnOpen += WebSocketSharp_OnOpen; 184 _webSocketSharp.OnOpen += WebSocketSharp_OnOpen;
163 _webSocketSharp.OnClose += WebSocketSharp_OnClose; 185 _webSocketSharp.OnClose += WebSocketSharp_OnClose;
-   186 _webSocketSharp.Log.Output = (data, s) =>
-   187 {
-   188 var a = s;
-   189 };
164 _webSocketSharp.ConnectAsync(); 190 _webSocketSharp.ConnectAsync();
165 } 191 }
166   192  
167 private void WebSocketSharp_OnClose(object sender, CloseEventArgs e) 193 private void WebSocketSharp_OnClose(object sender, CloseEventArgs e)
168 { 194 {
169 Log.Information($"WebSockets connection to server {_webSocketsUri.AbsoluteUri} closed with reason {e.Reason}."); 195 Log.Information($"WebSockets connection to server {_webSocketsUri.AbsoluteUri} closed with reason {e.Reason}.");
170 } 196 }
171   197  
172 private void WebSocketSharp_OnOpen(object sender, EventArgs e) 198 private void WebSocketSharp_OnOpen(object sender, EventArgs e)
173 { 199 {
174 Log.Information($"WebSockets connection to server {_webSocketsUri.AbsoluteUri} is now open."); 200 Log.Information($"WebSockets connection to server {_webSocketsUri.AbsoluteUri} is now open.");
175 } 201 }
176   202  
177 private async void WebSocketSharp_OnError(object sender, ErrorEventArgs e) 203 private async void WebSocketSharp_OnError(object sender, ErrorEventArgs e)
178 { 204 {
179 Log.Error($"Connection to WebSockets server {_webSocketsUri.AbsoluteUri} terminated unexpectedly with message {e.Message}.", e.Exception); 205 Log.Error($"Connection to WebSockets server {_webSocketsUri.AbsoluteUri} terminated unexpectedly with message {e.Message}.", e.Exception);
180   206  
181 if (_cancellationToken.IsCancellationRequested) 207 if (_cancellationToken.IsCancellationRequested)
182 { 208 {
183 Stop(); 209 Stop();
184 return; 210 return;
185 } 211 }
186   212  
187 await Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken); 213 await Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken);
188 Log.Information($"Reconnecting to websocket server {_webSocketsUri.AbsoluteUri}."); 214 Log.Information($"Reconnecting to websocket server {_webSocketsUri.AbsoluteUri}.");
189   215  
190 Connect(); 216 Connect();
191 } 217 }
192   218  
193 private async void WebSocketSharp_OnMessage(object sender, MessageEventArgs e) 219 private async void WebSocketSharp_OnMessage(object sender, MessageEventArgs e)
194 { 220 {
195 if (e.RawData.Length == 0) 221 if (e.RawData.Length == 0)
196 { 222 {
197 Log.Warning($"Empty message received from server."); 223 Log.Warning($"Empty message received from server.");
198 return; 224 return;
199 } 225 }
200   226  
201 var message = Encoding.UTF8.GetString(e.RawData, 0, e.RawData.Length); 227 var message = Encoding.UTF8.GetString(e.RawData, 0, e.RawData.Length);
202   228  
203 GotifyNotification gotifyNotification; 229 GotifyNotification gotifyNotification;
204   230  
205 try 231 try
206 { 232 {
207 gotifyNotification = JsonConvert.DeserializeObject<GotifyNotification>(message); 233 gotifyNotification = JsonConvert.DeserializeObject<GotifyNotification>(message);
208 } 234 }
209 catch (JsonSerializationException exception) 235 catch (JsonSerializationException exception)
210 { 236 {
211 Log.Warning($"Could not deserialize notification: {exception.Message}"); 237 Log.Warning($"Could not deserialize notification: {exception.Message}");
212 return; 238 return;
213 } 239 }
214   240  
215 if (gotifyNotification == null) 241 if (gotifyNotification == null)
216 { 242 {
217 Log.Warning($"Could not deserialize gotify notification: {message}"); 243 Log.Warning($"Could not deserialize gotify notification: {message}");
218   244  
219 return; 245 return;
220 } 246 }
221   247  
222 gotifyNotification.Server = _server; 248 gotifyNotification.Server = _server;
223   249  
224 if (!Uri.TryCreate(Path.Combine($"{_httpUri}", "application"), UriKind.Absolute, 250 if (!Uri.TryCreate(Path.Combine($"{_httpUri}", "application"), UriKind.Absolute,
225 out var applicationUri)) 251 out var applicationUri))
226 { 252 {
227 Log.Warning($"Could not build an URI to an application."); 253 Log.Warning($"Could not build an URI to an application.");
228 return; 254 return;
229 } 255 }
230   256  
231 using (var imageStream = 257 using (var imageStream =
232 await RetrieveGotifyApplicationImage(gotifyNotification.AppId, applicationUri, _cancellationToken)) 258 await RetrieveGotifyApplicationImage(gotifyNotification.AppId, applicationUri, _cancellationToken))
233 { 259 {
234 if (imageStream == null) 260 if (imageStream == null)
235 { 261 {
236 Log.Warning("Could not find any application image for notification."); 262 Log.Warning("Could not find any application image for notification.");
237 return; 263 return;
238 } 264 }
239   265  
240 var image = Image.FromStream(imageStream); 266 var image = Image.FromStream(imageStream);
241   267  
242 GotifyNotification?.Invoke(this, 268 GotifyNotification?.Invoke(this,
243 new GotifyNotificationEventArgs(gotifyNotification, image)); 269 new GotifyNotificationEventArgs(gotifyNotification, image));
244 } 270 }
245   271  
246 Log.Debug($"Notification message received: {gotifyNotification.Message}"); 272 Log.Debug($"Notification message received: {gotifyNotification.Message}");
247 } 273 }
248   274  
249 public void Stop() 275 public void Stop()
250 { 276 {
251 if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel(); 277 if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel();
252 } 278 }
253   279  
254 #endregion 280 #endregion
255   281  
256 #region Private Methods 282 #region Private Methods
257   283  
258 private async Task Run(CancellationToken cancellationToken) 284 private async Task Run(CancellationToken cancellationToken)
259 { 285 {
260 try 286 try
261 { 287 {
262 do 288 do
263 { 289 {
264 await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); 290 await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
265 } while (!cancellationToken.IsCancellationRequested); 291 } while (!cancellationToken.IsCancellationRequested);
266 } 292 }
267 catch (Exception exception) when (exception is OperationCanceledException || exception is ObjectDisposedException) 293 catch (Exception exception) when (exception is OperationCanceledException || exception is ObjectDisposedException)
268 { 294 {
269 } 295 }
270 catch (Exception exception) 296 catch (Exception exception)
271 { 297 {
272 Log.Warning(exception, "Failure running connection loop."); 298 Log.Warning(exception, "Failure running connection loop.");
273 } 299 }
274 } 300 }
275   301  
276 private async Task<Stream> RetrieveGotifyApplicationImage(int appId, Uri applicationUri, 302 private async Task<Stream> RetrieveGotifyApplicationImage(int appId, Uri applicationUri,
277 CancellationToken cancellationToken) 303 CancellationToken cancellationToken)
278 { 304 {
279 var applicationResponse = await _httpClient.GetAsync(applicationUri, cancellationToken); 305 var applicationResponse = await _httpClient.GetAsync(applicationUri, cancellationToken);
280   306  
281 var applications = await applicationResponse.Content.ReadAsStringAsync(); 307 var applications = await applicationResponse.Content.ReadAsStringAsync();
282   308  
283 GotifyApplication[] gotifyApplications; 309 GotifyApplication[] gotifyApplications;
284 try 310 try
285 { 311 {
286 gotifyApplications = 312 gotifyApplications =
287 JsonConvert.DeserializeObject<GotifyApplication[]>(applications); 313 JsonConvert.DeserializeObject<GotifyApplication[]>(applications);
288 } 314 }
289 catch (JsonSerializationException exception) 315 catch (JsonSerializationException exception)
290 { 316 {
291 Log.Warning($"Could not deserialize the list of applications from the server: {exception.Message}"); 317 Log.Warning($"Could not deserialize the list of applications from the server: {exception.Message}");
292   318  
293 return null; 319 return null;
294 } 320 }
295   321  
296 foreach (var application in gotifyApplications) 322 foreach (var application in gotifyApplications)
297 { 323 {
298 if (application.Id != appId) continue; 324 if (application.Id != appId) continue;
299   325  
300 if (!Uri.TryCreate(Path.Combine($"{_httpUri}", $"{application.Image}"), UriKind.Absolute, 326 if (!Uri.TryCreate(Path.Combine($"{_httpUri}", $"{application.Image}"), UriKind.Absolute,
301 out var applicationImageUri)) 327 out var applicationImageUri))
302 { 328 {
303 Log.Warning("Could not build URL path to application icon."); 329 Log.Warning("Could not build URL path to application icon.");
304 continue; 330 continue;
305 } 331 }
306   332  
307 var imageResponse = await _httpClient.GetAsync(applicationImageUri, cancellationToken); 333 var imageResponse = await _httpClient.GetAsync(applicationImageUri, cancellationToken);
308   334  
309 var memoryStream = new MemoryStream(); 335 var memoryStream = new MemoryStream();
310   336  
311 await imageResponse.Content.CopyToAsync(memoryStream); 337 await imageResponse.Content.CopyToAsync(memoryStream);
312   338  
313 return memoryStream; 339 return memoryStream;
314 } 340 }
315   341  
316 return null; 342 return null;
317 } 343 }
318   344  
319 #endregion 345 #endregion
320 } 346 }
321 } 347 }
322   348  
323
Generated by GNU Enscript 1.6.5.90.
349
Generated by GNU Enscript 1.6.5.90.
324   350  
325   351  
326   352