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
RevLine 
[391]1using System;
2using System.Collections.Generic;
3using System.Text;
4using Webserver.UrlHandlers;
5
6namespace Webserver.SSE {
7 public abstract class AbsEvent {
[409]8 private const int encodingBufferSize = 1024 * 1024;
[391]9
[409]10 private readonly SseHandler parent;
[391]11 public readonly string Name;
12
13 private readonly byte[] encodingBuffer;
14 private readonly StringBuilder stringBuilder = new StringBuilder ();
15
[487]16 private readonly List<SseClient> openClients = new List<SseClient> ();
[391]17
[402]18 private readonly BlockingQueue<(string _eventName, string _data)> sendQueue =
19 new BlockingQueue<(string _eventName, string _data)> ();
[391]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;
[409]27 parent = _parent;
[391]28 if (_reuseEncodingBuffer) {
[409]29 encodingBuffer = new byte[encodingBufferSize];
[391]30 }
31 }
32
[487]33 public void AddListener (SseClient _client) {
[391]34 totalOpened++;
35 currentlyOpen++;
36
[487]37 openClients.Add (_client);
[499]38
39 logConnectionState ("Connection opened", _client);
[391]40 }
41
[402]42 protected void SendData (string _eventName, string _data) {
[391]43 sendQueue.Enqueue ((_eventName, _data));
[409]44 parent.SignalSendQueue ();
[391]45 }
46
47 public void ProcessSendQueue () {
48 while (sendQueue.HasData ()) {
[402]49 (string eventName, string data) = sendQueue.Dequeue ();
[391]50
51 stringBuilder.Append ("event: ");
52 stringBuilder.AppendLine (eventName);
53 stringBuilder.Append ("data: ");
[402]54 stringBuilder.AppendLine (data);
[391]55
56 stringBuilder.AppendLine ("");
[402]57
[391]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) {
[499]68 Log.Error ($"[Web] [SSE] '{Name}': Exception while encoding data for output, most likely exceeding buffer size:");
[391]69 Log.Exception (e);
70 return;
71 }
72 } else {
73 buf = Encoding.UTF8.GetBytes (output);
74 bytesToSend = buf.Length;
75 }
76
[409]77 sendBufToListeners (buf, bytesToSend);
78 }
79 }
[391]80
[409]81 private void sendBufToListeners (byte[] _bytes, int _bytesToSend) {
[487]82 for (int i = openClients.Count - 1; i >= 0; i--) {
[499]83 openClients [i].Write (_bytes, _bytesToSend);
[391]84 }
85 }
86
[499]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})");
[391]91 }
92
[499]93 public void ClientClosed (SseClient _client) {
94 if (openClients.Remove (_client)) {
95 currentlyOpen--;
96 totalClosed++;
[487]97
[499]98 logConnectionState ("Closed connection", _client);
99 }
[487]100 }
[391]101 }
102}
Note: See TracBrowser for help on using the repository browser.