Skip to content

Commit

Permalink
add some safety asserts to help catch when MaxClients is set too low …
Browse files Browse the repository at this point in the history
…for tests, channelIndex
  • Loading branch information
gafferongames committed Aug 30, 2024
1 parent c6c02df commit c006f71
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 28 deletions.
3 changes: 2 additions & 1 deletion include/yojimbo_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ namespace yojimbo

ConnectionConfig()
{
numChannels = 1;
numChannels = 2;
maxPacketSize = 8 * 1024;
channel[0].type = CHANNEL_TYPE_RELIABLE_ORDERED;
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/yojimbo_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace yojimbo
{
const int MaxClients = 64; ///< The maximum number of clients supported by this library. You can increase this if you want, but this library is designed around patterns that work best for [2,64] player games. If your game has less than 64 clients, reducing this will save memory.

const int MaxChannels = 64; ///< The maximum number of message channels supported by this library. If you need less than 64 channels per-packet, reducing this will save memory.
const int MaxChannels = 2; ///< The maximum number of message channels supported by this library. If you need less than 64 channels per-packet, reducing this will save memory.

const int KeyBytes = 32; ///< Size of encryption key for dedicated client/server in bytes. Must be equal to key size for libsodium encryption primitive. Do not change.

Expand Down
6 changes: 5 additions & 1 deletion include/yojimbo_network_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ namespace yojimbo

struct NetworkInfo
{
float RTT; ///< Round trip time estimate (milliseconds).
float RTT; ///< Round trip time estimate (milliseconds). Exponentially smoothed average tracking most recent RTT value.
float minRTT; ///< Minimum RTT seen over the last n samples (see rtt_history_size in reliable config). This is a more stable and accurate RTT value under typical Wi-Fi jitter.
float maxRTT; ///< Maximum RTT seen over the last n samples.
float averageRTT; ///< Average RTT seen over the last n samples.
float jitter; ///< Jitter relative to min RTT over the last n samples.
float packetLoss; ///< Packet loss percent.
float sentBandwidth; ///< Sent bandwidth (kbps).
float receivedBandwidth; ///< Received bandwidth (kbps).
Expand Down
120 changes: 114 additions & 6 deletions reliable/reliable.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,13 +508,18 @@ struct reliable_endpoint_t
struct reliable_config_t config;
double time;
float rtt;
float rtt_min;
float rtt_max;
float rtt_avg;
float jitter;
float packet_loss;
float sent_bandwidth_kbps;
float received_bandwidth_kbps;
float acked_bandwidth_kbps;
int num_acks;
uint16_t * acks;
uint16_t sequence;
float * rtt_history_buffer;
struct reliable_sequence_buffer_t * sent_packets;
struct reliable_sequence_buffer_t * received_packets;
struct reliable_sequence_buffer_t * fragment_reassembly;
Expand Down Expand Up @@ -556,9 +561,10 @@ void reliable_default_config( struct reliable_config_t * config )
config->received_packets_buffer_size = 256;
config->fragment_reassembly_buffer_size = 64;
config->rtt_smoothing_factor = 0.0025f;
config->rtt_history_size = 512;
config->packet_loss_smoothing_factor = 0.1f;
config->bandwidth_smoothing_factor = 0.1f;
config->packet_header_size = 28; // note: UDP over IPv4 = 20 + 8 bytes, UDP over IPv6 = 40 + 8 bytes
config->packet_header_size = 28; // note: UDP over IPv4 = 20 + 8 bytes, UDP over IPv6 = 40 + 8 bytes
}

struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t * config, double time )
Expand All @@ -574,6 +580,7 @@ struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t
reliable_assert( config->received_packets_buffer_size > 0 );
reliable_assert( config->transmit_packet_function != NULL );
reliable_assert( config->process_packet_function != NULL );
reliable_assert( config->rtt_history_size > 0 );

void * allocator_context = config->allocator_context;
void * (*allocate_function)(void*,size_t) = config->allocate_function;
Expand Down Expand Up @@ -601,7 +608,7 @@ struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t
endpoint->config = *config;
endpoint->time = time;

endpoint->acks = (uint16_t*) allocate_function( allocator_context, config->ack_buffer_size * sizeof( uint16_t ) );
endpoint->acks = (uint16_t*) allocate_function( allocator_context, config->ack_buffer_size * sizeof(uint16_t) );

endpoint->sent_packets = reliable_sequence_buffer_create( config->sent_packets_buffer_size,
sizeof( struct reliable_sent_packet_data_t ),
Expand All @@ -621,7 +628,14 @@ struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t
allocate_function,
free_function );

memset( endpoint->acks, 0, config->ack_buffer_size * sizeof( uint16_t ) );
endpoint->rtt_history_buffer = (float*) allocate_function( allocator_context, config->rtt_history_size * sizeof(float) );

for ( int i = 0; i < config->rtt_history_size; i++ )
{
endpoint->rtt_history_buffer[i] = -1.0f;
}

memset( endpoint->acks, 0, config->ack_buffer_size * sizeof(uint16_t) );

return endpoint;
}
Expand All @@ -632,6 +646,8 @@ void reliable_endpoint_destroy( struct reliable_endpoint_t * endpoint )
reliable_assert( endpoint->acks );
reliable_assert( endpoint->sent_packets );
reliable_assert( endpoint->received_packets );
reliable_assert( endpoint->fragment_reassembly );
reliable_assert( endpoint->rtt_history_buffer );

