123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- using InABox.Core;
- using InABox.WebSocket.Shared;
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Runtime.CompilerServices;
- using System.Text;
- using System.Threading.Tasks;
- using WebSocketSharp;
- using WebSocketSharp.Server;
- using static InABox.Server.WebSocket.NotifyState;
- using InternalServer = WebSocketSharp.Server.WebSocketServer;
- using Logger = InABox.Core.Logger;
- namespace InABox.Server.WebSocket
- {
- public delegate void PollEvent(Session session);
- public class NotifyState
- {
- public class Session
- {
- public string ID { get; set; }
- public Guid SessionID { get; set; }
- public Platform Platform { get; set; }
- public Session(string id, Guid sessionID, Platform platform)
- {
- ID = id;
- SessionID = sessionID;
- Platform = platform;
- }
- }
- public ConcurrentDictionary<Guid, Session> SessionMap = new();
- public event PollEvent? OnPoll;
- public void Poll(Session session)
- {
- OnPoll?.Invoke(session);
- }
- }
- public class NotifyHandler : WebSocketBehavior
- {
- private NotifyState NotifyState;
- public NotifyHandler(NotifyState state)
- {
- NotifyState = state;
- }
- protected override void OnOpen()
- {
- Logger.Send(LogType.Information, "", $"WebSocket client connected");
- }
- protected override void OnClose(CloseEventArgs e)
- {
- Logger.Send(LogType.Information, "", $"WebSocket client disconnected");
- var sessionID = NotifyState.SessionMap.Where(x => x.Value.ID == ID).FirstOrDefault().Key;
- NotifyState.SessionMap.TryRemove(sessionID, out var session);
- }
- protected override void OnError(WebSocketSharp.ErrorEventArgs e)
- {
- Logger.Send(LogType.Error, "", $"WebSocket Error: {e.Message}");
- }
- private void DoInitial(InitialMessage initial)
- {
- var newSession = new Session(ID, initial.SessionID, initial.Platform);
- NotifyState.SessionMap[initial.SessionID] = newSession;
- NotifyState.Poll(newSession);
- }
- protected override void OnMessage(MessageEventArgs e)
- {
- Logger.Send(LogType.Information, "", "Message received");
- var message = SocketMessage.ReadMessage(e.RawData);
- if (message is InitialMessage initial)
- {
- DoInitial(initial);
- }
- }
- }
- public class WebSocketServer
- {
- private InternalServer Server;
- private NotifyState NotifyState = new();
- public event PollEvent? Poll;
- public int Port => Server.Port;
- public WebSocketServer(int port)
- {
- Server = new InternalServer(IPAddress.Any, port);
- Server.AddWebSocketService("/notify", NewNotify);
- NotifyState.OnPoll += NotifyState_Poll;
- }
- private void NotifyState_Poll(Session session)
- {
- Poll?.Invoke(session);
- }
- public NotifyHandler NewNotify()
- {
- return new NotifyHandler(NotifyState);
- }
- public IEnumerable<Guid> GetSessions(Platform platform)
- {
- return NotifyState.SessionMap.Where(x => x.Value.Platform == platform).Select(x => x.Key);
- }
- public void Push(Guid sessionID, SocketMessage message)
- {
- if(NotifyState.SessionMap.TryGetValue(sessionID, out var session))
- {
- using(var stream = new MemoryStream())
- {
- message.Write(stream);
- Server.WebSocketServices["/notify"].Sessions.SendToAsync(stream, (int)stream.Length, session.ID, (succ) => { });
- }
- }
- }
- private void PushMessage(SocketMessage message)
- {
- Server.WebSocketServices["/notify"].Sessions.Broadcast(message.WriteToBytes());
- }
- private void PushMessage(SocketMessage message, string session)
- {
- Server.WebSocketServices["/notify"].Sessions.SendTo(message.WriteToBytes(), session);
- }
- public void Push(Type TNotification, object notification)
- {
- PushMessage(NotifyMessage.Notify(TNotification, notification));
- }
- public void Push<TNotification>(TNotification notification)
- {
- PushMessage(NotifyMessage.Notify(notification));
- }
- public void Push(Guid sessionID, Type TNotification, object notification)
- {
- if(NotifyState.SessionMap.TryGetValue(sessionID, out var session))
- {
- PushMessage(NotifyMessage.Notify(TNotification, notification), session.ID);
- }
- }
- public void Push<TNotification>(Guid sessionID, TNotification notification)
- {
- if(NotifyState.SessionMap.TryGetValue(sessionID, out var session))
- {
- PushMessage(NotifyMessage.Notify(notification), session.ID);
- }
- }
- public void Start()
- {
- Server.Start();
- }
- public void Stop()
- {
- Server.Stop();
- }
- }
- }
|