Skip to content

Commit e235c96

Browse files
committed
- Pass on safety, optimization and error handling
1 parent bece958 commit e235c96

9 files changed

Lines changed: 404 additions & 162 deletions

File tree

GenOnlineService/Constants.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,11 @@ public static async Task<UserWebSocketInstance> CreateSession(bool bIsReconnect,
238238
return newSess;
239239
}
240240

241-
public static async void Tick()
241+
public static async Task Tick()
242242
{
243243
foreach (var kvPair in m_dictUserSessions)
244244
{
245-
kvPair.Value.TickWebsocket();
245+
await kvPair.Value.TickWebsocket();
246246
}
247247
}
248248

@@ -642,7 +642,7 @@ public async Task<UserWebSocketInstance> CloseWebsocket(WebSocketCloseStatus rea
642642
return websocketForUser;
643643
}
644644

645-
public async void TickWebsocket()
645+
public async Task TickWebsocket()
646646
{
647647
// Do we have a connection to send on?
648648
UserWebSocketInstance websocketForUser = WebSocketManager.GetWebSocketForSession(this);
@@ -748,7 +748,7 @@ public bool WasPlayerInMatch(UInt64 matchID, out int slotIndexInLobby, out int a
748748
return bWasInMatch;
749749
}
750750

751-
public async void UpdateSessionNetworkRoom(Int16 newRoomID)
751+
public async Task UpdateSessionNetworkRoom(Int16 newRoomID)
752752
{
753753
Int16 oldRoom = networkRoomID;
754754
networkRoomID = newRoomID;

GenOnlineService/Controllers/Lobbies/LobbiesController.cs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,31 @@ public override Type GetReturnType()
6060
public class LobbiesController : ControllerBase
6161
{
6262
private readonly ILogger<LobbiesController> _logger;
63+
private static List<RoomData>? s_cachedRooms = null;
64+
private static readonly object s_roomsLock = new object();
6365

6466
public LobbiesController(ILogger<LobbiesController> logger)
6567
{
6668
_logger = logger;
6769
}
6870

71+
// Cache rooms.json data to avoid disk I/O on every request
72+
private static async Task<List<RoomData>?> GetCachedRooms(JsonSerializerOptions options)
73+
{
74+
if (s_cachedRooms == null)
75+
{
76+
lock (s_roomsLock)
77+
{
78+
if (s_cachedRooms == null)
79+
{
80+
string strFileData = System.IO.File.ReadAllText(Path.Combine("data", "rooms.json"));
81+
s_cachedRooms = JsonSerializer.Deserialize<List<RoomData>>(strFileData, options);
82+
}
83+
}
84+
}
85+
return await Task.FromResult(s_cachedRooms);
86+
}
87+
6988
// FOR LATENCY ESTIMATIONS
7089
// Convert degrees to radians
7190
public static double ToRadians(double angleInDegrees)
@@ -136,9 +155,8 @@ public async Task<APIResult> Get()
136155

137156
if (sourceData != null)
138157
{
139-
// TODO: Dont deserialize this per request, cache it in the session
140-
string strFileData = await System.IO.File.ReadAllTextAsync(Path.Combine("data", "rooms.json"));
141-
List<RoomData>? lstRooms = JsonSerializer.Deserialize<List<RoomData>>(strFileData, options);
158+
// Use cached rooms data
159+
List<RoomData>? lstRooms = await GetCachedRooms(options);
142160
if (lstRooms != null)
143161
{
144162
foreach (RoomData room in lstRooms)
@@ -307,6 +325,28 @@ public async Task<APIResult> Put()
307325
UInt32 exe_crc = data["exe_crc"].GetUInt32();
308326
UInt32 ini_crc = data["ini_crc"].GetUInt32();
309327

328+
// Input validation
329+
if (strName != null && strName.Length > 255)
330+
{
331+
Response.StatusCode = (int)HttpStatusCode.BadRequest;
332+
return result;
333+
}
334+
if (strMapName != null && strMapName.Length > 255)
335+
{
336+
Response.StatusCode = (int)HttpStatusCode.BadRequest;
337+
return result;
338+
}
339+
if (strMapPath != null && strMapPath.Length > 512)
340+
{
341+
Response.StatusCode = (int)HttpStatusCode.BadRequest;
342+
return result;
343+
}
344+
if (strPassword != null && strPassword.Length > 128)
345+
{
346+
Response.StatusCode = (int)HttpStatusCode.BadRequest;
347+
return result;
348+
}
349+
310350

311351

312352
// get requesting user data from session token

GenOnlineService/Controllers/Lobby/LobbyController.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ public async Task<APIResult> Delete(Int64 lobbyID)
263263
string jsonData = await reader.ReadToEndAsync();
264264
var options = new JsonSerializerOptions
265265
{
266-
PropertyNameCaseInsensitive = true
266+
PropertyNameCaseInsensitive = true,
267+
MaxDepth = 32
267268
};
268269

269270
try
@@ -487,7 +488,7 @@ public async Task<APIResult> Post(Int64 lobbyID)
487488
}
488489

489490
// we have to manually send to the kicked user... they won't get the dirty lobby update anymore
490-
lobby.DirtyRetransmitToSingleMember(KickedUserID);
491+
await lobby.DirtyRetransmitToSingleMember(KickedUserID);
491492
}
492493
}
493494
}

GenOnlineService/Controllers/Matchmaking/MatchmakingController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public MatchmakingController(ILogger<MatchmakingController> logger)
7171
{
7272
UInt16 playlistID = data["playlist"].GetUInt16();
7373
var array = data["maps"].EnumerateArray();
74-
List<int> mapIndices = array.ToList().Select(x => x.GetInt32()).ToList();
74+
List<int> mapIndices = array.Select(x => x.GetInt32()).ToList();
7575
UInt32 exe_crc = data["exe_crc"].GetUInt32();
7676
UInt32 ini_crc = data["ini_crc"].GetUInt32();
7777

GenOnlineService/Controllers/WebSocket/WebSocketController.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using Microsoft.AspNetCore.Authorization;
2222
using Microsoft.AspNetCore.Mvc;
2323
using System;
24+
using System.Buffers;
2425
using System.Net.WebSockets;
2526
using System.Security.Claims;
2627
using System.Text;
@@ -394,7 +395,7 @@ private async Task ProcessWSMessage(UserWebSocketInstance sourceWS, UserSession
394395

395396
outboundMsg.action = chatMessage.action;
396397

397-
// send to everyone (minus those who have the chatter blocked)
398+
// Serialize once before broadcasting
398399
byte[] bytesJSON = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(outboundMsg));
399400

400401
// send it to everyone in the same room
@@ -430,7 +431,7 @@ private async Task ProcessWSMessage(UserWebSocketInstance sourceWS, UserSession
430431
if (data != null && data.ContainsKey("room"))
431432
{
432433
Int16 roomID = data["room"].GetInt16();
433-
sourceUserSession.UpdateSessionNetworkRoom(roomID);
434+
await sourceUserSession.UpdateSessionNetworkRoom(roomID);
434435
}
435436
}
436437
else if (msgID == EWebSocketMessageID.NETWORK_ROOM_MARK_READY)
@@ -557,7 +558,7 @@ private async Task ProcessWSMessage(UserWebSocketInstance sourceWS, UserSession
557558
outboundMsg.announcement = chatMessage.announcement;
558559
outboundMsg.show_announcement_to_host = chatMessage.show_announcement_to_host;
559560

560-
// send to everyone in lobby
561+
// Serialize once before broadcasting
561562
byte[] bytesJSON = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(outboundMsg));
562563

563564
foreach (LobbyMember lobbyMember in playerLobby.Members)
@@ -630,15 +631,15 @@ private async Task ProcessWSMessage(UserWebSocketInstance sourceWS, UserSession
630631
}
631632

632633
// start match + create placeholder match
633-
lobbyInfo.UpdateState(ELobbyState.INGAME);
634+
await lobbyInfo.UpdateState(ELobbyState.INGAME);
634635

635636
// simple websocket msg, has no data, so dont even read anything
636637

637638
// response
638639
WebSocketMessage_Simple startCommand = new WebSocketMessage_Simple();
639640
startCommand.msg_id = (int)EWebSocketMessageID.START_GAME;
640641

641-
// send to everyone in lobby
642+
// Serialize once before broadcasting
642643
byte[] bytesJSON = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(startCommand));
643644

644645
foreach (KeyValuePair<Int64, UserSession> sessionData in WebSocketManager.GetUserDataCache())
@@ -682,7 +683,7 @@ private async Task ProcessWSMessage(UserWebSocketInstance sourceWS, UserSession
682683
WebSocketMessage_Simple startCommand = new WebSocketMessage_Simple();
683684
startCommand.msg_id = (int)EWebSocketMessageID.FULL_MESH_CONNECTIVITY_CHECK_RESPONSE;
684685

685-
// send to everyone in lobby
686+
// Serialize once before broadcasting
686687
byte[] bytesJSON = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(startCommand));
687688

688689
foreach (KeyValuePair<Int64, UserSession> sessionData in WebSocketManager.GetUserDataCache())
@@ -757,12 +758,6 @@ private async Task ProcessWSMessage(UserWebSocketInstance sourceWS, UserSession
757758
}
758759
else if (msgID == EWebSocketMessageID.NETWORK_SIGNAL)
759760
{
760-
var options = new JsonSerializerOptions
761-
{
762-
PropertyNameCaseInsensitive = true,
763-
AllowOutOfOrderMetadataProperties = true
764-
};
765-
766761
WebSocketMessage_SignalBidirectional? signal =
767762
JsonSerializer.Deserialize<WebSocketMessage_SignalBidirectional>(payload, JsonOpts);
768763
//Console.WriteLine("Signal received: " + signal.signal);

0 commit comments

Comments
 (0)