using System; using System.Collections.Generic; using UnityEngine; namespace Mirror.SimpleWeb { public class SimpleWebServer { public event Action onConnect; public event Action onDisconnect; public event Action> onData; public event Action onError; readonly int maxMessagesPerTick; readonly WebSocketServer server; readonly BufferPool bufferPool; public bool Active { get; private set; } public SimpleWebServer(int maxMessagesPerTick, TcpConfig tcpConfig, int maxMessageSize, int handshakeMaxSize, SslConfig sslConfig) { this.maxMessagesPerTick = maxMessagesPerTick; // use max because bufferpool is used for both messages and handshake int max = Math.Max(maxMessageSize, handshakeMaxSize); bufferPool = new BufferPool(5, 20, max); server = new WebSocketServer(tcpConfig, maxMessageSize, handshakeMaxSize, sslConfig, bufferPool); } public void Start(ushort port) { server.Listen(port); Active = true; } public void Stop() { server.Stop(); Active = false; } public void SendAll(List connectionIds, ArraySegment source) { ArrayBuffer buffer = bufferPool.Take(source.Count); buffer.CopyFrom(source); buffer.SetReleasesRequired(connectionIds.Count); // make copy of array before for each, data sent to each client is the same foreach (int id in connectionIds) server.Send(id, buffer); } public void SendOne(int connectionId, ArraySegment source) { ArrayBuffer buffer = bufferPool.Take(source.Count); buffer.CopyFrom(source); server.Send(connectionId, buffer); } public bool KickClient(int connectionId) => server.CloseConnection(connectionId); public string GetClientAddress(int connectionId) => server.GetClientAddress(connectionId); public Request GetClientRequest(int connectionId) => server.GetClientRequest(connectionId); /// /// Processes all new messages /// public void ProcessMessageQueue() { ProcessMessageQueue(null); } /// /// Processes all messages while is enabled /// /// public void ProcessMessageQueue(MonoBehaviour behaviour) { int processedCount = 0; bool skipEnabled = behaviour == null; // check enabled every time in case behaviour was disabled after data while ( (skipEnabled || behaviour.enabled) && processedCount < maxMessagesPerTick && // Dequeue last server.receiveQueue.TryDequeue(out Message next) ) { processedCount++; switch (next.type) { case EventType.Connected: onConnect?.Invoke(next.connId, GetClientAddress(next.connId)); break; case EventType.Data: onData?.Invoke(next.connId, next.data.ToSegment()); next.data.Release(); break; case EventType.Disconnected: onDisconnect?.Invoke(next.connId); break; case EventType.Error: onError?.Invoke(next.connId, next.exception); break; } } if (server.receiveQueue.Count > 0) { Log.Warn("[SWT-SimpleWebServer]: ProcessMessageQueue has {0} remaining.", server.receiveQueue.Count); } } } }