// discard working packet, now processing next packet in queue bool network_update( void ) { if (packet_in[0]) { packets_shift_up(packet_in, NET_PACKET_QUEUE); queue_in_sync++; return true; } return false; }
// discard working packet, now processing next packet in queue bool network_update( void ) { #ifdef __BLACKBERRY__ return true; #else if (packet_in[0]) { packets_shift_up(packet_in, NET_PACKET_QUEUE); queue_in_sync++; return true; } return false; #endif }
// receive state packet, wait until received bool network_state_update( void ) { #ifdef __BLACKBERRY__ return false; #else if (network_state_is_reset()) { return 0; } else { packets_shift_up(packet_state_in, NET_PACKET_QUEUE); packets_shift_up(packet_state_in_xor, NET_PACKET_QUEUE); last_state_in_sync++; // current xor packet index int x = network_delay - (last_state_in_sync - 1) % network_delay - 1; // loop until needed packet is available while (!packet_state_in[0]) { // xor the packet from thin air, if possible if (packet_state_in_xor[x] && SDLNet_Read16(&packet_state_in_xor[x]->data[0]) == PACKET_STATE_XOR) { // check for all other required packets bool okay = true; for (int i = 1; i <= x; i++) { if (packet_state_in[i] == NULL) { okay = false; break; } } if (okay) { packet_state_in[0] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_state_in[0], packet_state_in_xor[x]); for (int i = 1; i <= x; i++) for (int j = 4; j < packet_state_in[0]->len; j++) packet_state_in[0]->data[j] ^= packet_state_in[i]->data[j]; break; } } static Uint32 resend_tick = 0; if (SDL_GetTicks() - last_state_in_tick > NET_RESEND && SDL_GetTicks() - resend_tick > NET_RESEND) { SDLNet_Write16(PACKET_STATE_RESEND, &packet_out_temp->data[0]); SDLNet_Write16(last_state_in_sync - 1, &packet_out_temp->data[2]); network_send_no_ack(4); // PACKET_RESEND resend_tick = SDL_GetTicks(); } if (network_check() == 0) SDL_Delay(1); } if (network_delay > 1) { // process the current in packet against the xor queue if (packet_state_in_xor[x] == NULL) { packet_state_in_xor[x] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_state_in_xor[x], packet_state_in[0]); packet_state_in_xor[x]->status = 0; } else { for (int j = 4; j < packet_state_in_xor[x]->len; j++) packet_state_in_xor[x]->data[j] ^= packet_state_in[0]->data[j]; } } last_state_in_tick = SDL_GetTicks(); } return 1; #endif }
// poll for new packets received, check that connection is alive, resend queued packets if necessary int network_check( void ) { #ifdef __BLACKBERRY__ #else if (!net_initialized) return -1; if (connected) { // timeout if (!network_is_alive()) { if (!quit) network_tyrian_halt(2, false); } // keep-alive static Uint32 keep_alive_tick = 0; if (SDL_GetTicks() - keep_alive_tick > NET_KEEP_ALIVE) { network_prepare(PACKET_KEEP_ALIVE); network_send_no_ack(4); keep_alive_tick = SDL_GetTicks(); } } // retry if (packet_out[0] && SDL_GetTicks() - last_out_tick > NET_RETRY) { if (!SDLNet_UDP_Send(socket, 0, packet_out[0])) { printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); return -1; } last_out_tick = SDL_GetTicks(); } switch (SDLNet_UDP_Recv(socket, packet_temp)) { case -1: printf("SDLNet_UDP_Recv: %s\n", SDL_GetError()); return -1; break; case 0: break; default: if (packet_temp->channel == 0 && packet_temp->len >= 4) { switch (SDLNet_Read16(&packet_temp->data[0])) { case PACKET_ACKNOWLEDGE: if ((Uint16)(SDLNet_Read16(&packet_temp->data[2]) - last_ack_sync) < NET_PACKET_QUEUE) { last_ack_sync = SDLNet_Read16(&packet_temp->data[2]); } { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_out_sync; if (i < NET_PACKET_QUEUE) { if (packet_out[i]) { SDLNet_FreePacket(packet_out[i]); packet_out[i] = NULL; } } } // remove acknowledged packets from queue while (packet_out[0] == NULL && (Uint16)(last_ack_sync - queue_out_sync) < NET_PACKET_QUEUE) { packets_shift_up(packet_out, NET_PACKET_QUEUE); queue_out_sync++; } last_in_tick = SDL_GetTicks(); break; case PACKET_CONNECT: queue_in_sync = SDLNet_Read16(&packet_temp->data[2]); for (int i = 0; i < NET_PACKET_QUEUE; i++) { if (packet_in[i]) { SDLNet_FreePacket(packet_in[i]); packet_in[i] = NULL; } } case PACKET_DETAILS: case PACKET_WAITING: case PACKET_BUSY: case PACKET_GAME_QUIT: case PACKET_GAME_PAUSE: case PACKET_GAME_MENU: { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_in_sync; if (i < NET_PACKET_QUEUE) { if (packet_in[i] == NULL) packet_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_in[i], packet_temp); } else { // inbound packet queue overflow/underflow // under normal circumstances, this is okay } } network_acknowledge(SDLNet_Read16(&packet_temp->data[2])); case PACKET_KEEP_ALIVE: last_in_tick = SDL_GetTicks(); break; case PACKET_QUIT: if (!quit) { network_prepare(PACKET_QUIT); network_send(4); // PACKET_QUIT } network_acknowledge(SDLNet_Read16(&packet_temp->data[2])); if (!quit) network_tyrian_halt(1, true); break; case PACKET_STATE: // place packet in queue if within limits { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1; if (i < NET_PACKET_QUEUE) { if (packet_state_in[i] == NULL) packet_state_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_state_in[i], packet_temp); } } break; case PACKET_STATE_XOR: // place packet in queue if within limits { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1; if (i < NET_PACKET_QUEUE) { if (packet_state_in_xor[i] == NULL) { packet_state_in_xor[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_state_in_xor[i], packet_temp); } else if (SDLNet_Read16(&packet_state_in_xor[i]->data[0]) != PACKET_STATE_XOR) { for (int j = 4; j < packet_state_in_xor[i]->len; j++) packet_state_in_xor[i]->data[j] ^= packet_temp->data[j]; SDLNet_Write16(PACKET_STATE_XOR, &packet_state_in_xor[i]->data[0]); } } } break; case PACKET_STATE_RESEND: // resend requested state packet if still available { Uint16 i = last_state_out_sync - SDLNet_Read16(&packet_temp->data[2]); if (i > 0 && i < NET_PACKET_QUEUE) { if (packet_state_out[i]) { if (!SDLNet_UDP_Send(socket, 0, packet_state_out[i])) { printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); return -1; } } } } break; default: fprintf(stderr, "warning: bad packet %d received\n", SDLNet_Read16(&packet_temp->data[0])); return 0; break; } return 1; } break; } #endif return 0; }