inline void packet_data_insert_sorted(NetworkState *net, PacketData *queue, u32 max_sequence, u32 sequence, f32 time, i32 size) { if (packet_data_empty(queue)) { packet_data_insert_before(net, queue, sequence, time, size); } else { if (!sequence_more_recent(sequence, queue->next->sequence, max_sequence)) { packet_data_insert_before(net, queue->next, sequence, time, size); } else if (sequence_more_recent(sequence, queue->prev->sequence, max_sequence)) { packet_data_insert_before(net, queue, sequence, time, size); } else { for (PacketData *node = queue->next; node != queue; node = node->next) { assert(node->sequence != sequence); if (sequence_more_recent(node->sequence, sequence, max_sequence)) { packet_data_insert_before(net, node, sequence, time, size); break; } } } } }
void PacketQueue::insert_sorted( const PacketData & p, unsigned int max_sequence ) { if ( empty() ) { push_back( p ); } else { if ( !sequence_more_recent( p.sequence, front().sequence, max_sequence ) ) { push_front( p ); } else if ( sequence_more_recent( p.sequence, back().sequence, max_sequence ) ) { push_back( p ); } else { for ( PacketQueue::iterator itor = begin(); itor != end(); itor++ ) { assert( itor->sequence != p.sequence ); if ( sequence_more_recent( itor->sequence, p.sequence, max_sequence ) ) { insert( itor, p ); break; } } } } }
void ReliabilitySystem::updateQueues() { const float epsilon = 0.001f; while ( sentQueue.size() && sentQueue.front().time > rtt_maximum + epsilon ) { sentQueue.pop_front(); } if ( receivedQueue.size() ) { const unsigned int latest_sequence = receivedQueue.back().sequence; const unsigned int minimum_sequence = latest_sequence >= 34 ? ( latest_sequence - 34 ) : max_sequence - ( 34 - latest_sequence ); while ( receivedQueue.size() && !sequence_more_recent( receivedQueue.front().sequence, minimum_sequence, max_sequence ) ) receivedQueue.pop_front(); } while ( ackedQueue.size() && ackedQueue.front().time > rtt_maximum * 2 - epsilon ) { ackedQueue.pop_front(); } while ( pendingAckQueue.size() && pendingAckQueue.front().time > rtt_maximum + epsilon ) { pendingAckQueue.pop_front(); lost_packets++; } }
void ReliabilitySystem::process_ack( unsigned int ack, unsigned int ack_bits, PacketQueue & pending_ack_queue, PacketQueue & acked_queue, std::vector<unsigned int> & acks, unsigned int & acked_packets, float & rtt, unsigned int max_sequence ) { if ( pending_ack_queue.empty() ) { return; } PacketQueue::iterator itor = pending_ack_queue.begin(); while ( itor != pending_ack_queue.end() ) { bool acked = false; if ( itor->sequence == ack ) { acked = true; } else if ( !sequence_more_recent( itor->sequence, ack, max_sequence ) ) { int bit_index = bit_index_for_sequence( itor->sequence, ack, max_sequence ); if ( bit_index <= 31 ) { acked = ( ack_bits >> bit_index ) & 1; } }
void ReliabilitySystem::process_ack(unsigned int ack, unsigned int ack_bits, PacketQueue & pending_ack_queue, PacketQueue & acked_queue, std::vector<unsigned int> & acks, unsigned int & acked_packets, float & rtt, unsigned int max_sequence) { if (pending_ack_queue.empty()) return; PacketQueue::iterator itor = pending_ack_queue.begin(); while (itor != pending_ack_queue.end()) { bool acked = false; if (itor->sequence == ack) { acked = true; } else if (!sequence_more_recent(itor->sequence, ack, max_sequence)) { int bit_index = bit_index_for_sequence(itor->sequence, ack, max_sequence); if (bit_index <= 31) acked = (ack_bits >> bit_index) & 1; } if (acked) { rtt += (itor->time - rtt) * 0.1f; acked_queue.insert_sorted(*itor, max_sequence); acks.push_back(itor->sequence); acked_packets++; itor = pending_ack_queue.erase(itor); } else { ++itor; } }
void PacketQueue::verify_sorted( quint32 max_sequence ){ PacketQueue::iterator prev = end(); for ( PacketQueue::iterator itor = begin(); itor != end(); itor++ ){ assert( itor->sequence <= max_sequence ); if ( prev != end() ){ assert( sequence_more_recent( itor->sequence, prev->sequence, max_sequence ) ); prev = itor; } } }
inline void packet_data_verify_sorted(PacketData *queue, u32 max_sequence) { for (PacketData *node = queue->next; node != queue; node = node->next) { assert(node->sequence <= max_sequence); if (node->prev != queue) { assert(sequence_more_recent(node->sequence, node->prev->sequence, max_sequence)); } } }
unsigned int ReliabilitySystem::generate_ack_bits(unsigned int ack, const PacketQueue & received_queue, unsigned int max_sequence) { unsigned int ack_bits = 0; for (PacketQueue::const_iterator itor = received_queue.begin(); itor != received_queue.end(); itor++) { if (itor->sequence == ack || sequence_more_recent(itor->sequence, ack, max_sequence)) break; int bit_index = bit_index_for_sequence(itor->sequence, ack, max_sequence); if (bit_index <= 31) ack_bits |= 1 << bit_index; } return ack_bits; }
void ReliabilitySystem::PacketReceived(unsigned int sequence, int size) { FunctionLock lock(thisLock); recv_packets++; if (receivedQueue.exists(sequence)) return; PacketData data; data.sequence = sequence; data.time = 0.0f; data.size = size; receivedQueue.push_back(data); if (sequence_more_recent(sequence, remote_sequence, max_sequence)) remote_sequence = sequence; }
// TODOCM maybe change from uint8 to bigger value for bigger chains static int16_t sequence_difference(uint8_t s1, uint8_t s2, unsigned int max) { // If s1 is larger and the difference is less then half // meaning if they're not wrapped, the differnce should be less then half for it to be more recent // or // If s2 is the larger one, and their difference is larger then half // meaning if they're wrapped, the difference should be more then half for it to be wrapped if(s1 > s2) { if(sequence_more_recent(s1, s2, max)) { return s1 - s2; } else { return -(max - s1 + s2 + 1); } } else if(s2 > s1) // TODOCM check if this really is right { if(sequence_more_recent(s1, s2, max)) { return max + 1 - s2 + s1; } else { return s1 - s2; } } else { // std::cout << "Snapshot sequence is same, something is wrong" << std::endl; // TODOCM remove maybe return 0; } }
int ReliabilitySystem::bit_index_for_sequence(unsigned int sequence, unsigned int ack, unsigned int max_sequence) { assert(sequence != ack); assert(!sequence_more_recent(sequence, ack, max_sequence)); if (sequence > ack) { //TODO: This fails because too many physics updates per tick //if (ack >= 33) // assert(ack < 33); if (max_sequence < sequence) assert(max_sequence >= sequence); return ack + (max_sequence - sequence); } else { assert(ack >= 1); assert(sequence <= ack - 1); return ack - 1 - sequence; } }
int ReliabilitySystem::bit_index_for_sequence( unsigned int sequence, unsigned int ack, unsigned int max_sequence ) { assert( sequence != ack ); assert( !sequence_more_recent( sequence, ack, max_sequence ) ); if ( sequence > ack ) { assert( ack < 33 ); assert( max_sequence >= sequence ); return ack + ( max_sequence - sequence ); } else { assert( ack >= 1 ); assert( sequence <= ack - 1 ); return ack - 1 - sequence; } }
static u32 generate_ack_bits(u32 ack, PacketData *recv_queue, u32 max_sequence) { u32 ack_bits = 0; for (PacketData *node = recv_queue->next; node != recv_queue; node = node->next) { if (node->sequence == ack || sequence_more_recent(node->sequence, ack, max_sequence)) { break; } i32 bit_index = bit_index_for_sequence(node->sequence, ack, max_sequence); if (bit_index <= 31) { ack_bits |= 1 << bit_index; } } return ack_bits; }
static void process_ack(NetworkState *net, u32 ack, u32 ack_bits) { if (!packet_data_empty(net->pending_ack_queue)) { PacketData *node = net->pending_ack_queue->next; while (node != net->pending_ack_queue) { b32 acked = false; if (node->sequence == ack) { acked = true; } else if (!sequence_more_recent(node->sequence, ack, net->max_sequence)) { i32 bit_index = bit_index_for_sequence(node->sequence, ack, net->max_sequence); if (bit_index <= 31) { acked = (ack_bits >> bit_index) & 1; } }
static i32 bit_index_for_sequence(u32 sequence, u32 ack, u32 max_sequence) { assert(sequence != ack); assert(!sequence_more_recent(sequence, ack, max_sequence)); i32 result = 0; if (sequence > ack) { assert(ack < 33); assert(max_sequence >= sequence); result = ack + (max_sequence - sequence); } else { assert(ack >= 1); assert(sequence <= (ack - 1)); result = ack - 1 - sequence; } return result; }
static void update_connection(NetworkState *net, Connection *connection, f32 dt) { // NOTE(dan): clear acks array net->num_acks = 0; // NOTE(dan): update connection { connection->timeout_accum += dt; if (connection->timeout_accum > connection->timeout_sec) { if (connection->state == ConnectionState_Connecting || connection->state == ConnectionState_Connected) { connection->state = ConnectionState_ConnectionFailed; } } } // NOTE(dan): advance queue time { for (PacketData *node = net->sent_queue->next; node != net->sent_queue; node = node->next) { node->time += dt; } for (PacketData *node = net->recv_queue->next; node != net->recv_queue; node = node->next) { node->time += dt; } for (PacketData *node = net->pending_ack_queue->next; node != net->pending_ack_queue; node = node->next) { node->time += dt; } for (PacketData *node = net->acked_queue->next; node != net->acked_queue; node = node->next) { node->time += dt; } } // NOTE(dan): update queues { f32 epsilon = 0.001f; while (!packet_data_empty(net->sent_queue) && (net->sent_queue->next->time > (net->max_rtt + epsilon))) { packet_data_delete_node(net, net->sent_queue->next); } if (!packet_data_empty(net->recv_queue)) { u32 latest_sequence = net->recv_queue->prev->sequence; u32 min_sequence = latest_sequence >= 34 ? (latest_sequence - 34) : net->max_sequence - (34 - latest_sequence); while (!packet_data_empty(net->recv_queue) && !sequence_more_recent(net->recv_queue->next->sequence, min_sequence, net->max_sequence)) { packet_data_delete_node(net, net->recv_queue->next); } } while (!packet_data_empty(net->acked_queue) && (net->acked_queue->next->time > (net->max_rtt * 2 - epsilon))) { packet_data_delete_node(net, net->acked_queue->next); } while (!packet_data_empty(net->pending_ack_queue) && (net->pending_ack_queue->next->time > (net->max_rtt + epsilon))) { packet_data_delete_node(net, net->pending_ack_queue->next); ++net->lost_packets; } } // NOTE(dan): update stats { i32 sent_bytes_per_sec = 0; i32 acked_packets_per_sec = 0; i32 acked_bytes_per_sec = 0; for (PacketData *node = net->sent_queue->next; node != net->sent_queue; node = node->next) { sent_bytes_per_sec += node->size; } for (PacketData *node = net->acked_queue->next; node != net->acked_queue; node = node->next) { if (node->time >= net->max_rtt) { ++acked_packets_per_sec; acked_bytes_per_sec += node->size; } } sent_bytes_per_sec = (i32)(sent_bytes_per_sec / net->max_rtt); acked_bytes_per_sec = (i32)(acked_bytes_per_sec / net->max_rtt); net->sent_bandwidth = sent_bytes_per_sec * (8 / 1000.0f); net->acked_bandwidth = acked_bytes_per_sec * (8 / 1000.0f); } // NOTE(dan): validate #if INTERNAL_BUILD { packet_data_verify_sorted(net->sent_queue, net->max_sequence); // packet_data_verify_sorted(net->recv_queue, net->max_sequence); packet_data_verify_sorted(net->pending_ack_queue, net->max_sequence); packet_data_verify_sorted(net->acked_queue, net->max_sequence); } #endif }
void NetworkEventReceiver::ReadEvents(NetworkStreamer& p_streamer, uint32_t p_bufferSize, uint32_t& op_BytesRead) { // Get header size uint32_t t_headerSize = sizeof(uint8_t) * 2; // Check how many bytes we have left to write uint32_t bytesLeftToRead = p_bufferSize - op_BytesRead; // Check if we can read headers if(bytesLeftToRead < t_headerSize) { return; } // Read number of sequences packets uint8_t NumOfSequencesLeft = p_streamer.ReadUnsignedInt8(); bytesLeftToRead -= sizeof(uint8_t); op_BytesRead += sizeof(uint8_t); // Read starting sequence uint8_t CurrentSequence = p_streamer.ReadUnsignedInt8(); bytesLeftToRead -= sizeof(uint8_t); op_BytesRead += sizeof(uint8_t); // While we still got sequences to read, and already have them, we skip to use while(NumOfSequencesLeft && sequence_more_recent(m_currentSequence, CurrentSequence, 255)) { // Increment how many we read, and how many that are left CurrentSequence++; NumOfSequencesLeft--; uint32_t t_bitsRead = 0; // If we don't have enough memory to read next line if(bytesLeftToRead < sizeof(uint8_t)) { return; } // Interpet events and throw InterpetEventAndThrow(p_streamer, t_bitsRead); // Get full bytes read uint32_t t_FullBytesRead = ceil((float)t_bitsRead / 8.0f); bytesLeftToRead -= t_FullBytesRead; op_BytesRead += t_FullBytesRead; // Set read point p_streamer.SetReadWritePosition(op_BytesRead); } // Increment by how many we should read, could move this for each we read instead m_currentSequence += NumOfSequencesLeft; // While we still have sequences left to read while(NumOfSequencesLeft) { uint32_t t_bitsRead = 0; // If we don't have enough memory to read next line if(bytesLeftToRead < sizeof(uint8_t)) { return; } // Interpet events and save InterpetEventAndQueue(p_streamer, t_bitsRead); // Get full bytes read uint32_t t_FullBytesRead = ceil((float)t_bitsRead / 8.0f); bytesLeftToRead -= t_FullBytesRead; op_BytesRead += t_FullBytesRead; // Set read point p_streamer.SetReadWritePosition(op_BytesRead); // Decrement counter NumOfSequencesLeft--; } }