fixed: websocket server wrong execution thread

This commit is contained in:
2022-12-25 03:13:01 -08:00
parent f34b05e6ff
commit e9418f4b22
10 changed files with 110 additions and 109 deletions
+1 -2
View File
@@ -3,9 +3,8 @@ using Ragon.Common;
namespace Ragon.Core.Game; namespace Ragon.Core.Game;
public class EntityState public class EntityState
{ {
private Logger _logger = LogManager.GetCurrentClassLogger();
private List<EntityStateProperty> _properties; private List<EntityStateProperty> _properties;
private Entity _entity; private Entity _entity;
+2 -2
View File
@@ -24,8 +24,8 @@ public class EntityStateProperty
public ReadOnlySpan<byte> Read() public ReadOnlySpan<byte> Read()
{ {
var dataSpan = _data.AsSpan(); var dataSpan = _data.AsSpan();
var src = dataSpan.Slice(0, Size);
return dataSpan.Slice(0, Size); return src;
} }
public void Write(ref ReadOnlySpan<byte> src) public void Write(ref ReadOnlySpan<byte> src)
@@ -14,6 +14,7 @@ public sealed class EntityStateHandler: IHandler
for (var entityIndex = 0; entityIndex < entitiesCount; entityIndex++) for (var entityIndex = 0; entityIndex < entitiesCount; entityIndex++)
{ {
var entityId = reader.ReadUShort(); var entityId = reader.ReadUShort();
if (room.Entities.TryGetValue(entityId, out var entity)) if (room.Entities.TryGetValue(entityId, out var entity))
{ {
entity.State.Read(reader); entity.State.Read(reader);
@@ -76,6 +76,6 @@ public sealed class JoinOrCreateHandler : IHandler
var sendData = writer.ToArray(); var sendData = writer.ToArray();
player.Connection.Reliable.Send(sendData); player.Connection.Reliable.Send(sendData);
_logger.Trace($"Joined to room {room.Id}"); _logger.Trace($"{player.Connection.Id}|{player.Name} joined to room {room.Id}");
} }
} }
+2 -1
View File
@@ -36,10 +36,11 @@ public sealed class SceneLoadedHandler : IHandler
entity.State.AddProperty(new EntityStateProperty(propertySize, propertyType)); entity.State.AddProperty(new EntityStateProperty(propertySize, propertyType));
} }
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} created entity {entity.Id}:{entity.Type}");
room.AttachEntity(player, entity); room.AttachEntity(player, entity);
} }
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} loaded with {statics} scene entities"); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} loaded");
room.WaitPlayersList.Add(player); room.WaitPlayersList.Add(player);
+1 -1
View File
@@ -35,7 +35,7 @@ namespace Ragon.Server.ENet
_host.Create(address, _connections.Length, 2, 0, 0, 1024 * 1024); _host.Create(address, _connections.Length, 2, 0, 0, 1024 * 1024);
var protocolDecoded = RagonVersion.Parse(_protocol); var protocolDecoded = RagonVersion.Parse(_protocol);
_logger.Info($"Network listening on {configuration.Port}"); _logger.Info($"Listen at 127.0.0.1:{configuration.Port}");
_logger.Info($"Protocol: {protocolDecoded}"); _logger.Info($"Protocol: {protocolDecoded}");
} }
@@ -13,109 +13,112 @@ namespace Ragon.Core;
public class NativeWebSocketServer : INetworkServer public class NativeWebSocketServer : INetworkServer
{ {
private ILogger _logger = LogManager.GetCurrentClassLogger(); private ILogger _logger = LogManager.GetCurrentClassLogger();
private INetworkListener _networkListener; private INetworkListener _networkListener;
private Stack<ushort> _sequencer; private Stack<ushort> _sequencer;
private Executor _executor; private Executor _executor;
private HttpListener _httpListener; private HttpListener _httpListener;
private WebSocketConnection[] _connections; private WebSocketConnection[] _connections;
private ushort _lastPeerId; private List<WebSocketConnection> _activeConnections;
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
public NativeWebSocketServer(Executor executor) public NativeWebSocketServer(Executor executor)
{
_sequencer = new Stack<ushort>();
_connections = Array.Empty<WebSocketConnection>();
_activeConnections = new List<WebSocketConnection>();
_executor = executor;
}
public async void StartAccept(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{ {
_sequencer = new Stack<ushort>(); var context = await _httpListener.GetContextAsync();
_connections = Array.Empty<WebSocketConnection>(); if (!context.Request.IsWebSocketRequest) continue;
_executor = executor;
var webSocketContext = await context.AcceptWebSocketAsync(null);
var webSocket = webSocketContext.WebSocket;
var peerId = _sequencer.Pop();
var connection = new WebSocketConnection(webSocket, peerId);
_connections[peerId] = connection;
StartListen(connection, cancellationToken);
}
}
async void StartListen(WebSocketConnection connection, CancellationToken cancellationToken)
{
_activeConnections.Add(connection);
_networkListener.OnConnected(connection);
var webSocket = connection.Socket;
var bytes = new byte[2048];
var buffer = new Memory<byte>(bytes);
while (
webSocket.State == WebSocketState.Open ||
!cancellationToken.IsCancellationRequested)
{
try
{
var result = await webSocket.ReceiveAsync(buffer, cancellationToken);
var dataRaw = buffer.Slice(0, result.Count);
_networkListener.OnData(connection, dataRaw.ToArray());
}
catch (Exception ex)
{
break;
}
} }
public async Task StartAccept(CancellationToken cancellationToken) _sequencer.Push(connection.Id);
{ _activeConnections.Remove(connection);
while (!cancellationToken.IsCancellationRequested) _networkListener.OnDisconnected(connection);
{ }
var context = await _httpListener.GetContextAsync();
if (!context.Request.IsWebSocketRequest) continue;
var webSocketContext = await context.AcceptWebSocketAsync(null); public void Poll()
var webSocket = webSocketContext.WebSocket; {
Flush();
}
var peerId = _sequencer.Pop(); public async void Flush()
var connection = new WebSocketConnection(webSocket, peerId); {
foreach (var conn in _activeConnections)
await conn.Flush();
}
_lastPeerId = peerId; public void Start(
_connections[peerId] = connection; INetworkListener listener,
_networkListener.OnConnected(connection); NetworkConfiguration configuration
_executor.Run(StartListen(connection, cancellationToken)); )
} {
} _networkListener = listener;
_cancellationTokenSource = new CancellationTokenSource();
async Task StartListen(WebSocketConnection connection, CancellationToken cancellationToken) var limit = (ushort)configuration.LimitConnections;
{ for (ushort i = limit; i != 0; i--)
var webSocket = connection.Socket; _sequencer.Push(i);
var bytes = new byte[2048];
var buffer = new Memory<byte>(bytes);
while (
webSocket.State == WebSocketState.Open ||
!cancellationToken.IsCancellationRequested)
{
try
{
var result = await webSocket.ReceiveAsync(buffer, cancellationToken);
var dataRaw = buffer.Slice(0, result.Count);
_networkListener.OnData(connection, dataRaw.ToArray()); _sequencer.Push(0);
}
catch (Exception ex)
{
break;
}
}
_sequencer.Push(connection.Id); _connections = new WebSocketConnection[configuration.LimitConnections];
_networkListener.OnDisconnected(connection);
}
public async void Poll() _httpListener = new HttpListener();
{ _httpListener.Prefixes.Add($"http://127.0.0.1:{configuration.Port}/");
foreach (var conn in _connections) _httpListener.Start();
{
if (conn != null)
{
await conn.Flush();
}
}
}
public void Start( _executor.Run(() => StartAccept(_cancellationTokenSource.Token));
INetworkListener listener,
NetworkConfiguration configuration
)
{
_networkListener = listener;
_cancellationTokenSource = new CancellationTokenSource();
var limit = (ushort) configuration.LimitConnections; var protocolDecoded = RagonVersion.Parse(configuration.Protocol);
for (ushort i = limit; i != 0; i--) _logger.Info($"Listen at http://*:{configuration.Port}/");
_sequencer.Push(i); _logger.Info($"Protocol: {protocolDecoded}");
}
_sequencer.Push(0); public void Stop()
{
_connections = new WebSocketConnection[configuration.LimitConnections]; _cancellationTokenSource.Cancel();
_httpListener.Stop();
_httpListener = new HttpListener(); }
_httpListener.Prefixes.Add($"http://127.0.0.1:{configuration.Port}/");
_httpListener.Start();
_executor.Run(StartAccept(_cancellationTokenSource.Token));
var protocolDecoded = RagonVersion.Parse(configuration.Protocol);
_logger.Info($"Network listening on http://*:{configuration.Port}/");
_logger.Info($"Protocol: {protocolDecoded}");
}
public void Stop()
{
_cancellationTokenSource.Cancel();
_httpListener.Stop();
}
} }
+2 -2
View File
@@ -9,9 +9,9 @@ public class Executor: TaskScheduler
private Queue<Task> _pendingTasks; private Queue<Task> _pendingTasks;
private TaskFactory _taskFactory; private TaskFactory _taskFactory;
public void Run(Task task) public void Run(Action action)
{ {
_taskFactory.StartNew(() => task); _taskFactory.StartNew(action);
} }
public Executor() public Executor()
+2 -5
View File
@@ -6,14 +6,12 @@
Ragon is fully free, small and high perfomance room based game server with plugin based architecture. Ragon is fully free, small and high perfomance room based game server with plugin based architecture.
<a href="https://ragon-server.com/docs/category/basics">Documentation</a> <a href="http://localhost:3000/docs/installation">Documentation</a>
<br>
<a href="https://ragon-server.com/docs/get-started">Get started</a>
### Features: ### Features:
- Effective - Effective
- Free - Free
- Simple matchmaking - Lobby
- Room based architecture - Room based architecture
- Сustomizable authorization - Сustomizable authorization
- Сustomizable server-side logic via plugins with flexible API*(2) - Сustomizable server-side logic via plugins with flexible API*(2)
@@ -33,5 +31,4 @@ MIT
### Tips ### Tips
\* Limited to 4095 CCU by library ENet-Sharp (1) \* Limited to 4095 CCU by library ENet-Sharp (1)
\* Non finally (2) \* Non finally (2)