Skip to content

Unhandled exception: System.ArgumentException: Invalid offset & size! (Parameter 'offset') #326

@253153

Description

@253153

Hi all,
I'm making a multiplayer game and using NetCoreServer as the game server web socket library. Everything has been going well, I wrapped everything in try catch and we have 20-100 players in our room at any given time and it all was running smoothly. But I got this exception that crashed the server despite it all being wrapped in try catch:

02/02/2025 17:57:20 Game WebSocket session with Id 363fd3c4-e36f-4e09-b114-41a2e7aea495 connected! 363fd3c4-e36f-4e09-b114-41a2e7aea495 Client IP Address from X-Real-IP: redacted 02/02/2025 17:57:20 Game WebSocket session with Id 363fd3c4-e36f-4e09-b114-41a2e7aea495 disconnected! Player 7526 connected. Total players: 30 Player 7526 disconnected. 02/02/2025 17:57:20 Unknown message code received: 200 from player with id: 362b3254-4a87-4dc8-974b-dc4528407b76 Full message byte array: C8-4D-6D-12-BA-BF-B8-28-17-E0-98-21-AF-BF-AD-3F-9E-A9-BB-24-BA-AF-A7-23-83-A3-BB-3E-AF-A1-AD-61-EE-87-BB-3E-AB-AB-AA-21-B7-EB-8B-1E-A6-A7-BA-3D-6C-8F-8C-4D-6F-9E-02-0C-D5-97-5D-EC-97-0C-77-95-BC-26-69-17-04-07-37-C9-A6-64-9A-15-04-C6-C8-4D-CE-64-9A-14-04-F9-96-98-CA-64-9A-17-04-C6-C8-4D-CE-64-9A-1A-04-78-34-46-25-67-89-E6-E3-F7-F8-7A-FF-FE-FD-79-F7-F1-FA-EC-9D-0C-F6-9F-70-A7 Closing session because of unknown message code. 02/02/2025 17:57:20 Game WebSocket session with Id 362b3254-4a87-4dc8-974b-dc4528407b76 disconnected! Player 7506 disconnected. 02/02/2025 17:57:20 Game WebSocket session with Id 4bd2e316-b504-4d4d-8079-2f43f817cc95 connected! 4bd2e316-b504-4d4d-8079-2f43f817cc95 Client IP Address from X-Real-IP: redacted Player 7527 connected. Total players: 29 02/02/2025 17:57:20 Game WebSocket session with Id 4bd2e316-b504-4d4d-8079-2f43f817cc95 disconnected! Player 7527 disconnected. Unhandled exception: System.ArgumentException: Invalid offset & size! (Parameter 'offset') at NetCoreServer.Buffer.ExtractString(Int64 offset, Int64 size) at NetCoreServer.HttpRequest.ReceiveHeader(Byte[] buffer, Int32 offset, Int32 size) at NetCoreServer.HttpSession.OnReceived(Byte[] buffer, Int64 offset, Int64 size) at NetCoreServer.TcpSession.ProcessReceive(SocketAsyncEventArgs e) at NetCoreServer.TcpSession.TryReceive() at NetCoreServer.TcpSession.Connect(Socket socket) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.OnAsyncCompleted(Object sender, SocketAsyncEventArgs e) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Net.Sockets.SocketAsyncContext.ReadOperation.System.Threading.IThreadPoolWorkItem.Execute() at System.Net.Sockets.SocketAsyncEngine.System.Threading.IThreadPoolWorkItem.Execute() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() Unhandled exception. System.ArgumentException: Invalid offset & size! (Parameter 'offset') at NetCoreServer.Buffer.ExtractString(Int64 offset, Int64 size) at NetCoreServer.HttpRequest.ReceiveHeader(Byte[] buffer, Int32 offset, Int32 size) at NetCoreServer.HttpSession.OnReceived(Byte[] buffer, Int64 offset, Int64 size) at NetCoreServer.TcpSession.ProcessReceive(SocketAsyncEventArgs e) at NetCoreServer.TcpSession.TryReceive() at NetCoreServer.TcpSession.Connect(Socket socket) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.ProcessAccept(SocketAsyncEventArgs e) at NetCoreServer.TcpServer.OnAsyncCompleted(Object sender, SocketAsyncEventArgs e) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Net.Sockets.SocketAsyncContext.ReadOperation.System.Threading.IThreadPoolWorkItem.Execute() at System.Net.Sockets.SocketAsyncEngine.System.Threading.IThreadPoolWorkItem.Execute() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()

