WebSocketServer.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using InABox.Core;
  2. using InABox.WebSocket.Shared;
  3. using System;
  4. using System.Collections.Concurrent;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Runtime.CompilerServices;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using WebSocketSharp;
  12. using WebSocketSharp.Server;
  13. using static InABox.Server.WebSocket.PushState;
  14. using InternalServer = WebSocketSharp.Server.WebSocketServer;
  15. using Logger = InABox.Core.Logger;
  16. namespace InABox.Server.WebSocket
  17. {
  18. public delegate void PollEvent(Session session);
  19. public class PushState
  20. {
  21. public class Session
  22. {
  23. public string ID { get; set; }
  24. public Guid SessionID { get; set; }
  25. public Platform Platform { get; set; }
  26. public Session(string id, Guid sessionID, Platform platform)
  27. {
  28. ID = id;
  29. SessionID = sessionID;
  30. Platform = platform;
  31. }
  32. }
  33. public ConcurrentDictionary<Guid, Session> SessionMap = new();
  34. public event PollEvent? OnPoll;
  35. public void Poll(Session session)
  36. {
  37. OnPoll?.Invoke(session);
  38. }
  39. }
  40. public class PushHandler : WebSocketBehavior
  41. {
  42. public PushState State { get; set; }
  43. public PushHandler()
  44. {
  45. }
  46. public PushHandler(PushState state)
  47. {
  48. State = state;
  49. }
  50. protected override void OnOpen()
  51. {
  52. Logger.Send(LogType.Information, "", $"WebSocket client connected");
  53. }
  54. protected override void OnClose(CloseEventArgs e)
  55. {
  56. Logger.Send(LogType.Information, "", $"WebSocket client disconnected");
  57. var sessionID = State.SessionMap.FirstOrDefault(x => x.Value.ID == ID).Key;
  58. State.SessionMap.TryRemove(sessionID, out var session);
  59. }
  60. protected override void OnError(WebSocketSharp.ErrorEventArgs e)
  61. {
  62. Logger.Send(LogType.Error, "", $"WebSocket Error: {e.Message}");
  63. }
  64. private void DoInitial(InitialMessage initial)
  65. {
  66. var newSession = new Session(ID, initial.SessionID, initial.Platform);
  67. State.SessionMap[initial.SessionID] = newSession;
  68. State.Poll(newSession);
  69. }
  70. protected override void OnMessage(MessageEventArgs e)
  71. {
  72. Logger.Send(LogType.Information, "", "Message received");
  73. var message = SocketMessage.ReadMessage(e.RawData);
  74. if (message is InitialMessage initial)
  75. {
  76. DoInitial(initial);
  77. }
  78. }
  79. }
  80. public class WebSocketServer
  81. {
  82. private InternalServer Server;
  83. private PushState PushState = new();
  84. public event PollEvent? Poll;
  85. public int Port => Server.Port;
  86. public WebSocketServer(int port)
  87. {
  88. Server = new InternalServer(IPAddress.Any, port);
  89. Server.AddWebSocketService<PushHandler>("/push", (push) =>
  90. {
  91. push.State = PushState;
  92. });
  93. PushState.OnPoll += PushState_Poll;
  94. }
  95. private void PushState_Poll(Session session)
  96. {
  97. Poll?.Invoke(session);
  98. }
  99. public PushHandler NewPush()
  100. {
  101. return new PushHandler(PushState);
  102. }
  103. public IEnumerable<Guid> GetSessions(Platform platform)
  104. {
  105. return PushState.SessionMap.Where(x => x.Value.Platform == platform).Select(x => x.Key);
  106. }
  107. public void Push(Guid sessionID, SocketMessage message)
  108. {
  109. if(PushState.SessionMap.TryGetValue(sessionID, out var session))
  110. {
  111. using(var stream = new MemoryStream())
  112. {
  113. message.Write(stream);
  114. Server.WebSocketServices["/push"].Sessions.SendToAsync(stream, (int)stream.Length, session.ID, (succ) => { });
  115. }
  116. }
  117. }
  118. private void PushMessage(SocketMessage message)
  119. {
  120. Server.WebSocketServices["/push"].Sessions.Broadcast(message.WriteToBytes());
  121. }
  122. private void PushMessage(SocketMessage message, string session)
  123. {
  124. Server.WebSocketServices["/push"].Sessions.SendTo(message.WriteToBytes(), session);
  125. }
  126. public void Push(Type TPush, object push)
  127. {
  128. PushMessage(InABox.WebSocket.Shared.PushMessage.Push(TPush, push));
  129. }
  130. public void Push<TPush>(TPush push)
  131. where TPush : BaseObject
  132. {
  133. PushMessage(InABox.WebSocket.Shared.PushMessage.Push(push));
  134. }
  135. public void Push(Guid sessionID, Type TPush, object push)
  136. {
  137. if(PushState.SessionMap.TryGetValue(sessionID, out var session))
  138. {
  139. PushMessage(InABox.WebSocket.Shared.PushMessage.Push(TPush, push), session.ID);
  140. }
  141. }
  142. public void Push<TPush>(Guid sessionID, TPush push)
  143. where TPush : BaseObject
  144. {
  145. if(PushState.SessionMap.TryGetValue(sessionID, out var session))
  146. {
  147. PushMessage(InABox.WebSocket.Shared.PushMessage.Push(push), session.ID);
  148. }
  149. }
  150. public void Start()
  151. {
  152. Server.Start();
  153. }
  154. public void Stop()
  155. {
  156. Server.Stop();
  157. }
  158. }
  159. }