Files
survival-game/Assets/Mirror/Transports/SimpleWeb/SimpleWeb/Server/SimpleWebServer.cs
2025-06-16 13:15:42 +00:00

116 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace Mirror.SimpleWeb
{
public class SimpleWebServer
{
public event Action<int, string> onConnect;
public event Action<int> onDisconnect;
public event Action<int, ArraySegment<byte>> onData;
public event Action<int, Exception> 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<int> connectionIds, ArraySegment<byte> 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<byte> 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);
/// <summary>
/// Processes all new messages
/// </summary>
public void ProcessMessageQueue()
{
ProcessMessageQueue(null);
}
/// <summary>
/// Processes all messages while <paramref name="behaviour"/> is enabled
/// </summary>
/// <param name="behaviour"></param>
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);
}
}
}
}