Cleaning up request code (client side) master
authorhgn <hgodden00@gmail.com>
Thu, 10 Jul 2025 00:52:54 +0000 (01:52 +0100)
committerhgn <hgodden00@gmail.com>
Thu, 10 Jul 2025 00:52:54 +0000 (01:52 +0100)
src/network_msg.h
src/network_requests.c
src/network_requests.h
src/replay2.c

index 98161bbc9ee591ccda468d8d3d3305bf1f9f1139..2db62a41253f2ec7eca077cf6b2095a3d7f4e009 100644 (file)
@@ -135,16 +135,27 @@ struct netmsg_start_run{
 
 /* requests 300 */
 typedef struct netmsg_request netmsg_request;
+
+#if defined( REQUEST_V2 )
+enum{ k_inetmsg_request = 302, k_inetmsg_response = 303 };
+#else
 enum{ k_inetmsg_request = 300, k_inetmsg_response = 301 };
+#endif
 struct netmsg_request {
    u16 inetmsg_id;
    u8 id, status;
+#if defined( REQUEST_V2 )
+   u32 uid;
+#endif
    u8 buffer[];
 };
 
 struct netmsg_transfer_header 
 {
    u32 data_size, chunks;
+#if defined( REQUEST_V2 )
+   u32 uid;
+#endif
 };
 
 enum request_status {
index 1f0e8e8458072760138a13dcb535d2d29ccbb6e5..104f2aaf9a451c9bb29e6aec1e7df6dba5cac039 100644 (file)
@@ -78,6 +78,14 @@ void network_send_request( netmsg_request *packet, vg_msg *body,
    if( callback )
    {
       packet->id = vg_pool_lru( &_net_requests.request_pool );
+#if defined( REQUEST_V2 )
+      packet->uid = _net_requests.global_uid;
+      if( _net_requests.global_uid == 0xffffffff )
+         _net_requests.global_uid = 4;
+      else
+         _net_requests.global_uid ++;
+#endif
+
       if( packet->id )
       {
          vg_pool_watch( &_net_requests.request_pool, packet->id );
@@ -95,7 +103,12 @@ void network_send_request( netmsg_request *packet, vg_msg *body,
       }
    }
    else
+   {
       packet->id = 0;
+#if defined( REQUEST_V2 )
+      packet->uid = 0;
+#endif
+   }
 
    SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( _steam_api.pSteamNetworkingSockets, network_client.remote, 
                                                              packet, sizeof(netmsg_request)+len,
@@ -175,11 +188,20 @@ static void _delete_request( net_request *request )
    request->state = k_request_state_none;
 }
 
-static void _transfer_reset(void)
+static void _net_requests_degenerate( u8 request_id, const c8 *reason )
 {
-   _net_requests.recieving_request_id = 0;
-   _net_requests.recieve_offset = 0;
-   _net_requests.data_buffer_recieve_size = 0;
+   if( request_id != 0 )
+   {
+      net_request *request = vg_pool_item( &_net_requests.request_pool, request_id );
+      if( request->callback )
+         request->callback( NULL, 0, request->userdata, k_request_status_server_error );
+      request->state = k_request_state_error;
+      log_request_status( request, reason );
+      _delete_request( request );
+
+      if( request_id == _net_requests.transfer_request_id )
+         _net_requests.transfer_request_id = 0;
+   }
 }
 
 void _net_handle_response_message( SteamNetworkingMessage_t *msg )
@@ -189,117 +211,100 @@ void _net_handle_response_message( SteamNetworkingMessage_t *msg )
    if( (response->id == 0) || (response->id > NETWORK_MAX_REQUESTS) )
    {
       vg_error( "Response with invalid ID: %u.\n", response->id );
+      _net_requests_degenerate( _net_requests.transfer_request_id, 
+                                "Attempting to recover from stream error (Invalid request ID)\n" ); 
       return;
    }
 
    net_request *request = vg_pool_item( &_net_requests.request_pool, response->id );
    if( request->state == k_request_state_none )
    {
-      vg_error( "Response to inactive request (id %u)\n", response->id );
+      vg_error( "Bad request state\n" );
+      _net_requests_degenerate( _net_requests.transfer_request_id,
+                                "Attempting to recover from stream error (Bad request ID).\n" ); 
       return;
    }
 
    u32 byte_count = msg->m_cbSize - sizeof(netmsg_request);
-   if( response->status == k_request_status_ok )
-   {
-      request->state = k_request_state_finished;
-      log_request_status( request, "200" );
 
-      if( request->callback )
-         request->callback( response->buffer, byte_count, request->userdata, k_request_status_ok );
-      
-      vg_pool_unwatch( &_net_requests.request_pool, response->id );
-      request->state = k_request_state_none;
-   }
-   else if( response->status == k_request_status_transfer_header )
+   if( response->status == k_request_status_transfer_header )
    {
-      u8 old_id = _net_requests.recieving_request_id;
-      if( old_id )
-      {
-         net_request *old_request = vg_pool_item( &_net_requests.request_pool, old_id );
-         if( old_request->callback )
-            old_request->callback( NULL, 0, old_request->userdata, k_request_status_server_error );
-         old_request->state = k_request_state_error;
-         log_request_status( old_request, "Interrupted by new header" );
-         _delete_request( old_request );
-         _transfer_reset();
-      }
+      _net_requests_degenerate( _net_requests.transfer_request_id, "Interrupted\n" );
 
       struct netmsg_transfer_header *header = (void *)response->buffer;
-      if( header->data_size > 1024*1024*4 )
+      if( header->data_size > VG_MB(4) )
+         _net_requests_degenerate( response->id, "Header specified size too large (>4mb)" );
+      else
       {
-         if( request->callback )
-            request->callback( NULL, 0, request->userdata, k_request_status_out_of_memory );
-         request->state = k_request_state_error;
-         log_request_status( request, "Header specified size too large (>4mb)" );
-         _delete_request( request );
-         return;
+         _net_requests.transfer_request_id = response->id;
+#if defined( REQUEST_V2 )
+         _net_requests.transfer_uid = header->uid;
+#endif
+         _net_requests.transfer_expected_size = header->data_size;
+         _net_requests.transfer_recieved = 0;
+         _net_requests.transfer_timeout = TRANSFER_TIMEOUT_SECONDS;
+
+         request->state = k_request_state_receiving;
+         log_request_status( request, "New Transfer Header\n" );
       }
-
-      _transfer_reset();
-      _net_requests.recieving_request_id = response->id;
-      _net_requests.data_buffer_recieve_size = header->data_size;
-
-      request->state = k_request_state_receiving;
-      log_request_status( request, "Valid" );
    }
    else if( response->status == k_request_status_transfer_continue )
    {
-      u8 current_id = _net_requests.recieving_request_id;
-      if( current_id != response->id )
+      bool ids_match = 0;
+      if( _net_requests.transfer_request_id == response->id )
       {
-         if( current_id )
-         {
-            net_request *current = vg_pool_item( &_net_requests.request_pool, current_id );
-            if( current->callback )
-               current->callback( NULL, 0, current->userdata, k_request_status_server_error );
-            current->state = k_request_state_error;
-            log_request_status( current, "Transfer protocol fault" );
-            _delete_request( current );
-         }
-
-         if( request->callback )
-            request->callback( NULL, 0, request->userdata, k_request_status_server_error );
-         request->state = k_request_state_error;
-         log_request_status( request, "Transfer protocol fault" );
-         _delete_request( request );
-         _transfer_reset();
-         return;
+#if defined( REQUEST_V2 )
+         if( response->uid == _net_requests.transfer_uid )
+            ids_match = 1;
+#else
+         ids_match = 1;
+#endif
       }
 
-      bool end = 0;
-      if( _net_requests.recieve_offset + byte_count >= _net_requests.data_buffer_recieve_size )
+      if( ids_match )
       {
-         end = 1;
-         byte_count = _net_requests.data_buffer_recieve_size - _net_requests.recieve_offset;
-      }
-
-      memcpy( _net_requests.data_buffer + _net_requests.recieve_offset, response->buffer, byte_count );
-      _net_requests.recieve_offset += byte_count;
+         u32 new_size = _net_requests.transfer_recieved + byte_count;
+         if( new_size > _net_requests.transfer_expected_size )
+         {
+            _net_requests_degenerate( response->id, "Transfer exceeded declared size. Will not proceed using truncated data.\n" );
+            return;
+         }
 
-      if( end )
-      {
-         request->state = k_request_state_finished;
-         log_request_status( request, NULL );
+         memcpy( _net_requests.transfer_buffer + _net_requests.transfer_recieved, response->buffer, byte_count );
+         _net_requests.transfer_recieved += byte_count;
+         _net_requests.transfer_timeout = TRANSFER_TIMEOUT_SECONDS;
 
-         if( request->callback )
+         if( new_size == _net_requests.transfer_expected_size )
          {
-            request->callback( _net_requests.data_buffer, _net_requests.data_buffer_recieve_size, 
-                               request->userdata, k_request_status_ok );
+            _net_requests.transfer_request_id = 0;
+            request->state = k_request_state_finished;
+            log_request_status( request, "Transfer completed\n" );
+
+            if( request->callback )
+            {
+               request->callback( _net_requests.transfer_buffer, _net_requests.transfer_expected_size,
+                                  request->userdata, k_request_status_ok );
+            }
+            else
+               vg_warn( "Why are you requesting transfers, and then doing nothing with it?\n" );
+
+            _delete_request( request );
          }
-
-         _delete_request( request );
-         _transfer_reset();
+      }
+      else
+      {
+         /* Current transfer- we have to assume it was interrupted,
+          * New transfer- we have to assume broken because if it sent a header, it would have changed the transfer ID 
+          * correctly.
+          *
+          * Both get discarded.
+          */
+         _net_requests_degenerate( _net_requests.transfer_request_id, "Very broken stream\n" );
+         _net_requests_degenerate( response->id, "Very broken stream\n" );
       }
    }
    else
-   {
-      if( request->callback )
-         request->callback( NULL, 0, request->userdata, k_request_status_server_error );
-      request->state = k_request_state_error;
-      log_request_status( request, request_status_string(response->status) );
-      _delete_request( request );
-   }
+      _net_requests_degenerate( response->id, "Defined server Error\n" );
 }
 
 void _net_requests_init(void)
@@ -307,8 +312,8 @@ void _net_requests_init(void)
    u32 alloc_size = sizeof(net_request)*NETWORK_MAX_REQUESTS;
    _net_requests.request_buffer = vg_stack_allocate( &vg.rtmem, alloc_size, 8, "Request buffer" );
    memset( _net_requests.request_buffer, 0, alloc_size );
-
-   _net_requests.data_buffer = vg_stack_allocate( &vg.rtmem, VG_MB(4), 8, "Request data buffer" );
+   _net_requests.transfer_buffer = vg_stack_allocate( &vg.rtmem, VG_MB(4), 8, "Request transfer data buffer" );
+   _net_requests.global_uid = time(NULL) ^ 0x35aa3203;
 
    vg_pool *pool = &_net_requests.request_pool;
    pool->buffer = _net_requests.request_buffer;
@@ -321,9 +326,10 @@ void _net_requests_init(void)
 void _net_requests_reset(void)
 {
    /* return the infinity stones */
-   _net_requests.data_buffer_recieve_size = 0;
-   _net_requests.recieve_offset = 0;
-   _net_requests.recieving_request_id = 0;
+   _net_requests.transfer_request_id = 0;
+   _net_requests.transfer_expected_size = 0;
+   _net_requests.transfer_recieved = 0;
+   _net_requests.transfer_timeout = 0.0f;
    for( u32 i=0; i<NETWORK_MAX_REQUESTS; i ++ )
    {
       net_request *request = &_net_requests.request_buffer[ i ];
@@ -336,3 +342,13 @@ void _net_requests_reset(void)
       }
    }
 }
+
+void _net_requests_update(void)
+{
+   if( _net_requests.transfer_request_id )
+   {
+      _net_requests.transfer_timeout -= vg.time_frame_delta;
+      if( _net_requests.transfer_timeout < 0.0f )
+         _net_requests_degenerate( _net_requests.transfer_request_id, "Timed out.\n" );
+   }
+}
index e376ad1c889e1e06de293a9c7cc4f100662dc250..fbb7476a0da8198887218addbfe8465647fafdcb 100644 (file)
@@ -1,5 +1,6 @@
 #pragma once
 #include "network.h"
+#define TRANSFER_TIMEOUT_SECONDS 5.0f
 
 typedef struct net_request net_request;
 struct net_request 
@@ -26,10 +27,14 @@ struct _net_requests
    net_request *request_buffer;
    vg_pool request_pool;
 
-   void *data_buffer;
-   u32 data_buffer_recieve_size;
-   u32 recieve_offset;
-   u8  recieving_request_id;
+   void *transfer_buffer;
+   u8  transfer_request_id;
+   u32 transfer_expected_size;
+   u32 transfer_recieved;
+   u32 transfer_uid;
+   f32 transfer_timeout;
+
+   u32 global_uid;
 }
 extern _net_requests;
 
index e0a6959117ab3d4edc0d81ddfb6b8deb29ceef44..9ff3302364c28eee7bd9fda25611057792439e3e 100644 (file)
@@ -830,6 +830,21 @@ void _replay2_imgui( ui_context *ctx )
             {
                if( i < _remote_replay.chunks_downloaded )
                   ui_fill( ctx, chunkbox, ui_colour( ctx, k_ui_fg ) );
+               else if( i == _remote_replay.chunks_downloaded )
+               {
+                  ui_outline( ctx, chunkbox, -2, ui_colour( ctx, k_ui_fg+2 ), 0 );
+
+                  if( _net_requests.transfer_expected_size )
+                  {
+                     f32 progress = (f32)_net_requests.transfer_recieved / (f32)_net_requests.transfer_expected_size;
+
+                     ui_rect inner;
+                     rect_copy( chunkbox, inner );
+                     inner[2] = (f32)inner[2] * progress;
+                     if( inner[2] > 0 )
+                        ui_fill( ctx, inner, ui_colour( ctx, k_ui_fg ) );
+                  }
+               }
                else
                   ui_outline( ctx, chunkbox, -2, ui_colour( ctx, k_ui_fg+2 ), 0 );
             }