int i;
for ( i = 0; i < endpoint->config.fragment_reassembly_buffer_size; ++i )
Expand All @@ -652,6 +668,8 @@ void reliable_endpoint_destroy( struct reliable_endpoint_t * endpoint )
reliable_sequence_buffer_destroy( endpoint->received_packets );
reliable_sequence_buffer_destroy( endpoint->fragment_reassembly );

endpoint->free_function( endpoint->allocator_context, endpoint->rtt_history_buffer );

endpoint->free_function( endpoint->allocator_context, endpoint );
}

Expand Down Expand Up @@ -1141,8 +1159,14 @@ void reliable_endpoint_receive_packet( struct reliable_endpoint_t * endpoint, ui
endpoint->counters[RELIABLE_ENDPOINT_COUNTER_NUM_PACKETS_ACKED]++;
sent_packet_data->acked = 1;

float rtt = (float) ( endpoint->time - sent_packet_data->time ) * 1000.0f;
const float rtt = (float) ( endpoint->time - sent_packet_data->time ) * 1000.0f;

reliable_assert( rtt >= 0.0 );

int index = ack_sequence % endpoint->config.rtt_history_size;

endpoint->rtt_history_buffer[index] = rtt;

if ( ( endpoint->rtt == 0.0f && rtt > 0.0f ) || fabs( endpoint->rtt - rtt ) < 0.00001 )
{
endpoint->rtt = rtt;
Expand Down Expand Up @@ -1320,7 +1344,67 @@ void reliable_endpoint_update( struct reliable_endpoint_t * endpoint, double tim
reliable_assert( endpoint );

endpoint->time = time;


// calculate min and max rtt
{
float min_rtt = 10000.0f;
float max_rtt = 0.0f;
float sum_rtt = 0.0f;
int count = 0;
for ( int i = 0; i < endpoint->config.rtt_history_size; i++ )
{
const float rtt = endpoint->rtt_history_buffer[i];
if ( rtt >= 0.0f )
{
if ( rtt < min_rtt )
{
min_rtt = rtt;
}
if ( rtt > max_rtt )
{
max_rtt = rtt;
}
sum_rtt += rtt;
count++;
}
}
if ( min_rtt == 10000.0f )
{
min_rtt = 0.0f;
}
endpoint->rtt_min = min_rtt;
endpoint->rtt_max = max_rtt;
if ( count > 0 )
{
endpoint->rtt_avg = sum_rtt / (float)count;
}
else
{
endpoint->rtt_avg = 0.0f;
}
}

// calculate jitter
{
float sum = 0.0f;
int count = 0;
for ( int i = 0; i < endpoint->config.rtt_history_size; i++ )
{
if ( endpoint->rtt_history_buffer[i] >= 0.0f )
{
sum += endpoint->rtt_history_buffer[i];
}
}
if ( count > 0 )
{
endpoint->jitter = sum / (float)count;
}
else
{
endpoint->jitter = 0.0f;
}
}

// calculate packet loss
{
uint32_t base_sequence = ( endpoint->sent_packets->sequence - endpoint->config.sent_packets_buffer_size + 1 ) + 0xFFFF;
Expand Down Expand Up @@ -1478,6 +1562,30 @@ float reliable_endpoint_rtt( struct reliable_endpoint_t * endpoint )
return endpoint->rtt;
}

float reliable_endpoint_rtt_min( struct reliable_endpoint_t * endpoint )
{
reliable_assert( endpoint );
return endpoint->rtt_min;
}

float reliable_endpoint_rtt_max( struct reliable_endpoint_t * endpoint )
{
reliable_assert( endpoint );
return endpoint->rtt_max;
}

float reliable_endpoint_rtt_avg( struct reliable_endpoint_t * endpoint )
{
reliable_assert( endpoint );
return endpoint->rtt_avg;
}

float reliable_endpoint_jitter( struct reliable_endpoint_t * endpoint )
{
reliable_assert( endpoint );
return endpoint->jitter;
}

float reliable_endpoint_packet_loss( struct reliable_endpoint_t * endpoint )
{
reliable_assert( endpoint );
Expand Down Expand Up @@ -2382,7 +2490,7 @@ void test_fragment_cleanup()

void reliable_test()
{
//while ( 1 )
// while ( 1 )
{
RUN_TEST( test_endian );
RUN_TEST( test_sequence_buffer );
Expand Down
11 changes: 10 additions & 1 deletion reliable/reliable.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
#define RELIABLE_ENDPOINT_NUM_COUNTERS 10

#define RELIABLE_MAX_PACKET_HEADER_BYTES 9
#define RELIABLE_FRAGMENT_HEADER_BYTES 5
#define RELIABLE_FRAGMENT_HEADER_BYTES 5

#define RELIABLE_LOG_LEVEL_NONE 0
#define RELIABLE_LOG_LEVEL_ERROR 1
Expand Down Expand Up @@ -107,6 +107,7 @@ struct reliable_config_t
int received_packets_buffer_size;
int fragment_reassembly_buffer_size;
float rtt_smoothing_factor;
int rtt_history_size;
float packet_loss_smoothing_factor;
float bandwidth_smoothing_factor;
int packet_header_size;
Expand Down Expand Up @@ -139,6 +140,14 @@ void reliable_endpoint_update( struct reliable_endpoint_t * endpoint, double tim

float reliable_endpoint_rtt( struct reliable_endpoint_t * endpoint );

float reliable_endpoint_rtt_min( struct reliable_endpoint_t * endpoint );

float reliable_endpoint_rtt_max( struct reliable_endpoint_t * endpoint );

float reliable_endpoint_rtt_avg( struct reliable_endpoint_t * endpoint );

float reliable_endpoint_jitter( struct reliable_endpoint_t * endpoint );

float reliable_endpoint_packet_loss( struct reliable_endpoint_t * endpoint );

void reliable_endpoint_bandwidth( struct reliable_endpoint_t * endpoint, float * sent_bandwidth_kbps, float * received_bandwidth_kbps, float * acked_bandwidth_kpbs );
Expand Down
12 changes: 12 additions & 0 deletions source/yojimbo_base_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,24 +235,32 @@ namespace yojimbo
bool BaseClient::CanSendMessage( int channelIndex ) const
{
yojimbo_assert( m_connection );
yojimbo_assert( channelIndex >= 0 );
yojimbo_assert( channelIndex < m_config.numChannels );
return m_connection->CanSendMessage( channelIndex );
}

bool BaseClient::HasMessagesToSend( int channelIndex ) const
{
yojimbo_assert( m_connection );
yojimbo_assert( channelIndex >= 0 );
yojimbo_assert( channelIndex < m_config.numChannels );
return m_connection->HasMessagesToSend( channelIndex );
}

void BaseClient::SendMessage( int channelIndex, Message * message )
{
yojimbo_assert( m_connection );
yojimbo_assert( channelIndex >= 0 );
yojimbo_assert( channelIndex < m_config.numChannels );
m_connection->SendMessage( channelIndex, message, GetContext() );
}

Message * BaseClient::ReceiveMessage( int channelIndex )
{
yojimbo_assert( m_connection );
yojimbo_assert( channelIndex >= 0 );
yojimbo_assert( channelIndex < m_config.numChannels );
return m_connection->ReceiveMessage( channelIndex );
}

Expand All @@ -273,6 +281,10 @@ namespace yojimbo
info.numPacketsReceived = counters[RELIABLE_ENDPOINT_COUNTER_NUM_PACKETS_RECEIVED];
info.numPacketsAcked = counters[RELIABLE_ENDPOINT_COUNTER_NUM_PACKETS_ACKED];
info.RTT = reliable_endpoint_rtt( m_endpoint );
info.minRTT = reliable_endpoint_rtt_min( m_endpoint );
info.maxRTT = reliable_endpoint_rtt_min( m_endpoint );
info.averageRTT = reliable_endpoint_rtt_avg( m_endpoint );
info.jitter = reliable_endpoint_jitter( m_endpoint );
info.packetLoss = reliable_endpoint_packet_loss( m_endpoint );
reliable_endpoint_bandwidth( m_endpoint, &info.sentBandwidth, &info.receivedBandwidth, &info.ackedBandwidth );
}
Expand Down
Loading

0 comments on commit c006f71

Please sign in to comment.