// Thread which will handle dequeing and re-enqueing based on the status // and the flags for all ports in the output buffer void *output_monitor_routine(void *arg) { packet_t in_pkt ; ip_address_t address ; int dest_port=0 ; int loop_count= 0 ; element_to_queue * element ; while(!die) { // Only care dequing if there are elements. if((output_buffer->size > 0)) { // This will indeed dequeue the packet, but we may // have to put it back if the port isn't ready. queue_lock(output_buffer) ; dequeue(output_buffer,&in_pkt) ; queue_unlock(output_buffer) ; // Fetch the IP & lookup destination port ip_address_copy(&(in_pkt.address),&address); dest_port = cam_lookup_address(&address) ; if((dest_port != -1) && (dest_port < 4)) { // Wait for the lock port_lock(&(out_port[dest_port])) ; // If the flag is busy from the last write, then // we have to put the packet back in the queue and just // have to wait until we get to it again. if(out_port[dest_port].flag) { element = calloc(1,sizeof(element_to_queue)) ; packet_copy(&in_pkt,&(element->packet)); queue_lock(output_buffer) ; enqueue(element,output_buffer) ; queue_unlock(output_buffer) ; port_unlock(&(out_port[dest_port])) ; continue ; } // Port ready to be written , so go ahead and write. packet_copy(&in_pkt,&(out_port[dest_port].packet)); out_port[dest_port].flag = TRUE ; port_unlock(&(out_port[dest_port])) ; } } // Make sure it tried to at least deque 5 elements, before we // make it sleep. if(loop_count > LOOP_COUNT) { loop_count = 0 ; sleep() ; } else loop_count++ ; } }
// send state packet, xor packet if applicable int network_state_send( void ) { #ifdef __BLACKBERRY__ #else if (!SDLNet_UDP_Send(socket, 0, packet_state_out[0])) { printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); return -1; } // send xor of last network_delay packets if (network_delay > 1 && (last_state_out_sync + 1) % network_delay == 0 && packet_state_out[network_delay - 1] != NULL) { packet_copy(packet_temp, packet_state_out[0]); SDLNet_Write16(PACKET_STATE_XOR, &packet_temp->data[0]); for (int i = 1; i < network_delay; i++) for (int j = 4; j < packet_temp->len; j++) packet_temp->data[j] ^= packet_state_out[i]->data[j]; if (!SDLNet_UDP_Send(socket, 0, packet_temp)) { printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); return -1; } } packets_shift_down(packet_state_out, NET_PACKET_QUEUE); last_state_out_sync++; #endif return 0; }
// send packet and place it in queue to be acknowledged bool network_send( int len ) { #ifdef __BLACKBERRY__ return true; #else bool temp = network_send_no_ack(len); Uint16 i = last_out_sync - queue_out_sync; if (i < NET_PACKET_QUEUE) { packet_out[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_out[i], packet_out_temp); } else { // connection is probably bad now fprintf(stderr, "warning: outbound packet queue overflow\n"); return false; } last_out_sync++; if (network_is_sync()) last_out_tick = SDL_GetTicks(); return temp; #endif }
int mysql_driver_rewrite_command(packet * in, packet * out, const char *db_name) { if (command_is_client_auth) { int db_name_offset = 36 + strlen(in->bytes + 36) + 2; out->size = out->allocated = db_name_offset + strlen(db_name) + 1; out->bytes = malloc(out->size); if (!out->bytes) { out->size = out->allocated = 0; return 0; } bcopy(in->bytes, out->bytes, db_name_offset); bcopy(db_name, out->bytes + db_name_offset, strlen(db_name) + 1); edit_packet_length(out); } else { packet *p = packet_copy(in); if (!p) { return 0; } out->bytes = p->bytes; out->allocated = p->allocated; out->size = p->size; free(p); } return 1; }
void *switch_thread_routine(void *arg) { BOOL recv_flag=FALSE ; packet_t in_pkt ; ip_address_t address ; int dest_port=0 ; int i= 0 ; element_to_queue * element ; while(!die) { // Lock all 4 ports first ... // This is a better way to do this, since this thread may get // preempted and switched back to the input port writer which // might override the existing messages. for(i=0 ; i < NUM_PORTS ; i++) { port_lock(&(in_port[i])) ; } // Then try to unlock and check if packets are available. // We are sure to have saved all elements in the queue once // we've unlocked them for(i=0 ; i < NUM_PORTS ; i++) { if(in_port[i].flag == TRUE) { packet_copy(&(in_port[i].packet),&in_pkt); in_port[i].flag = FALSE ; } else { port_unlock(&(in_port[i])) ; continue ; } element = calloc(1,sizeof(element_to_queue)) ; packet_copy(&in_pkt,&(element->packet)); queue_lock(output_buffer) ; enqueue(element,output_buffer) ; queue_unlock(output_buffer) ; port_unlock(&(in_port[i])) ; } // pause for a a little while and then check again sleep() ; } printf("All packets sent.. Exiting !\n") ; }
packet *mysql_driver_reduce_replies(packet_set * replies) { lo(LOG_DEBUG, "mysql_driver_reduce_replies: hack hack hack"); packet *p; for (delegate_id i = 0; i < delegate_states_count; ++i) { p = packet_set_get(replies, i); if (p && p->size) { break; } } return packet_copy(p); }
static void process_eapol(struct network *n, struct client *c, const unsigned char *p, const int len, struct ieee80211_frame *wh, const int totlen) { int num, i; num = eapol_handshake_step(p, len); if (num == 0) return; /* reset... should use time, too. XXX conservative - check retry */ if (c->c_wpa == 0 || num <= c->c_wpa) { for (i = 0; i < 4; i++) c->c_handshake[i].p_len = 0; c->c_wpa_got = 0; } c->c_wpa = num; switch (num) { case 1: c->c_wpa_got |= 1; break; case 2: c->c_wpa_got |= 2; c->c_wpa_got |= 4; break; case 3: if (memcmp(&p[17], ZERO, 32) != 0) c->c_wpa_got |= 1; c->c_wpa_got |= 4; break; case 4: if (memcmp(&p[17], ZERO, 32) != 0) c->c_wpa_got |= 2; c->c_wpa_got |= 4; break; default: abort(); } packet_copy(&c->c_handshake[num - 1], wh, totlen); if (c->c_wpa_got == 7) n->n_handshake = c; }
// Given a header to the start of the queue , store the packet in the // reference. void dequeue(buf_queue * buffer,packet_t * packet) { element_to_queue * ptr_to_remove ; if(buffer->head == NULL) { return ; } else { ptr_to_remove = buffer->head ; packet_copy(&(buffer->head->packet),packet); buffer->head = buffer->head->next ; if(buffer->head == NULL) { buffer->tail == NULL ; } buffer->size-- ; } free(ptr_to_remove) ; }
// 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; }
void mysql_driver_reply(delegate_id id, packet * p) { /* have to handle being called unnecessarily */ if (delegate_states[id].expect_replies == REP_NONE) { return; } /* short-circuit for error packets */ if ((unsigned char)(p->bytes[4]) == 0xff) { char *error = malloc(p->size - 7 + 1); if (error) { strncpy(error, p->bytes + 7, p->size - 7); error[p->size - 7] = 0; lo(LOG_INFO, "mysql_driver_reply(%hu): ERROR: %s", id, error); free(error); } delegate_states[id].error = 1; delegate_states[id].expect_replies = REP_NONE; delegate_states[id].expecting_rows = 0; error_packet = packet_copy(p); /* XX: hacky, will probably need fix */ return; } switch (delegate_states[id].expect_replies) { case REP_GREETING: waiting_for_client_auth = 1; lo(LOG_DEBUG, "mysql_driver_reply(%hu): REP_GREETING -> REP_NONE", id); delegate_states[id].expect_replies = REP_NONE; break; case REP_SIMPLE: if (p->bytes[4] == 0) { lo(LOG_DEBUG, "mysql_driver_reply(%hu): REP_SIMPLE -> REP_NONE", id); delegate_states[id].expect_replies = REP_NONE; } else { lo(LOG_DEBUG, "mysql_driver_reply(%hu): REP_SIMPLE -> REP_TABLE_FIELDS", id); delegate_states[id].expect_replies = REP_TABLE_FIELDS; } break; case REP_TABLE_FIELDS: if ((unsigned char)(p->bytes[4]) == 0xfe) { if (delegate_states[id].expecting_rows) { lo(LOG_DEBUG, "mysql_driver_reply(%hu): REP_TABLE_FIELDS " "-> REP_TABLE_ROWS", id); delegate_states[id].expect_replies = REP_TABLE_ROWS; } else { lo(LOG_DEBUG, "mysql_driver_reply(%hu): REP_TABLE_FIELDS -> REP_NONE", id); delegate_states[id].expect_replies = REP_NONE; } } else { lo(LOG_DEBUG, "mysql_driver_reply(%hu): field", id); } break; case REP_TABLE_ROWS: if ((unsigned char)(p->bytes[4]) == 0xfe) { lo(LOG_DEBUG, "mysql_driver_reply(%hu): REP_TABLE_ROWS -> REP_NONE", id); delegate_states[id].expect_replies = REP_NONE; } else { lo(LOG_DEBUG, "mysql_driver_reply(%hu): row", id); } break; case REP_NONE: lo(LOG_ERROR, "mysql_driver_reply(%hu): I wasn't expecting" "any replies!", id); break; }; }
packet *mysql_driver_error_packet(void) { return packet_copy(error_packet); }