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 );
}
}
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,
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 )
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)
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;
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 ];
}
}
}
+
+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" );
+ }
+}