source: TFP-WebServer/WebServer/src/SSE/AbsEvent.cs@ 500

Last change on this file since 500 was 499, checked in by alloc, 4 months ago

*Fixed: Chat code
*Fixed: SSE connection counting, added connection set up logging

File size: 2.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Text;
4using Webserver.UrlHandlers;
5
6namespace Webserver.SSE {
7 public abstract class AbsEvent {
8 private const int encodingBufferSize = 1024 * 1024;
9
10 private readonly SseHandler parent;
11 public readonly string Name;
12
13 private readonly byte[] encodingBuffer;
14 private readonly StringBuilder stringBuilder = new StringBuilder ();
15
16 private readonly List<SseClient> openClients = new List<SseClient> ();
17
18 private readonly BlockingQueue<(string _eventName, string _data)> sendQueue =
19 new BlockingQueue<(string _eventName, string _data)> ();
20
21 private int currentlyOpen;
22 private int totalOpened;
23 private int totalClosed;
24
25 protected AbsEvent (SseHandler _parent, bool _reuseEncodingBuffer = true, string _name = null) {
26 Name = _name ?? GetType ().Name;
27 parent = _parent;
28 if (_reuseEncodingBuffer) {
29 encodingBuffer = new byte[encodingBufferSize];
30 }
31 }
32
33 public void AddListener (SseClient _client) {
34 totalOpened++;
35 currentlyOpen++;
36
37 openClients.Add (_client);
38
39 logConnectionState ("Connection opened", _client);
40 }
41
42 protected void SendData (string _eventName, string _data) {
43 sendQueue.Enqueue ((_eventName, _data));
44 parent.SignalSendQueue ();
45 }
46
47 public void ProcessSendQueue () {
48 while (sendQueue.HasData ()) {
49 (string eventName, string data) = sendQueue.Dequeue ();
50
51 stringBuilder.Append ("event: ");
52 stringBuilder.AppendLine (eventName);
53 stringBuilder.Append ("data: ");
54 stringBuilder.AppendLine (data);
55
56 stringBuilder.AppendLine ("");
57
58 string output = stringBuilder.ToString ();
59 stringBuilder.Clear ();
60
61 byte[] buf;
62 int bytesToSend;
63 if (encodingBuffer != null) {
64 buf = encodingBuffer;
65 try {
66 bytesToSend = Encoding.UTF8.GetBytes (output, 0, output.Length, buf, 0);
67 } catch (ArgumentException e) {
68 Log.Error ($"[Web] [SSE] '{Name}': Exception while encoding data for output, most likely exceeding buffer size:");
69 Log.Exception (e);
70 return;
71 }
72 } else {
73 buf = Encoding.UTF8.GetBytes (output);
74 bytesToSend = buf.Length;
75 }
76
77 sendBufToListeners (buf, bytesToSend);
78 }
79 }
80
81 private void sendBufToListeners (byte[] _bytes, int _bytesToSend) {
82 for (int i = openClients.Count - 1; i >= 0; i--) {
83 openClients [i].Write (_bytes, _bytesToSend);
84 }
85 }
86
87 public virtual int DefaultPermissionLevel () => 0;
88
89 private void logConnectionState (string _message, SseClient _client) {
90 Log.Out ($"[Web] [SSE] '{Name}': {_message} from {_client.RemoteEndpoint} (Left open: {currentlyOpen}, total opened: {totalOpened}, closed: {totalClosed})");
91 }
92
93 public void ClientClosed (SseClient _client) {
94 if (openClients.Remove (_client)) {
95 currentlyOpen--;
96 totalClosed++;
97
98 logConnectionState ("Closed connection", _client);
99 }
100 }
101 }
102}
Note: See TracBrowser for help on using the repository browser.