Here is my GameServer.cs connection methods (inherits from WsServer):

   protected override void OnConnected(TcpSession session)
    {
        try
        {
            base.OnConnected(session);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception in OnConnected: " + e);
        }
    }

    protected override void OnDisconnected(TcpSession session)
    {
        try
        {
            base.OnDisconnected(session);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception in OnDisconnected: " + e);
        }
    }

    protected override void OnError(SocketError error)
    {
        Console.WriteLine($"Game WebSocket server caught an error with code {error}");
    }

Here is my GameSession.cs connection methods (inherits from WsSession):

    public override void OnWsConnected(HttpRequest request)
    {
        try
        {

            Console.WriteLine($"{DateTime.Now} Game WebSocket session with Id {Id} connected!");

            // Get the real IP address from the headers
            clientIp = null;

            // Iterate over headers to find 'X-Forwarded-For' or 'X-Real-IP'
            for (int i = 0; i < request.Headers; I++)
            {
                var header = request.Header(i);
                var headerName = header.Item1;
                var headerValue = header.Item2;

                if (headerName.Equals("X-Forwarded-For", StringComparison.OrdinalIgnoreCase))
                {
                    var ipAddresses = headerValue.Split(',');
                    clientIp = ipAddresses[0].Trim();
                    Console.WriteLine($"{Id} Client IP Address from X-Forwarded-For: {clientIp}");
                    break;
                }
                else if (headerName.Equals("X-Real-IP", StringComparison.OrdinalIgnoreCase))
                {
                    clientIp = headerValue.Trim();
                    Console.WriteLine($"{Id} Client IP Address from X-Real-IP: {clientIp}");
                    break;
                }
            }

            // If client IP is still null, use the remote endpoint
            if (clientIp == null)
            {
                clientIp = Socket.RemoteEndPoint.ToString();
                Console.WriteLine($"Client IP Address from RemoteEndPoint: {clientIp}");
            }

            if (clientIp != null && GameServer.IsUserBanned(clientIp))
            {
                Console.WriteLine($"Client IP Address {clientIp} is banned. Closing connection...");
                Close(1000, "You have been banned.");
            }
            else
            {
                // Create a new player associated with this session
                Player = new Player(this);
                Player.LastMessageTime = DateTime.UtcNow;
                GameServer.AddPlayer(Player);

                // Send existing players' data to the new player
                SendExistingPlayersData();

                // Notify other players about the new player
                BroadcastNewPlayerData();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"{DateTime.Now} Exception in OnWsConnected: {e.Message}");
        }
    }

    public override void OnWsDisconnected()
    {
        Console.WriteLine($"{DateTime.Now} Game WebSocket session with Id {Id} disconnected!");
        GameServer.RemovePlayer(this);
        // Player removal is handled in GameServer.OnDisconnected
    }

    public override void OnWsReceived(byte[] buffer, long offset, long size)
    {
        try
        {
            // Ensure the buffer has at least one byte for the message code
            if (size < 1)
                return;

            var messageCode = buffer[offset];
            var messageData = new byte[size - 1];
            Array.Copy(buffer, offset + 1, messageData, 0, size - 1);
            Player.LastMessageTime = DateTime.UtcNow;
            switch (messageCode)
            {
                case MessageCodes.PositionMessage:
                    HandlePositionMessage(messageData);
                    break;

Does anyone have any clue what the problem might be?

I am using NetCoreServer version 8.0.7 on .NET 8.0.405 Debian.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions