static void obj_mushroom_update_pos(GameObject* self) { ObjMushroom* mushroom = (ObjMushroom*)self; RenderComponent* r = self->render; float f = 30.0f * (mushroom->oh - mushroom->h); mushroom->dh += f * (time_delta()/1000.0f); mushroom->h += (mushroom->dh * 10.0f) * (time_delta()/1000.0f); mushroom->dh *= 0.9f; r->world_dest.top = r->world_dest.bottom - mushroom->h; }
PSoderoSession sodero_session_append(PSoderoSessionManager object, PSoderoSession session, int offset) { int index = time_delta(session->live, object->tick); // printf("Insert %p @ %d plus %d\n", session, index, offset); // if (index < 0 ) return session; // if (index >= object->count) return session; if (index < 0 ) { // printf("Sodero session %p index overflow: %d\n", session, index); return session; } if (index >= object->count) { // printf("Sodero session %p index overflow: %d\n", session, index); return session; } index += offset; session->time = session->live + offset; if (!object->tails[index]) object->tails[index] = session; session->prev = nullptr; session->next = object->heads[index]; if (object->heads[index]) object->heads[index]->prev = session; object->heads[index] = session; return nullptr; }
int main() { float* test_output = malloc( sizeof(float)*(INPUT_LENGTH-KERNEL_LENGTH+1)*ROWS); float* workspace = malloc( sizeof(float)*(INPUT_LENGTH-KERNEL_LENGTH+1)*ROWS); float* input_array; if (ROWS > 1) { input_array = malloc(sizeof(float)*(INPUT_LENGTH*ROWS)); for (int col=0; col<INPUT_LENGTH; col++){ for(int row=0; row<ROWS; row++){ input_array[row*INPUT_LENGTH + col] = INPUT_ARRAY[col]; } } } else { input_array = INPUT_ARRAY; } struct timeval now, then; float min_delta = -1.0; float delta; printf("Running %d tests of %d loops\n", N_TESTS, N_LOOPS); for (int j=0; j<N_TESTS; j++){ gettimeofday(&then, NULL); convolve_sse_2d_separable_multiple(input_array, test_output, workspace, //convolve_sse_in_aligned_fixed_kernel_multiple(INPUT_ARRAY, test_output, //convolve_sse_in_aligned_multiple(INPUT_ARRAY, test_output, //convolve_sse_partial_unroll_multiple(INPUT_ARRAY, test_output, //convolve_sse_simple_multiple(INPUT_ARRAY, test_output, //convolve_naive_multiple(INPUT_ARRAY, test_output, INPUT_LENGTH, ROWS, KERNEL, KERNEL_LENGTH, N_LOOPS); gettimeofday(&now, NULL); delta = ((float)time_delta(&now, &then))/N_LOOPS; min_delta = ((min_delta == -1.0) || (delta < min_delta)) ? delta : min_delta; } printf("Lowest test time: %1.3f microseconds per loop.\n", min_delta); for (int i=0; i<(INPUT_LENGTH-KERNEL_LENGTH+1); i++){ if (TEST_OUTPUT_CORRECT[i] != test_output[i]){ g_error("Computed convolution is incorrect."); return(-1); } } printf("Convolution is valid.\n"); free(test_output); return 0; }
static double measure(void) { long long i, iterations; int result; struct timeval start, stop; double elapsed; add1(0, 0); /* prepare off-line */ i = 0; iterations = 1000; result = gettimeofday(&start, NULL); assert(result == 0); while (1) { for (; i < iterations; i++) { add1(((int)i) & 0xaaaaaa, ((int)i) & 0x555555); } result = gettimeofday(&stop, NULL); assert(result == 0); elapsed = time_delta(&stop, &start); assert(elapsed >= 0.0); if (elapsed > 2.5) break; iterations = iterations * 3 / 2; } return elapsed / (double)iterations; }
static void wdt_enable() { pthread_spin_lock(&wrn_wdt_lock); if (time_delta(&wrn_wdt_keep_alive_sent) >= WDT_MIN_KEEP_ALIVE_INTERVAL) { // watchdog is making this call too often if (device_write_command("W0", "WDT:KEEP-ALIVE")) gettimeofday(&wrn_wdt_keep_alive_sent, NULL); } pthread_spin_unlock(&wrn_wdt_lock); }
PSoderoSession sodero_session_check(PSoderoSessionManager object, unsigned long long tick) { PSoderoSession result = nullptr; unsigned int time = tick / uSecsPerSec; int step = time_delta(time, object->tick); // printf("Check manager %0.6f from %0.6f step %d\n", 1e-6*tick, 1e-6*object->tick, step); if (step > 0) { // if (step > 1) // printf("Session check step %d\n", step); // printf("Session step %d\n", step); if (step > object->count) step = object->count; // unsigned long long b = now(); // unsigned int count = 0; // unsigned int total = 0; for (int i = 0; i < step; i++) { PSoderoSession session = object->heads[i]; // if (session) // count++; while(session) { // total++; PSoderoSession curr = session; session = sodero_session_next(curr); if (sodero_session_timeout(curr, time) > 0) curr = sodero_session_append(object, curr, step); if (curr) { curr->prev = nullptr; curr->next = result; if (result) result->prev = curr; result = curr; } } } object->tick = time; memmove(object->heads, object->heads + step, object->count * sizeof(*object->heads)); memmove(object->tails, object->tails + step, object->count * sizeof(*object->tails)); bzero(object->heads + object->count, step * sizeof(*object->heads)); bzero(object->tails + object->count, step * sizeof(*object->tails)); // unsigned long long e = now(); // // printf("Session check in %.3f %u/%u\n", 1e-6*(e-b), count, total); } object->tick = time; return result; }
static void obj_trampoline_update_pos(GameObject* self) { ObjTrampoline* trampoline = (ObjTrampoline*)self; RenderComponent* r = self->render; float f = 30.0f * (trampoline->oh - trampoline->h); trampoline->dh += f * (time_delta()/1000.0f); trampoline->h += (trampoline->dh * 10.0f) * (time_delta()/1000.0f); trampoline->dh *= 0.9f; r->world_dest.top = r->world_dest.bottom - trampoline->h; r->world_dest.bottom += trampoline->db; PhysicsComponent* p = self->physics; if(p->cd_obj->pos.y > 783.0f && trampoline->db == 0.0f){ p->cd_obj->pos.y -= 10.0f; r->world_dest.bottom -= 10.0f; } if(trampoline->owner->physics->cd_obj->pos.x > r->world_dest.right +50.0f) trampoline->db = 5.0f; }
void LogDefer::add_log(int verbosity, const std::string &msg) { picojson::array entry; struct timeval end_tv; gettimeofday(&end_tv, NULL); entry.push_back(time_delta(&end_tv, &start_tv_)); entry.push_back(picojson::value((double)verbosity)); entry.push_back(picojson::value(msg)); picojson::value entry_val(entry); logs_.push_back(entry_val); }
PSoderoSession sodero_session_remove(PSoderoSessionManager object, PSoderoSession session) { int index = time_delta(session->time, object->tick); // printf("Remove %p @ %d\n", session, index); if (index < 0 ) { // printf("Sodero session %p index overflow: %d\n", session, index); return nullptr; } if (index >= object->count) { // printf("Sodero session %p index overflow: %d\n", session, index); return nullptr; } // if (!sodero_session_find_next(object->heads[index], session)) { // printf("Sodero session %p find next failure\n", session); // for(int i = 0; i < object->count; i++) { // if (sodero_session_find_next(object->heads[i], session)) // printf("Found head: %d\n", i); // } // return nullptr; // } // if (!sodero_session_find_prev(object->tails[index], session)) { // printf("Sodero session %p find prev failure\n", session); // for(int i = 0; i < object->count; i++) { // if (sodero_session_find_prev(object->tails[i], session)) // printf("Found tail: %d\n", i); // } // return nullptr; // } if (session->prev) session->prev->next = session->next; else do { if (object->heads[index] == session) object->heads[index] = session->next; } while (false); if (session->next) session->next->prev = session->prev; else do { if (index < 0 ) break; if (index >= object->count) break; if (object->tails[index] == session) object->tails[index] = session->prev; } while (false); session->prev = nullptr; session->next = nullptr; return session; }
// Calculate the time delta void calc_time_delta(void) { START_PROFILING; #pragma acc kernels \ present(time_delta[:time_delta_len], velocity[:velocity_len]) #pragma acc loop independent for(int g = 0; g < ng; ++g) { time_delta(g) = 2.0 / (dt * velocity(g)); } STOP_PROFILING(__func__); }
query_status_t deal_with_ottdmaster_packet(struct qserver *server, char *rawpkt, int pktlen) { unsigned num; server->ping_total += time_delta(&packet_recv_time, &server->packet_time1); server->server_name = MASTER; if(swap_short_from_little(rawpkt) != pktlen) { malformed_packet( server, "invalid packet length" ); return PKT_ERROR; } if(rawpkt[2] != 7) { malformed_packet( server, "invalid packet type" ); return PKT_ERROR; } if(rawpkt[3] != 1) { malformed_packet( server, "invalid packet version" ); return PKT_ERROR; } num = swap_short_from_little(&rawpkt[4]); rawpkt += 6; pktlen -= 6; if( num && num*6 <= pktlen ) { unsigned i; server->master_pkt = (char*)realloc(server->master_pkt, server->master_pkt_len + pktlen ); memset(server->master_pkt + server->master_pkt_len, 0, pktlen ); server->master_pkt_len += pktlen; for( i = 0; i < num * 6; i += 6 ) { memcpy(&server->master_pkt[i], &rawpkt[i], 4); server->master_pkt[i+4] = rawpkt[i+5]; server->master_pkt[i+5] = rawpkt[i+4]; } server->n_servers += num; } else { malformed_packet( server, "invalid packet" ); return PKT_ERROR; } bind_sockets(); return DONE_AUTO; }
query_status_t deal_with_doom3master_packet( struct qserver *server, char *rawpkt, int pktlen) { char* pkt, *dest; int len; server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); if ( pktlen < sizeof(doom3_masterresponse) + 6 // at least one server || (pktlen - sizeof(doom3_masterresponse)) % 6 || memcmp( doom3_masterresponse, rawpkt, sizeof(doom3_masterresponse) ) != 0 ) { server->server_name= SERVERERROR; server->master_pkt_len = 0; malformed_packet(server, "too short or invalid response"); return PKT_ERROR; } server->retry1 = 0; // received at least one packet so no need to retry pkt = rawpkt + sizeof(doom3_masterresponse); len = pktlen - sizeof(doom3_masterresponse); server->master_pkt = (char*)realloc( server->master_pkt, server->master_pkt_len + len); dest = server->master_pkt + server->master_pkt_len; server->master_pkt_len += len; while(len > 0) { memcpy(dest, pkt, 4 ); dest[4] = pkt[5]; dest[5] = pkt[4]; dest += 6; pkt += 6; len -= 6; } assert(len == 0); server->n_servers= server->master_pkt_len / 6; debug(2, "%d servers added", server->n_servers); return INPROGRESS; }
// Calculate the inverted denominator for all the energy groups void calc_denominator(void) { START_PROFILING; #pragma acc kernels \ present(denom[:denom_len], total_cross_section[:total_cross_section_len], \ time_delta[:time_delta_len], mu[:mu_len], dd_j[:dd_j_len], \ dd_k[:dd_k_len]) #pragma acc loop collapse(3) independent for (unsigned int ind = 0; ind < nx*ny*nz; ind++) { for (unsigned int g = 0; g < ng; ++g) { for (unsigned int a = 0; a < nang; ++a) { denom[a+g*nang+ind*ng*nang] = 1.0 / (total_cross_section[g+ind*ng] + time_delta(g) + mu(a)*dd_i + dd_j(a) + dd_k(a)); } } } STOP_PROFILING(__func__); }
LogDefer::~LogDefer() { struct timeval end_tv; gettimeofday(&end_tv, NULL); o_.emplace("end", time_delta(&end_tv, &start_tv_)); if (!data_.empty()) { picojson::value data_val(data_); o_.emplace("data", data_val); } if (!logs_.empty()) { picojson::value logs_val(logs_); o_.emplace("logs", logs_val); } if (!timers_.empty()) { picojson::value timers_val(timers_); o_.emplace("timers", timers_val); } picojson::value v(o_); callback_(v.serialize()); }
int main(int argc, char** argv) { /* unit_test1(); return 0;*/ char isPrintPretty = 0; if(argc > 1 && strcmp(argv[1], "beauty")==0) {isPrintPretty=1; printf("Print occurances.\n");} char filename[1000]; int len; int i, j; char filename_needles[1000]; int len_needles; int* array = NULL; while(array==NULL) { printf(" >> Please input filename.\n >>"); scanf("%s", filename); array = readfile_haystack(filename, &len); } printf(" >> Please input pattern filename. If you don't want a pattern file, enter random characters and press enter.\n >>"); scanf("%s", filename_needles); struct intarray** needles = readfile_needles(filename_needles, &len_needles); // Profiling start gettimeofday(&tv_start, NULL); printf(" >> Building lookup array.\n"); int* array_lkp = sort_012(array, len); printf(" >> Building suffix array.\n"); int* array_sa = get_SA(array_lkp, len); printf(" >> Building BWT.\n"); int* array_bwt = get_BWT(array, array_sa, len); printf(" >> Building dictionary.\n"); int* array_alpha = alphabetical_sort(array, len); struct intarray2 dictc; struct int2 fl; int nocc; get_dicandc(array_alpha, len, &dictc); printf(" >> Building wavelet tree.\n"); // struct wavelettree* array_wavelettree = wavelettree_build(array, len, &dictc); struct wavelettree* array_bwt_wlt = wavelettree_build(array_bwt, len, &dictc); /* Completed generating SA, BWT, WLT */ gettimeofday(&tv_sa, NULL); wavelettree_print(array_bwt_wlt); #ifdef DEBUG printf("dict size=%d\n", dictc.len1); for(i=0; i<dictc.len1; i++) printf("(%c, %d)\n", dictc.ia1[i], dictc.ia2[i]); printf("\n"); #endif #ifdef DEBUG printf(" >> Testing wavelet tree.\n"); for(i=0; i<dictc.len1; i++) { int rk = wavelettree_rank(array_bwt_wlt, len-1, dictc.ia1[i]); int rk2 = (i==dictc.len1-1) ? len - dictc.ia2[i] : dictc.ia2[i+1]-dictc.ia2[i]; printf("%d. [%c] tree_rk: %d dict_rk: %d\n", i, dictc.ia1[i], rk, rk2); } #endif for(i=0;i<len_needles;i++) { nocc = find_num_of_occurances(array_alpha, array_bwt, array_bwt_wlt, len, &dictc, needles[i]->ia, needles[i]->len, &fl); int* array_occ = occurances_to_locations(array_sa, &fl, len); /* Don't print if the input is massively large! */ if(isPrintPretty==1) print_beautiful_occurances(array, len, needles[i], array_occ, nocc); free(array_occ); printf("Pattern No.%d, [", i); for(j=0; j<needles[i]->len; j++) { printf("%c", needles[i]->ia[j]); if(j > 100) { printf(" ... "); break;} } printf("], "); if(nocc>0) printf("Found %d occurances.", nocc); else printf("Not found."); printf("\n"); } // Profiling end gettimeofday(&tv_end, NULL); long mtime; mtime = time_delta(&tv_start, &tv_sa); printf("\n==========Running time!==========\n"); printf("Building SA, BWT and alphabetically sorting used %ld milliseconds.\n", mtime); mtime = time_delta(&tv_sa, &tv_end); printf("Searching %d patterns used %ld milliseconds.\n", len_needles, mtime); printf("\nIf you want to search any other keywords, enter them here. (Ctrl+C to exit)\n"); char keyin[1000]; int ikeyin[1000]; struct intarray iakeyin; iakeyin.ia=ikeyin; iakeyin.len=0; while(1) { printf(" >>"); scanf("%s", keyin); if(strcmp(keyin, "~~~")==0) break; gettimeofday(&tv_start, NULL); iakeyin.len = strlen(keyin); for(i=0; i<iakeyin.len; i++)ikeyin[i]=keyin[i]; nocc = find_num_of_occurances(array_alpha, array_bwt, array_bwt_wlt, len, &dictc, iakeyin.ia, iakeyin.len, &fl); int* array_occ = occurances_to_locations(array_sa, &fl, len); gettimeofday(&tv_sa, NULL); mtime = time_delta(&tv_start, &tv_sa); if(isPrintPretty==1) print_beautiful_occurances(array, len, &iakeyin, array_occ, nocc); free(array_occ); if(nocc!=-1) printf(" >> Found %d occurances in %ld milliseconds.\n", nocc, mtime); else printf(" >> Not found. Time used: %ld milliseconds.\n", mtime); } return 0; }
query_status_t deal_with_tm_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *s; char *pkt = rawpkt; char *key = NULL, *value = NULL, *tmpp = NULL; char fullname[256]; struct player *player = NULL; int pkt_max = server->saved_data.pkt_max; unsigned total_len, expected_len; int method_response = 1; debug( 2, "processing..." ); s = rawpkt; // We may get the setup handle and the protocol version in one packet we may not // So we continue to parse if we see the handle if ( 4 <= pktlen && 0 == memcmp( pkt, "\x0b\x00\x00\x00", 4 ) ) { // setup handle identifier // greater 2^31 = XML-RPC, less = callback server->challenge = 0x80000001; if ( 4 == pktlen ) { return 0; } pktlen -= 4; pkt += 4; } if ( 11 <= pktlen && 1 == sscanf( pkt, "GBXRemote %d", &server->protocol_version ) ) { // Got protocol version send request send_tm_request_packet( server ); return 0; } if ( 8 <= pktlen && 0 == memcmp( pkt+4, &server->challenge, 4 ) ) { // first 4 bytes = the length // Note: We use pkt_id to store the length of the expected packet // this could cause loss but very unlikely unsigned long len; memcpy( &len, rawpkt, 4 ); // second 4 bytes = handle identifier we sent in the request if ( 8 == pktlen ) { // split packet // we have at least one more packet coming if ( ! add_packet( server, len, 0, 2, pktlen, rawpkt, 1 ) ) { // fatal error e.g. out of memory return -1; } return 0; } else { // ensure the length is stored server->saved_data.pkt_id = (int)len; s += 8; } } total_len = combined_length( server, server->saved_data.pkt_id ); expected_len = server->saved_data.pkt_id; debug( 2, "total: %d, expected: %d\n", total_len, expected_len ); if ( total_len < expected_len + 8 ) { // we dont have a complete response add the packet int last, new_max; if ( total_len + pktlen >= expected_len + 8 ) { last = 1; new_max = pkt_max; } else { last = 0; new_max = pkt_max + 1; } if ( ! add_packet( server, server->saved_data.pkt_id, pkt_max - 1, new_max, pktlen, rawpkt, 1 ) ) { // fatal error e.g. out of memory return -1; } if ( last ) { // we are the last packet run combine to call us back return combine_packets( server ); } return 0; } server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL); } // Terminate the packet data pkt = (char*)malloc( pktlen + 1 ); if ( NULL == pkt ) { debug( 0, "Failed to malloc memory for packet terminator\n" ); return MEM_ERROR; } memcpy( pkt, rawpkt, pktlen ); pkt[pktlen] = '\0'; //fprintf( stderr, "S=%s\n", s ); s = strtok( pkt + 8, "\015\012" ); while ( NULL != s ) { //fprintf( stderr, "S=%s\n", s ); if ( 0 == strncmp( s, "<member><name>", 14 ) ) { key = s + 14; tmpp = strstr( key, "</name>" ); if ( NULL != tmpp ) { *tmpp = '\0'; } s = strtok( NULL, "\015\012" ); value = NULL; continue; } else if ( NULL != key && 0 == strncmp( s, "<value>", 7 ) ) { // value s += 7; if ( 0 == strncmp( s, "<string>", 8 ) ) { // String value = s+8; tmpp = strstr( s, "</string>" ); } else if ( 0 == strncmp( s, "<i4>", 4 ) ) { // Int value = s+4; tmpp = strstr( s, "</i4>" ); } else if ( 0 == strncmp( s, "<boolean>", 9 ) ) { // Boolean value = s+9; tmpp = strstr( s, "</boolean>" ); } else if ( 0 == strncmp( s, "<double>", 8 ) ) { // Double value = s+8; tmpp = strstr( s, "</double>" ); } // also have struct and array but not interested in those if ( NULL != tmpp ) { *tmpp = '\0'; } if ( NULL != value ) { debug( 4, "%s = %s\n", key, value ); } } else if ( 0 == strncmp( s, "</struct>", 9 ) && 3 > method_response ) { // end of method response method_response++; } if ( NULL != value && NULL != key ) { switch( method_response ) { case 1: // GetServerOptions response if ( 0 == strcmp( "Name", key ) ) { server->server_name = strdup( value ); } else if ( 0 == strcmp( "CurrentMaxPlayers", key ) ) { server->max_players = atoi( value ); } else { sprintf( fullname, "server.%s", key ); add_rule( server, fullname, value, NO_FLAGS); } break; case 2: // GetCurrentChallengeInfo response if ( 0 == strcmp( "Name", key ) ) { server->map_name = strdup( value ); } else { sprintf( fullname, "challenge.%s", key ); add_rule( server, fullname, value, NO_FLAGS); } break; case 3: // GetPlayerList response // Player info if ( 0 == strcmp( "Login", key ) ) { player = add_player( server, server->n_player_info ); server->num_players++; } else if ( NULL != player ) { if ( 0 == strcmp( "NickName", key ) ) { player->name = strdup( value ); } else if ( 0 == strcmp( "PlayerId", key ) ) { //player->number = atoi( value ); } else if ( 0 == strcmp( "TeamId", key ) ) { player->team = atoi( value ); } else if ( 0 == strcmp( "IsSpectator", key ) ) { player->flags = player->flags & 1; } else if ( 0 == strcmp( "IsInOfficialMode", key ) ) { player->flags = player->flags & 2; } else if ( 0 == strcmp( "LadderRanking", key ) ) { player->score = atoi( value ); } } break; } value = NULL; } s = strtok( NULL, "\015\012" ); } free( pkt ); if ( 0 == strncmp( rawpkt + pktlen - 19, "</methodResponse>", 17 ) ) { // last packet seen return DONE_FORCE; } return INPROGRESS; }
query_status_t deal_with_crysis_packet(struct qserver *server, char *rawpkt, int pktlen) { char *s, *val, *line; query_status_t state = INPROGRESS; debug(2, "processing..."); if (!server->combined) { state = valid_crysis_response(server, rawpkt, pktlen); server->retry1 = n_retries; if (0 == server->n_requests) { server->ping_total = time_delta(&packet_recv_time, &server->packet_time1); server->n_requests++; } switch (state) { case INPROGRESS: { // response fragment recieved int pkt_id; int pkt_max; // We're expecting more to come debug(5, "fragment recieved..."); pkt_id = packet_count(server); pkt_max = pkt_id++; if (!add_packet(server, 0, pkt_id, pkt_max, pktlen, rawpkt, 1)) { // fatal error e.g. out of memory return (MEM_ERROR); } // combine_packets will call us recursively return (combine_packets(server)); } case DONE_FORCE: break; // single packet response fall through default: return (state); } } if (DONE_FORCE != state) { state = valid_crysis_response(server, rawpkt, pktlen); switch (state) { case DONE_FORCE: break; // actually process default: return (state); } } debug(3, "packet: challenge = %ld", server->challenge); s = NULL; switch (server->challenge) { case 1: s = crysis_response(server, rawpkt, pktlen); if (NULL != s) { server->challenge_string = s; return (send_crysis_request_packet(server)); } return (REQ_ERROR); case 2: s = crysis_response(server, rawpkt, pktlen); if (NULL == s) { return (REQ_ERROR); } if (0 != strncmp(s, "authorized", 10)) { free(s); return (REQ_ERROR); } free(s); return (send_crysis_request_packet(server)); case 3: s = crysis_response(server, rawpkt, pktlen); if (NULL == s) { return (REQ_ERROR); } } // Correct ping // Not quite right but gives a good estimate server->ping_total = (server->ping_total * server->n_requests) / 2; debug(3, "processing response..."); s = decode_crysis_val(s); line = strtok(s, "\012"); // NOTE: id=XXX and msg=XXX will be processed by the mod following the one they where the response of while (NULL != line) { debug(4, "LINE: %s\n", line); val = strstr(line, ":"); if (NULL != val) { *val = '\0'; val += 2; debug(4, "var: %s, val: %s", line, val); if (0 == strcmp("name", line)) { server->server_name = strdup(val); } else if (0 == strcmp("level", line)) { server->map_name = strdup(val); } else if (0 == strcmp("players", line)) { if (2 == sscanf(val, "%d/%d", &server->num_players, &server->max_players)) { } } else if ( (0 == strcmp("version", line)) || (0 == strcmp("gamerules", line)) || (0 == strcmp("time remaining", line)) ) { add_rule(server, line, val, NO_FLAGS); } } line = strtok(NULL, "\012"); } gettimeofday(&server->packet_time1, NULL); return (DONE_FORCE); }
query_status_t deal_with_dirtybomb_packet(struct qserver *server, char *rawpkt, int pktlen) { unsigned char *s, *l, pkt_id, pkt_max; debug(2, "processing..."); if (8 > pktlen) { // not valid response malformed_packet(server, "packet too small"); return PKT_ERROR; } if (rawpkt[4] != 0x01) { // not a known response malformed_packet(server, "unknown packet type 0x%02hhx", rawpkt[4]); return PKT_ERROR; } // Response ID - long // Response Type - byte // Current Packet Number - byte pkt_id = rawpkt[5]; // Last Packet Number - byte pkt_max = rawpkt[6]; // Payload Blob - msgpack map s = (unsigned char*)rawpkt + 7; if (!server->combined) { int pkt_cnt = packet_count(server); server->retry1 = n_retries; if (0 == server->n_requests) { server->ping_total = time_delta( &packet_recv_time, &server->packet_time1 ); server->n_requests++; } if (pkt_cnt < pkt_max) { // We're expecting more to come debug( 5, "fragment recieved..." ); if (!add_packet(server, 0, pkt_id, pkt_max, pktlen, rawpkt, 1)) { // fatal error e.g. out of memory return MEM_ERROR; } // combine_packets will call us recursively return combine_packets(server); } } // Correct ping // Not quite right but gives a good estimate server->ping_total = (server->ping_total * server->n_requests) / 2; debug(3, "processing response..."); gettimeofday(&server->packet_time1, NULL); l = (unsigned char *)rawpkt + pktlen - 1; if (!unpack_msgpack(server, s, l)) { return PKT_ERROR; } return DONE_FORCE; }
query_status_t deal_with_fl_packet(struct qserver *server, char *rawpkt, int pktlen) { struct fl_status* status = (struct fl_status*)server->master_query_tag; char* pkt = rawpkt; char buf[16]; char* str; unsigned cnt; unsigned short tmp_short; if(server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); server->n_requests++; } if(pktlen < 5) goto out_too_short; if( 0 == memcmp(pkt, "\xFF\xFF\xFF\xFE", 4) ) { // fragmented packet unsigned char pkt_index, pkt_max; unsigned int pkt_id; SavedData *sdata; if(pktlen < 9) goto out_too_short; // format: // int Header // int RequestId // byte PacketNumber // byte NumPackets // Short SizeOfPacketSplits // Header pkt += 4; // RequestId pkt_id = ntohl( *(long *)pkt ); debug( 3, "RequestID: %d", pkt_id ); pkt += 4; // The next two bytes are: // 1. the max packets sent ( byte ) // 2. the index of this packet starting from 0 ( byte ) // 3. Size of the split ( short ) if(pktlen < 10) goto out_too_short; // PacketNumber pkt_index = ((unsigned char)*pkt); // NumPackates pkt_max = ((unsigned char)*(pkt+1)); // SizeOfPacketSplits debug( 3, "packetid[2]: 0x%hhx => idx: %hhu, max: %hhu", *pkt, pkt_index, pkt_max ); pkt+=4; pktlen -= 12; // pkt_max is the total number of packets expected // pkt_index is a bit mask of the packets received. if ( server->saved_data.data == NULL ) { sdata = &server->saved_data; } else { sdata = (SavedData*) calloc( 1, sizeof(SavedData)); sdata->next = server->saved_data.next; server->saved_data.next = sdata; } sdata->pkt_index = pkt_index; sdata->pkt_max = pkt_max; sdata->pkt_id = pkt_id; sdata->datalen = pktlen; sdata->data= (char*)malloc( pktlen ); if ( NULL == sdata->data ) { malformed_packet(server, "Out of memory"); return MEM_ERROR; } memcpy( sdata->data, pkt, sdata->datalen ); // combine_packets will call us recursively return combine_packets( server ); } else if ( 0 != memcmp(pkt, "\xFF\xFF\xFF\xFF", 4) ) { malformed_packet(server, "invalid packet header"); return PKT_ERROR; } pkt += 4; pktlen -= 4; pktlen -= 1; debug( 2, "FL type = 0x%x", *pkt ); switch(*pkt++) { case FL_CHALLENGERESPONSE: if(pktlen < 4) goto out_too_short; memcpy(&status->challenge, pkt, 4); // do not count challenge as retry if(!status->have_challenge && server->retry1 != n_retries) { ++server->retry1; if(server->n_retries) { --server->n_retries; } } status->have_challenge = 1; debug(3, "challenge %x", status->challenge); break; case FL_INFORESPONSE: if(pktlen < 1) goto out_too_short; status->type = *pkt; if ( *pkt > 1 && ( get_server_rules || get_player_info ) ) { server->next_rule = ""; // trigger calling send_fl_rule_request_packet } snprintf(buf, sizeof(buf), "%hhX", *pkt); add_rule(server, "protocol", buf, 0); pktlen--; pkt++; // ServerName str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->server_name = strdup(pkt); pktlen -= str-pkt+1; pkt += str-pkt+1; // MapName str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->map_name = strdup(pkt); pktlen -= str-pkt+1; pkt += str-pkt+1; // ModName str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->game = strdup(pkt); add_rule(server, "modname", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; // GameMode str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "gamemode", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; // GameDescription str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "gamedescription", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; // GameVersion str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "gameversion", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; if( pktlen < 13 ) { goto out_too_short; } // GamePort tmp_short = ((unsigned short)pkt[0] <<8 ) | ((unsigned short)pkt[1]); change_server_port( server, tmp_short, 0 ); pkt += 2; // Num Players server->num_players = (unsigned char)*pkt++; // Max Players server->max_players = (unsigned char)*pkt++; // Dedicated add_rule(server, "dedicated", ( 'd' == *pkt++) ? "1" : "0", 0); // OS switch( *pkt ) { case 'l': add_rule(server, "sv_os", "linux", 0); break; case 'w': add_rule(server, "sv_os", "windows", 0); break; default: buf[0] = *pkt; buf[1] = '\0'; add_rule(server, "sv_os", buf, 0); break; } pkt++; // Passworded add_rule(server, "passworded", ( *pkt++ ) ? "1" : "0" , 0); // Anticheat add_rule(server, "passworded", ( *pkt++ ) ? "1" : "0" , 0); // FrameTime sprintf( buf, "%hhu", *pkt++ ); add_rule(server, "frametime", buf , 0); // Round sprintf( buf, "%hhu", *pkt++ ); add_rule(server, "round", buf , 0); // RoundMax sprintf( buf, "%hhu", *pkt++ ); add_rule(server, "roundmax", buf , 0); // RoundSeconds tmp_short = ((unsigned short)pkt[0] <<8 ) | ((unsigned short)pkt[1]); sprintf( buf, "%hu", tmp_short ); add_rule(server, "roundseconds", buf , 0); pkt += 2; status->have_info = 1; server->retry1 = n_retries; server->next_player_info = server->num_players; break; case FL_RULESRESPONSE: if(pktlen < 2) goto out_too_short; cnt = ((unsigned char)pkt[0] << 8 ) + ((unsigned char)pkt[1]); pktlen -= 2; pkt += 2; debug(3, "num_rules: %d", cnt); for(;cnt && pktlen > 0; --cnt) { char* key, *value; str = memchr(pkt, '\0', pktlen); if(!str) break; key = pkt; pktlen -= str-pkt+1; pkt += str-pkt+1; str = memchr(pkt, '\0', pktlen); if(!str) break; value = pkt; pktlen -= str-pkt+1; pkt += str-pkt+1; add_rule(server, key, value, NO_FLAGS); } if(cnt) { malformed_packet(server, "packet contains too few rules, missing %d", cnt); server->missing_rules = 1; } if(pktlen) malformed_packet(server, "garbage at end of rules, %d bytes left", pktlen); status->have_rules = 1; server->retry1 = n_retries; break; case FL_PLAYERRESPONSE: if(pktlen < 1) goto out_too_short; cnt = (unsigned char)pkt[0]; pktlen -= 1; pkt += 1; debug(3, "num_players: %d", cnt); for(;cnt && pktlen > 0; --cnt) { unsigned idx; const char* name; struct player* p; // Index idx = *pkt++; --pktlen; // PlayerName str = memchr(pkt, '\0', pktlen); if(!str) break; name = pkt; pktlen -= str-pkt+1; pkt += str-pkt+1; if(pktlen < 8) goto out_too_short; debug(3, "player index %d", idx); p = add_player(server, server->n_player_info); if(p) { union { int i; float fl; } temp; p->name = strdup(name); // Score p->frags = ntohl( *(unsigned int *)pkt ); // TimeConnected temp.i = ntohl( *(unsigned int *)(pkt+4) ); p->connect_time = temp.fl; // Ping p->ping = 0; p->ping = ntohs( *(unsigned int *)(pkt+8) ); //((unsigned char*)&p->ping)[0] = pkt[9]; //((unsigned char*)&p->ping)[1] = pkt[8]; // ProfileId //p->profileid = ntohl( *(unsigned int *)pkt+10 ); // Team p->team = *(pkt+14); //fprintf( stderr, "Player: '%s', Frags: %u, Time: %u, Ping: %hu, Team: %d\n", p->name, p->frags, p->connect_time, p->ping, p->team ); } pktlen -= 15; pkt += 15; } #if 0 // seems to be a rather normal condition if(cnt) { malformed_packet(server, "packet contains too few players, missing %d", cnt); } #endif if(pktlen) malformed_packet(server, "garbage at end of player info, %d bytes left", pktlen); status->have_player = 1; server->retry1 = n_retries; break; default: malformed_packet(server, "invalid packet id %hhx", *--pkt); return PKT_ERROR; } if( (!get_player_info || (get_player_info && status->have_player)) && (!get_server_rules || (get_server_rules && status->have_rules)) ) { server->next_rule = NULL; } return DONE_AUTO; out_too_short: malformed_packet(server, "packet too short"); return PKT_ERROR; }
inline std::string time_delta_str(const boost::posix_time::ptime &ref_time) { return boost::posix_time::to_simple_string(time_delta(ref_time)); }
query_status_t deal_with_cube2_packet( struct qserver *server, char *rawpkt, int pktlen ) { // skip unimplemented ack, crc, etc int i; int numattr; int attr[MAX_ATTR]; char buf[MAX_STRING]; enum { MM_OPEN = 0, MM_VETO, MM_LOCKED, MM_PRIVATE }; struct offset d; d.d = (unsigned char *) rawpkt; d.pos = 0; d.len = pktlen; server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); getint( &d ); // we have the ping already server->num_players = getint( &d ); numattr = getint( &d ); for ( i = 0; i < numattr && i < MAX_ATTR; i++ ) { attr[i] = getint (&d); } server->protocol_version = attr[0]; sprintf( buf, "%d %s", attr[0], sb_getversion_s (attr[0]) ); add_rule( server, "version", buf, NO_FLAGS ); sprintf( buf, "%d %s", attr[1], sb_getmode_s (attr[1]) ); add_rule( server, "mode", buf, NO_FLAGS ); sprintf( buf, "%d", attr[2] ); add_rule( server, "seconds_left", buf, NO_FLAGS ); server->max_players = attr[3]; switch ( attr[5] ) { case MM_OPEN: sprintf( buf, "%d open", attr[5] ); break; case MM_VETO: sprintf( buf, "%d veto", attr[5] ); break; case MM_LOCKED: sprintf( buf, "%d locked", attr[5] ); break; case MM_PRIVATE: sprintf( buf, "%d private", attr[5] ); break; default: sprintf( buf, "%d unknown", attr[5] ); } add_rule( server, "mm", buf, NO_FLAGS); for ( i = 0; i < numattr && i < MAX_ATTR; i++ ) { char buf2[MAX_STRING]; sprintf( buf, "attr%d", i ); sprintf( buf2, "%d", attr[i] ); add_rule( server, buf, buf2, NO_FLAGS ); } getstr( buf, MAX_STRING, &d ); server->map_name = strdup(buf); getstr( buf, MAX_STRING, &d ); server->server_name = strdup(buf); return DONE_FORCE; }
query_status_t deal_with_ts3_packet(struct qserver *server, char *rawpkt, int pktlen) { char *s, *player_name = "unknown"; int valid_response = 0, mode = 0, all_servers = 0; char last_char; unsigned short port = 0, down = 0, auth_seen = 0; debug(2, "processing..."); if (0 == pktlen) { // Invalid password return (REQ_ERROR); } last_char = rawpkt[pktlen - 1]; rawpkt[pktlen - 1] = '\0'; s = rawpkt; all_servers = all_ts3_servers(server); debug(3, "packet: combined = %d, challenge = %ld, n_servers = %d", server->combined, server->challenge, server->n_servers); if (!server->combined) { server->retry1 = n_retries; if (0 == server->n_requests) { server->ping_total = time_delta(&packet_recv_time, &server->packet_time1); server->n_requests++; } if (server->n_servers >= server->challenge) { // response fragment recieved int pkt_id; int pkt_max; // We're expecting more to come debug(5, "fragment recieved..."); pkt_id = packet_count(server); pkt_max = pkt_id + 1; rawpkt[pktlen - 1] = last_char; // restore the last character if (!add_packet(server, 0, pkt_id, pkt_max, pktlen, rawpkt, 1)) { // fatal error e.g. out of memory return (MEM_ERROR); } // combine_packets will call us recursively return (combine_packets(server)); } } else { valid_response = valid_ts3_response(server, rawpkt + server->master_pkt_len, pktlen - server->master_pkt_len); debug(2, "combined packet: valid_response: %d, challenge: %ld, n_servers: %d, offset: %d", valid_response, server->challenge, server->n_servers, server->master_pkt_len); if (0 > valid_response) { // Error occured return (valid_response); } server->challenge += valid_response; if (valid_response) { // Got a valid response, send the next request int ret = send_ts3_request_packet(server); if (0 != ret) { // error sending packet debug(4, "Request failed: %d", ret); return (ret); } } if (server->n_servers > server->challenge) { // recursive call which is still incomplete return (INPROGRESS); } } // Correct ping // Not quite right but gives a good estimate server->ping_total = (server->ping_total * server->n_requests) / 2; debug(3, "processing response..."); s = strtok(rawpkt, "\012\015 |"); // NOTE: id=XXX and msg=XXX will be processed by the mod following the one they where the response of while (NULL != s) { debug(4, "LINE: %d, %s\n", mode, s); switch (mode) { case 0: // prompt, use or serverlist response if (0 == strcmp("TS3", s)) { // nothing to do unless in all servers mode if (1 == all_servers) { mode++; } } else if (0 == strncmp("error", s, 5)) { // end of use response mode++; } break; case 1: // serverinfo or serverlist response including condition authentication if ((0 == auth_seen) && (0 != strlen(get_param_value(server, "password", ""))) && (0 == strncmp("error", s, 5))) { // end of auth response auth_seen = 1; } else if (0 == strncmp("error", s, 5)) { // end of serverinfo response mode++; } else { // Server Rule char *key = s; char *value = strchr(key, '='); if (NULL != value) { *value = '\0'; value++; debug(6, "Rule: %s = %s\n", key, value); if (0 == strcmp("virtualserver_name", key)) { if (1 == all_servers) { struct qserver *new_server = add_qserver_byaddr(ntohl(server->ipaddr), port, server->type, NULL); if (NULL != new_server) { if (down) { // Status indicates this server is actually offline new_server->server_name = DOWN; } else { new_server->max_players = server->max_players; new_server->num_players = server->num_players; new_server->server_name = strdup(decode_ts3_val(value)); new_server->map_name = strdup("N/A"); new_server->ping_total = server->ping_total; new_server->n_requests = server->n_requests; } cleanup_qserver(new_server, FORCE); } down = 0; } else { server->server_name = strdup(decode_ts3_val(value)); } } else if (0 == strcmp("virtualserver_port", key)) { port = atoi(value); change_server_port(server, port, 0); add_rule(server, key, value, NO_FLAGS); } else if (0 == strcmp("virtualserver_maxclients", key)) { server->max_players = atoi(value); } else if (0 == strcmp("virtualserver_clientsonline", key)) { server->num_players = atoi(value); } else if (0 == strcmp("virtualserver_queryclientsonline", key)) { // clientsonline includes queryclientsonline so remove these from our count server->num_players -= atoi(value); } else if ((0 == strcmp("virtualserver_status", key)) && (0 != strcmp("online", value))) { // Server is actually offline to client so display as down down = 1; if (1 != all_servers) { server->server_name = DOWN; //server->saved_data.pkt_index = 0; return (DONE_FORCE); } } else if ((0 == strcmp("id", key)) || (0 == strcmp("msg", key))) { // Ignore details from the response code } else if (1 != all_servers) { add_rule(server, key, value, NO_FLAGS); } } } break; case 2: // clientlist response if (0 == strncmp("error", s, 5)) { // end of serverinfo response mode++; } else { // Client char *key = s; char *value = strchr(key, '='); if (NULL != value) { *value = '\0'; value++; debug(6, "Player: %s = %s\n", key, value); if (0 == strcmp("client_nickname", key)) { player_name = value; } else if (0 == strcmp("clid", key)) { } else if ((0 == strcmp("client_type", key)) && (0 == strcmp("0", value))) { struct player *player = add_player(server, server->n_player_info); if (NULL != player) { player->name = strdup(decode_ts3_val(player_name)); } } else if ((0 == strcmp("id", key)) || (0 == strcmp("msg", key))) { // Ignore details from the response code } } } break; } s = strtok(NULL, "\012\015 |"); } gettimeofday(&server->packet_time1, NULL); server->map_name = strdup("N/A"); return (DONE_FORCE); }
// See the following for protocol details: // http://dev.kquery.com/index.php?article=42 query_status_t deal_with_gs2_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *ptr = rawpkt; char *end = rawpkt + pktlen; unsigned char type = 0; unsigned char no_players = 0; unsigned char total_players = 0; unsigned char no_teams = 0; unsigned char total_teams = 0; unsigned char no_headers = 0; char **headers = NULL; debug( 2, "processing packet..." ); if ( pktlen < 15 ) { // invalid packet? return PKT_ERROR; } server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL); } // Could check the header here should // match the 4 byte id sent ptr += 5; while ( 0 == type && ptr < end ) { // server info: // name value pairs null seperated // empty name && value signifies the end of section char *var, *val; int var_len, val_len; var = ptr; var_len = strlen( var ); if ( ptr + var_len + 2 > end ) { if ( 0 != var_len ) { malformed_packet( server, "no rule value" ); } else if ( get_player_info ) { malformed_packet( server, "no player headers" ); } return PKT_ERROR; } ptr += var_len + 1; val = ptr; val_len = strlen( val ); ptr += val_len + 1; debug( 2, "var:%s (%d)=%s (%d)\n", var, var_len, val, val_len ); // Lets see what we've got if ( 0 == strcmp( var, "hostname" ) ) { server->server_name = strdup( val ); } else if( 0 == strcmp( var, "game_id" ) ) { server->game = strdup( val ); } else if( 0 == strcmp( var, "gamever" ) ) { // format: // v1.0 server->protocol_version = atoi( val+1 ); add_rule( server, var, val, NO_FLAGS ); } else if( 0 == strcmp( var, "mapname" ) ) { server->map_name = strdup( val ); } else if( 0 == strcmp( var, "map" ) ) { // For BF2MC compatibility server->map_name = strdup( val ); } else if( 0 == strcmp( var, "maxplayers" ) ) { server->max_players = atoi( val ); } else if( 0 == strcmp( var, "numplayers" ) ) { server->num_players = no_players = atoi( val ); } else if( 0 == strcmp( var, "hostport" ) ) { change_server_port( server, atoi( val ), 0 ); } else if ( 0 == var_len ) { // check for end of section type = 1; } else { add_rule( server, var, val, NO_FLAGS ); } } if ( 1 != type ) { // no more info should be player headers here as we // requested it malformed_packet( server, "no player headers" ); return PKT_ERROR; } // player info header // format: // first byte = player count // followed by null seperated header no_players = (unsigned char)*ptr; debug( 2, "No Players:%d\n", no_players ); ptr++; if ( ptr >= end ) { malformed_packet( server, "no player headers" ); return PKT_ERROR; } while ( 1 == type && ptr < end ) { // first we have the headers null seperated char **tmpp; char *head = ptr; int head_len = strlen( head ); no_headers++; tmpp = (char**)realloc( headers, no_headers * sizeof( char* ) ); if ( NULL == tmpp ) { debug( 0, "Failed to realloc memory for headers\n" ); if ( NULL != headers ) { free( headers ); } return MEM_ERROR; } headers = tmpp; headers[no_headers-1] = head; ptr += head_len + 1; // end of headers check if ( 0x00 == *ptr ) { type = 2; ptr++; } debug( 2, "player header[%d] = '%s'", no_headers-1, head ); } if ( 2 != type ) { // no more info should be player info here as we // requested it malformed_packet( server, "no players" ); return PKT_ERROR; } while( 2 == type && ptr < end ) { // now each player details // add the player if ( 0x00 == *ptr ) { // no players if ( 0 != no_players ) { malformed_packet( server, "no players" ); return PKT_ERROR; } } else { struct player *player = add_player( server, total_players ); int i; for ( i = 0; i < no_headers; i++ ) { char *header = headers[i]; char *val; int val_len; if ( ptr >= end ) { malformed_packet( server, "short player detail" ); return PKT_ERROR; } val = ptr; val_len = strlen( val ); ptr += val_len + 1; // lets see what we got if ( 0 == strcmp( header, "player_" ) ) { player->name = strdup( val ); } else if ( 0 == strcmp( header, "score_" ) ) { player->score = atoi( val ); } else if ( 0 == strcmp( header, "deaths_" ) ) { player->deaths = atoi( val ); } else if ( 0 == strcmp( header, "ping_" ) ) { player->ping = atoi( val ); } else if ( 0 == strcmp( header, "kills_" ) ) { player->frags = atoi( val ); } else if ( 0 == strcmp( header, "team_" ) ) { player->team = atoi( val ); } else { int len = strlen( header ); if ( '_' == header[len-1] ) { header[len-1] = '\0'; } player_add_info( player, header, val, NO_FLAGS ); } debug( 2, "Player[%d][%s]=%s\n", total_players, headers[i], val ); } total_players++; } if ( total_players > no_players ) { malformed_packet( server, "to many players %d > %d", total_players, no_players ); return PKT_ERROR; } // check for end of player info if ( 0x00 == *ptr ) { if ( total_players != no_players ) { malformed_packet( server, "bad number of players %d != %d", total_players, no_players ); return PKT_ERROR; } type = 3; ptr++; } } if ( 3 != type ) { // no more info should be team info here as we // requested it malformed_packet( server, "no teams" ); return PKT_ERROR; } no_teams = (unsigned char)*ptr; ptr++; debug( 2, "No teams:%d\n", no_teams ); no_headers = 0; while ( 3 == type && ptr < end ) { // first we have the headers null seperated char **tmpp; char *head = ptr; int head_len = strlen( head ); no_headers++; tmpp = (char**)realloc( headers, no_headers * sizeof( char* ) ); if ( NULL == tmpp ) { debug( 0, "Failed to realloc memory for headers\n" ); if ( NULL != headers ) { free( headers ); } return MEM_ERROR; } headers = tmpp; headers[no_headers-1] = head; ptr += head_len + 1; // end of headers check if ( 0x00 == *ptr ) { type = 4; ptr++; } } if ( 4 != type ) { // no more info should be team info here as we // requested it malformed_packet( server, "no teams" ); return PKT_ERROR; } while( 4 == type && ptr < end ) { // now each teams details int i; for ( i = 0; i < no_headers; i++ ) { char *val; int val_len; if ( ptr >= end ) { malformed_packet( server, "short team detail" ); return PKT_ERROR; } val = ptr; val_len = strlen( val ); ptr += val_len + 1; // lets see what we got if ( 0 == strcmp( headers[i], "team_t" ) ) { // BF being stupid again teams 1 based instead of 0 players_set_teamname( server, total_teams + 1, val ); } debug( 2, "Team[%d][%s]=%s\n", total_teams, headers[i], val ); } total_teams++; if ( total_teams > no_teams ) { malformed_packet( server, "to many teams" ); return PKT_ERROR; } } return DONE_FORCE; }
void q_timer(int fd) { int i = 0, j = 0, k = 0, type = q_type; int nextpart = 0, num_players = 0, cheats = 0; struct quake_variable variable[50]; struct timeval tv; char status[65507], temp[1024]; char server_hostname[1024], server_maxclients[1024], server_mapname[1024]; char server_fraglimit[1024], server_timelimit[1024], server_game[1024]; /* ick. */ memset(&temp, 0, sizeof(temp)); memset(&server_hostname, 0, sizeof(server_hostname)); memset(&server_maxclients, 0, sizeof(server_maxclients)); memset(&server_mapname, 0, sizeof(server_mapname)); memset(&server_fraglimit, 0, sizeof(server_fraglimit)); memset(&server_timelimit, 0, sizeof(server_timelimit)); memset(&server_game, 0, sizeof(server_game)); /* now we should be expecting something back */ memset(&status, 0, sizeof(status)); if(recv(fd, status, 65507, 0) < 0) { put_it("Error receiving from %s: %s", q_server, strerror(errno)); privmsg(q_chan, "Error receiving from %s: %s", q_server, strerror(errno)); close_socketread(fd); querying = 0; return; } gettimeofday(&tv, NULL); close_socketread(fd); memset(&variable, 0, sizeof(variable)); /* now we have our info, but we still need to decode it! */ if(type == 1) i = 7; else if(type == 2) i = 11; else if(type == 3) i = 20; /* the following while loop copies all the variables from the status message into an array together with their value */ while (status[i] != '\n') { /* check whether it's time for a new variable */ if (status[i] == '\\') { if (nextpart) { nextpart = 0; variable[j].value[k] = '\0'; j++; } else { nextpart = 1; variable[j].name[k] = '\0'; } k = 0; } else { /* put our character in the correct position */ if (nextpart) variable[j].value[k] = status[i]; else variable[j].name[k] = status[i]; k++; } i++; } variable[j].value[k] = '\0'; /* now we can count how many players there are on the server */ i++; put_it(&status[i]); while (i < strlen(status)) { if (status[i] == '\n') { num_players++; } i++; } for (i = 0; i < 50; i++) { if(type != 3) { if(!strcmp("hostname", variable[i].name)) strcpy(server_hostname, variable[i].value); if(!strcmp("maxclients", variable[i].name)) strcpy(server_maxclients, variable[i].value); } else { if(!strcmp("sv_hostname", variable[i].name)) strcpy(server_hostname, variable[i].value); if(!strcmp("sv_maxclients", variable[i].name)) strcpy(server_maxclients, variable[i].value); if(!strcmp("g_gametype", variable[i].name)) { switch(atoi(variable[i].name)) { case 0: strcpy(server_game, "FFA"); break; case 1: strcpy(server_game, "DUEL"); break; case 3: strcpy(server_game, "TEAM DM"); break; case 4: strcpy(server_game, "CTF"); break; default: strcpy(server_game, "UNKNOWN"); break; } } } if(type == 1) { if(!strcmp("map", variable[i].name)) strcpy(server_mapname, variable[i].value); if(!strcmp("*gamedir", variable[i].name)) strcpy(server_game, variable[i].value); if(!strcmp("cheats", variable[i].name)) cheats = 1; } else { if(!strcmp("mapname", variable[i].name)) strcpy(server_mapname, variable[i].value); } if(type == 2) { if(!strcmp("gamename", variable[i].name)) strcpy(server_game, variable[i].value); } if(!strcmp("timelimit", variable[i].name)) strcpy(server_timelimit, variable[i].value); if(!strcmp("fraglimit", variable[i].name)) strcpy(server_fraglimit, variable[i].value); } if(type == 1) { snprintf(temp, 1024, "%s : players: %d/%s, ping: %d, map: %s, timelimit: %s, fraglimit: %s", server_hostname, num_players, server_maxclients, time_delta(&tv, &q_tv), server_mapname, server_timelimit, server_fraglimit); if(server_game[0] != '\0') { char temp2[1024]; snprintf(temp2, 1024, ", game: %s", server_game); strcat(temp, temp2); } if(cheats) strcat(temp, ", cheats enabled"); } if(type == 2) snprintf(temp, 1024, "%s : players: %d/%s, ping: %d, map: %s, timelimit: %s, fraglimit: %s, game: %s", server_hostname, num_players, server_maxclients, time_delta(&tv, &q_tv), server_mapname, server_timelimit, server_fraglimit, server_game); if(type == 3) snprintf(temp, 1024, "%s : players: %d/%s, ping: %d, map: %s, gametype: %s, timelimit: %s, fraglimit: %s", server_hostname, num_players, server_maxclients, time_delta(&tv, &q_tv), server_mapname, server_game, server_timelimit, server_fraglimit); put_it(temp); privmsg(q_chan, temp); querying = 0; }
static query_status_t _deal_with_doom3_packet( struct qserver *server, char *rawpkt, int pktlen, unsigned version ) { char *ptr = rawpkt; char *end = rawpkt + pktlen; int type = 0; int size = 0; int tail_size = 4; int viewers = 0; int tv = 0; unsigned num_players = 0; unsigned challenge = 0; unsigned protocolver = 0; char tmp[32]; server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); } else { gettimeofday( &server->packet_time1, NULL); } // Check if correct reply if ( pktlen < sizeof(doom3_inforesponse) +4 +4 +1 || memcmp( doom3_inforesponse, ptr, sizeof(doom3_inforesponse)) != 0 ) { malformed_packet(server, "too short or invalid response"); return PKT_ERROR; } ptr += sizeof(doom3_inforesponse); if ( 5 == version ) { // TaskID ptr += 4; // osmask + ranked tail_size++; } challenge = swap_long_from_little(ptr); ptr += 4; protocolver = swap_long_from_little(ptr); ptr += 4; snprintf(tmp, sizeof(tmp), "%u.%u", protocolver >> 16, protocolver & 0xFFFF); debug(2, "challenge: 0x%08X, protocol: %s (0x%X)", challenge, tmp, protocolver); server->protocol_version = protocolver; add_rule( server, "protocol", tmp, NO_FLAGS ); if ( 5 == version ) { // Size Long size = swap_long_from_little(ptr); debug( 2, "Size = %d", size ); ptr += 4; } // Commented out until we have a better way to specify the expected version // This is due to prey demo requiring version 4 yet prey retail version 3 /* if( protocolver >> 16 != version ) { malformed_packet(server, "protocol version %u, expected %u", protocolver >> 16, version ); return PKT_ERROR; } */ while ( ptr < end ) { // server info: // name value pairs null seperated // empty name && value signifies the end of section char *key, *val; unsigned keylen, vallen; key = ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "no rule key" ); return PKT_ERROR; } keylen = ptr - key; val = ++ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "no rule value" ); return PKT_ERROR; } vallen = ptr - val; ++ptr; if( keylen == 0 && vallen == 0 ) { type = 1; break; // end } debug( 2, "key:%s=%s:", key, val); // Lets see what we've got if ( 0 == strcasecmp( key, "si_name" ) ) { server->server_name = strdup( val ); } else if( 0 == strcasecmp( key, "fs_game" ) ) { server->game = strdup( val ); } #if 0 else if( 0 == strcasecmp( key, "si_version" ) ) { // format: x // DOOM 1.0.1262.win-x86 Jul 8 2004 16:46:37 server->protocol_version = atoi( val+1 ); } #endif else if( 0 == strcasecmp( key, "si_map" ) ) { if ( 5 == version || 6 == version ) { // ET:QW reports maps/<mapname>.entities // so we strip that here if it exists char *tmpp = strstr( val, ".entities" ); if ( NULL != tmpp ) { *tmpp = '\0'; } if ( 0 == strncmp( val, "maps/", 5 ) ) { val += 5; } } server->map_name = strdup( val ); } else if ( 0 == strcasecmp( key, "si_maxplayers" ) ) { server->max_players = atoi( val ); } else if ( 0 == strcasecmp( key, "ri_maxViewers" ) ) { char max[20]; sprintf( max, "%d", server->max_players ); add_rule( server, "si_maxplayers", max, NO_FLAGS ); server->max_players = atoi( val ); } else if ( 0 == strcasecmp( key, "ri_numViewers" ) ) { viewers = atoi( val ); tv = 1; } add_rule( server, key, val, NO_FLAGS ); } if ( type != 1 ) { // no more info should be player headers here as we // requested it malformed_packet( server, "player info missing" ); return PKT_ERROR; } // now each player details while( ptr < end - tail_size ) { struct player *player; char *val; unsigned char player_id = *ptr++; short ping = 0; unsigned rate = 0; if( ( 6 == version && MAX_WOLF_ASYNC_CLIENTS == player_id ) || MAX_DOOM3_ASYNC_CLIENTS == player_id ) { break; } debug( 2, "ID = %d\n", player_id ); // Note: id's are not steady if ( ptr + 7 > end ) // 2 ping + 4 rate + empty player name ('\0') { // run off the end and shouldnt have malformed_packet( server, "player info too short" ); return PKT_ERROR; } /* if ( 6 == version ) { // Playerid is broken in wolf its always 0 player_id = num_players; } */ player = add_player( server, player_id ); if( ! player ) { malformed_packet( server, "duplicate player id" ); return PKT_ERROR; } // doesnt support score so set a sensible default player->score = 0; player->frags = 0; // Ping ping = swap_short_from_little(ptr); player->ping = ping; ptr += 2; if ( 5 != version || 0xa0013 >= protocolver ) // No Rate in ETQW since v1.4 ( protocol v10.19 ) { // Rate rate = swap_long_from_little(ptr); { char buf[16]; snprintf(buf, sizeof(buf), "%u", rate); player_add_info(player, "rate", buf, NO_FLAGS); } ptr += 4; } if ( 5 == version && ( ( 0xd0009 == protocolver || 0xd000a == protocolver ) && 0 != num_players ) ) // v13.9 or v13.10 { // Fix the packet offset due to the single bit used for bot // which realigns at the byte boundary for the player name ptr++; } // Name val = ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "player name not null terminated" ); return PKT_ERROR; } player->name = strdup( val ); ptr++; switch( version ) { case 2: // Quake 4 val = ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "player clan not null terminated" ); return PKT_ERROR; } player->tribe_tag = strdup( val ); ptr++; debug( 2, "Player[%d] = %s, ping %hu, rate %u, id %hhu, clan %s", num_players, player->name, ping, rate, player_id, player->tribe_tag); break; case 5: // ETQW case 6: // Wolfenstien if ( 0xa0011 <= protocolver ) // clan tag since 10.17 { // clantag position ptr++; // clantag val = ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "player clan not null terminated" ); return PKT_ERROR; } player->tribe_tag = strdup( val ); ptr++; } // Bot flag if ( 0xd0009 == protocolver || 0xd000a == protocolver ) // v13.9 or v13.10 { // Bot flag is a single bit so need to realign everything from here on in :( int i; unsigned char *tp = (unsigned char*)ptr; player->type_flag = (*tp)<<7; // alignment is reset at the end for( i = 0; i < 8 && tp < (unsigned char*)end; i++ ) { *tp = (*tp)>>1 | *(tp+1)<<7; tp++; } } else { player->type_flag = *ptr++; } if ( 0xa0011 <= protocolver ) // clan tag since 10.17 { debug( 2, "Player[%d] = %s, ping %hu, rate %u, id %hhu, bot %hu, clan %s", num_players, player->name, ping, rate, player_id, player->type_flag, player->tribe_tag); } else { debug( 2, "Player[%d] = %s, ping %hu, rate %u, id %hhu, bot %hu", num_players, player->name, ping, rate, player_id, player->type_flag ); } break; default: debug( 2, "Player[%d] = %s, ping %hu, rate %u, id %hhu", num_players, player->name, ping, rate, player_id ); }
query_status_t deal_with_gps_packet(struct qserver *server, char *rawpkt, int pktlen) { char *s, *key, *value, *end; struct player *player = NULL; int id_major = 0, id_minor = 0, final = 0, player_num; char tmp[256]; debug(2, "processing..."); server->n_servers++; if (server->server_name == NULL) { server->ping_total += time_delta(&packet_recv_time, &server->packet_time1); } else { gettimeofday(&server->packet_time1, NULL); } /* * // We're using the saved_data a bit differently here to track received * // packets. * // pkt_id is the id_major from the \queryid\ * // pkt_max is the total number of packets expected * // pkt_index is a bit mask of the packets received. The id_minor of * // \queryid\ provides packet numbers (1 through pkt_max). */ if (server->saved_data.pkt_index == -1) { server->saved_data.pkt_index = 0; } rawpkt[pktlen] = '\0'; end = &rawpkt[pktlen]; s = rawpkt; while (*s) { // find the '\' while (*s && *s == '\\') { s++; } if (!*s) { // out of packet break; } // Start of key key = s; // while we still have data and its not a '\' while (*s && *s != '\\') { s++; } if (!*s) { // out of packet break; } // Terminate the key *s++ = '\0'; // Now for the value value = s; // while we still have data and its not a '\' while (*s && *s != '\\') { s++; } if (s[0] && s[1]) { //fprintf( stderr, "%s = %s\n", key, value ); if (!isalpha((unsigned char)s[1])) { // escape char? s++; // while we still have data and its not a '\' while (*s && *s != '\\') { s++; } } else if ( isalpha((unsigned char)s[1]) && (0 == strncmp(key, "player_", 7)) && (0 != strcmp(key, "player_flags")) ) { // possible '\' in player name if (!gps_player_info_key(s + 1, end)) { // yep there was an escape in the player name s++; // while we still have data and its not a '\' while (*s && *s != '\\') { s++; } } } } if (*s) { *s++ = '\0'; } //fprintf( stderr, "%s = %s\n", key, value ); if (*value == '\0') { if (strcmp(key, "final") == 0) { final = 1; if (id_minor > server->saved_data.pkt_max) { server->saved_data.pkt_max = id_minor; } continue; } } /* This must be done before looking for player info because * "queryid" is a valid according to gps_player_info_key(). */ if (strcmp(key, "queryid") == 0) { sscanf(value, "%d.%d", &id_major, &id_minor); if (server->saved_data.pkt_id == 0) { server->saved_data.pkt_id = id_major; } if (id_major == server->saved_data.pkt_id) { if (id_minor > 0) { // pkt_index is bitmask of packets recieved server->saved_data.pkt_index |= 1 << (id_minor - 1); } if (final && (id_minor > server->saved_data.pkt_max)) { server->saved_data.pkt_max = id_minor; } } continue; }
query_status_t deal_with_ts2_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *s, *end; int ping, connect_time, mode = 0; char name[256]; debug( 2, "processing..." ); server->n_servers++; server->n_requests++; server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); if ( 0 == pktlen ) { // Invalid password return REQ_ERROR; } rawpkt[pktlen]= '\0'; end = &rawpkt[pktlen]; s = rawpkt; s = strtok( rawpkt, "\015\012" ); while ( NULL != s ) { if ( 0 == mode ) { // Rules char *key = s; char *value = strchr( key, '=' ); if ( NULL != value ) { // Server Rule *value = '\0'; value++; if ( 0 == strcmp( "server_name", key ) ) { server->server_name = strdup( value ); } else if ( 0 == strcmp( "server_udpport", key ) ) { change_server_port( server, atoi( value ), 0 ); add_rule( server, key, value, NO_FLAGS ); } else if ( 0 == strcmp( "server_maxusers", key ) ) { server->max_players = atoi( value ); } else if ( 0 == strcmp( "server_currentusers", key ) ) { server->num_players = atoi( value); } else { add_rule( server, key, value, NO_FLAGS); } } else if ( 0 == strcmp( "OK", s ) ) { // end of rules request server->saved_data.pkt_index--; mode++; } else if ( 0 == strcmp( "[TS]", s ) ) { // nothing to do } else if ( 0 == strcmp( "ERROR, invalid id", s ) ) { // bad server server->server_name = DOWN; server->saved_data.pkt_index = 0; } } else if ( 1 == mode ) { // Player info if ( 3 == sscanf( s, "%*d %*d %*d %*d %*d %*d %*d %d %d %*d %*d %*d %*d \"0.0.0.0\" \"%255[^\"]", &ping, &connect_time, name ) ) { // Player info struct player *player = add_player( server, server->n_player_info ); if ( NULL != player ) { player->name = strdup( name ); player->ping = ping; player->connect_time = connect_time; } } else if ( 0 == strcmp( "OK", s ) ) { // end of rules request server->saved_data.pkt_index--; mode++; } else if ( 0 == strcmp( "[TS]", s ) ) { // nothing to do } else if ( 0 == strcmp( "ERROR, invalid id", s ) ) { // bad server server->server_name = DOWN; server->saved_data.pkt_index = 0; } } s = strtok( NULL, "\015\012" ); } gettimeofday( &server->packet_time1, NULL ); if ( 0 == server->saved_data.pkt_index ) { server->map_name = strdup( "N/A" ); return DONE_FORCE; } return INPROGRESS; }
int main(int argc, char **argv) { VGA_Parms VGAParms; mod_parms modParms; rt_buffer baseBandBuffer; input_scale_struct inputStruct; pthread_t thread; int i; long long sampleCount=0; long long sampleWrittenCount=0; int fc = 35000000; int rate = 146200000; int fs = 1500000; int inputShift = 0; //input>>inputShift int carrierShift=0; //carrier>>inputShift char * inputName = "stdin"; char * outputName = "stdout"; FILE * inPipe; FILE * outPipe; int bInvert; struct timeval tv1, tv2; unsigned int offset_s=0; unsigned int offset_c=0; int outputBufferSize; int * outputBuffer; long long k_s; //2^16*fs/rate long long k_c; //2^16*fc/rate int ts_us,us; VGAParms.width = 40; VGAParms.wtotal = 50; VGAParms.height = 40; VGAParms.htotal = 42; VGAParms.outputShiftRight = 0; //shift right after multiply VGAParms.outputMask=0xFFFFFFFF; //clamp ouput value with mask VGAParms.outputShiftLeft = 0; //left shift after clamping VGAParms.outputAddOffset = 0; VGAParms.vsyncOffset = 0; /* Signal parameters */ // Get Input parameters while ((i = getopt(argc, argv, "w:W:h:H:r:c:s:i:o:C:I:O:a:v:")) != -1) { switch(i) { case 'w': VGAParms.width = atoi(optarg); break; case 'W': VGAParms.wtotal = atoi(optarg); break; case 'h': VGAParms.height = atoi(optarg); break; case 'H': VGAParms.htotal = atoi(optarg); break; case 'r': rate = atoi(optarg); break; case 'c': fc = atoi(optarg); break; case 's': fs = atoi(optarg); break; case 'i': inputName = strdup(optarg); break; case 'o': outputName = strdup(optarg); break; case 'C': carrierShift = atoi(optarg); break; case 'I': inputShift = atoi(optarg); break; case 'O': VGAParms.outputShiftRight = atoi(optarg); break; case 'M': sscanf(optarg, "%x", &VGAParms.outputMask); break; case 'L': VGAParms.outputShiftLeft = atoi(optarg); break; case 'a': VGAParms.outputAddOffset = atoi(optarg); break; case 'v': VGAParms.vsyncOffset = atoi(optarg); break; } } if(argc==1) { printf("Usage: testmod -w [width] -W [wtotal] -h [height] -H [htotal] \n"); printf(" -r [rate] -c [CarrierFreq] -s [SampleFreq] -i [InputFile]\n"); printf(" -o [outfile] -C [CarrierSignalShift] -I [InputSignalShift]\n"); printf(" -O [OutputShiftRight] -M [OutputMask] -L [OutputShiftLeft]\n"); printf(" -f [OutputAddOffset] \n"); } if(strcmp(inputName,"stdin")!=0) { inPipe = fopen(inputName,"rb"); if(!inPipe) { fprintf(stderr, "Cannon open file %s",inputName); exit(-1); } }else inPipe= stdin; if(strcmp(outputName,"stdout")!=0) { outPipe = fopen(outputName,"wb"); if(!outPipe) { fprintf(stderr, "Cannon open file %s",outputName); exit(-1); } }else outPipe= stdout; VGAParms.wtotal = max(VGAParms.wtotal,VGAParms.width); VGAParms.htotal = max(VGAParms.htotal,VGAParms.height); if(fc<0) { fc=-fc; modParms.Qsign=-1; }else modParms.Qsign=1; modParms.k_s = ((long long)(1<<OFFSET_BITS))*fs/rate; modParms.k_c = ((long long) (1<<OFFSET_BITS))*fc*COS_BUFFER_SIZE/rate; modParms.offset_s=0; modParms.offset_c=0; outputBufferSize = VGAParms.width*VGAParms.height; outputBuffer = malloc( outputBufferSize*sizeof(int)); InitBuffer(&baseBandBuffer,outputBufferSize); initCosineTable((float)1/(1<<carrierShift)); ts_us = 1000000/fs; inputStruct.buf = &baseBandBuffer; inputStruct.inputFile = inPipe; inputStruct.scale=((float)1/(1<<inputShift)); if (pthread_create(&thread, NULL, readInputScale, &inputStruct)) { printf("ERROR; Could not create read thread\n"); exit(-1); } fprintf(stderr, "buffering input..."); while (IsBufferEmpty(&baseBandBuffer)) usleep(100000); fprintf(stderr, "done %d\n",GetBufferFullness(&baseBandBuffer)); fprintf(stderr, "\n"); fprintf(stderr, "SampleRate: %3.2f MHz\n", (double)rate/1000000); fprintf(stderr, "Carrier: %3.2f MHz\n", (double)fc/1000000); fprintf(stderr, "SymbolRate: %3.2f\n", (double)fs); fprintf(stderr, "\n"); gettimeofday(&tv1, 0); while(!IsFlushComplete(&baseBandBuffer)) { if(GetBufferFullness(&baseBandBuffer)>=outputBufferSize || IsFlushing(&baseBandBuffer)) { sampleWrittenCount += ComplexModulate(&baseBandBuffer, outputBuffer, &modParms, &VGAParms); sampleCount += fwrite(outputBuffer, sizeof(int), outputBufferSize, outPipe); gettimeofday(&tv2, 0); us = time_delta(&tv1, &tv2); us = ts_us - us; if (us > 0) usleep(us); gettimeofday(&tv1, 0); } } fprintf(stderr,"Sample : %llu\n",sampleCount); fprintf(stderr,"Sample Written: %llu\n",sampleWrittenCount); DeInitBuffer(&baseBandBuffer); if(inPipe!=stdin) fclose(inPipe); if(outPipe!=stdout) fclose(outPipe); pthread_exit(NULL); }
query_status_t deal_with_gs3_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *ptr = rawpkt; unsigned int pkt_id; int pkt_index; unsigned char flag; unsigned int pkti, final; debug( 2, "packet n_requests %d, retry1 %d, n_retries %d, delta %d", server->n_requests, server->retry1, n_retries, time_delta( &packet_recv_time, &server->packet_time1 ) ); server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); if ( 7 == pktlen && 0x09 == *ptr ) { // gs4 query sent to a gs3 server // switch protocols and try again // Correct the stats due to two phase protocol int i; server_type *gs3_type = &builtin_types[50]; debug( 3, "Attempting gs3 fallback from gs4" ); server->retry1++; if ( GAMESPY3_PROTOCOL_SERVER != gs3_type->id ) { // Static coding failure do it the hard way debug( 1, "gs3 static lookup failure, using dynamic lookup" ); for( i = 0; i < GAMESPY3_PROTOCOL_SERVER; i++ ) { if ( GAMESPY3_PROTOCOL_SERVER == builtin_types[i].id ) { // found it gs3_type = &builtin_types[i]; i = GAMESPY3_PROTOCOL_SERVER; } } if ( GAMESPY3_PROTOCOL_SERVER != gs3_type->id ) { malformed_packet( server, "GS3 protocol not found" ); return PKT_ERROR; } } server->type = gs3_type; return send_gs3_request_packet( server ); } if ( pktlen < 12 ) { // invalid packet? malformed_packet( server, "too short" ); return PKT_ERROR; } if ( 0x09 == *ptr ) { // challenge response // Could check the header here should // match the 4 byte id sent ptr++; memcpy( &pkt_id, ptr, 4 ); ptr += 4; server->challenge = atoi( ptr ); debug( 3, "Challenge: %ld", server->challenge ); server->retry1++; return send_gs3_request_packet( server ); } if ( 0x00 != *ptr ) { malformed_packet( server, "bad initial byte '%hhx'", *ptr ); return PKT_ERROR; } ptr++; server->n_servers++; // Could check the header here should // match the 4 byte id sent memcpy( &pkt_id, ptr, 4 ); ptr += 4; // Next we have the splitnum details if ( 0 != strncmp( ptr, "splitnum", 8 ) ) { if ( server->flags & TF_STATUS_QUERY ) { // we have the status response return deal_with_gs3_status( server, ptr, pktlen - ( ptr - rawpkt ) ); } else { malformed_packet( server, "missing splitnum" ); return PKT_ERROR; } } ptr += 9; pkt_index = ((unsigned char)*ptr) & 127; final = ((unsigned char)*ptr) >> 7;
query_status_t deal_with_ottd_packet(struct qserver *server, char *rawpkt, int pktlen) { unsigned char *ptr = (unsigned char*)rawpkt; unsigned char *end = (unsigned char*)(rawpkt + pktlen); unsigned char type; char* str; char buf[32]; unsigned ver; server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); server->n_requests++; } else { gettimeofday( &server->packet_time1, NULL); } FAIL_IF(pktlen < 4 || swap_short_from_little(rawpkt) > pktlen, "invalid packet"); type = ptr[2]; ver = ptr[3]; ptr += 4; debug(3, "len %hu type %hhu ver %hhu", swap_short_from_little(rawpkt), type, ver); FAIL_IF(ver != 4 && ver != 5, "only version 4 and 5 servers are supported"); if(type == 1) // info packet { unsigned numgrf = *ptr; FAIL_IF(ptr + numgrf * 20 + 1 > end, "invalid newgrf number"); ptr += numgrf * 20 + 1; snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr)); add_rule(server, "date_days", buf, NO_FLAGS); ptr += 4; snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr)); add_rule(server, "startdate_days", buf, NO_FLAGS); ptr += 4; FAIL_IF(ptr + 3 > end, "invalid packet"); snprintf(buf, sizeof(buf), "%hhu", ptr[0]); add_rule(server, "maxcompanies", buf, NO_FLAGS); snprintf(buf, sizeof(buf), "%hhu", ptr[1]); add_rule(server, "numcompanies", buf, NO_FLAGS); server->max_spectators = ptr[2]; ptr += 3; GET_STRING; server->server_name = strdup(str); GET_STRING; add_rule(server, "version", str, NO_FLAGS); FAIL_IF(ptr + 7 > end, "invalid packet"); { static const char* langs[] = { "any", "English", "German", "French" }; unsigned i = *ptr++; if(i > 3) i = 0; add_rule(server, "language", (char*)langs[i], NO_FLAGS); } add_rule(server, "password", *ptr++ ? "1" : "0", NO_FLAGS); server->max_players = *ptr++; server->num_players = *ptr++; server->num_spectators = *ptr++; GET_STRING; server->map_name = strdup(str); snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr)); add_rule(server, "map_width", buf, NO_FLAGS); snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr)); add_rule(server, "map_height", buf, NO_FLAGS); { static const char* sets[] = { "temperate", "arctic", "desert", "toyland" }; unsigned i = *ptr++; if(i > 3) i = 0; add_rule(server, "map_set", (char*)sets[i], NO_FLAGS); } add_rule(server, "dedicated", *ptr++ ? "1" : "0", NO_FLAGS); } else if(type == 3) // player packet { unsigned i, j; INVALID_IF(ptr + 2 > end); server->num_players = *ptr++; for(i = 0; i < server->num_players; ++i) { unsigned long long lli; struct player* player; unsigned char nr; nr = *ptr++; debug(3, "player number %d", nr); player = add_player(server, i); FAIL_IF(!player, "can't allocate player"); GET_STRING; player->name = strdup(str); debug(3, "name %s", str); player->frags = 0; INVALID_IF(ptr + 4 + 3*8 + 2 + 1 + 2*MAX_VEHICLE_TYPES + 2*MAX_STATION_TYPES > end); snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr)); player_add_info(player, "startdate", buf, 0); ptr += 4; lli = swap_long_from_little(ptr+4); lli <<= 32; lli += swap_long_from_little(ptr); snprintf(buf, sizeof(buf), "%lld", lli); player_add_info(player, "value", buf, 0); ptr += 8; lli = swap_long_from_little(ptr+4); lli <<= 32; lli = swap_long_from_little(ptr); snprintf(buf, sizeof(buf), "%lld", lli); player_add_info(player, "money", buf, 0); ptr += 8; lli = swap_long_from_little(ptr+4); lli <<= 32; lli += swap_long_from_little(ptr); snprintf(buf, sizeof(buf), "%lld", lli); player_add_info(player, "income", buf, 0); ptr += 8; snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr)); player_add_info(player, "performance", buf, 0); ptr += 2; player_add_info(player, "password", *ptr?"1":"0", 0); ++ptr; for (j = 0; j < MAX_VEHICLE_TYPES; ++j) { snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr)); player_add_info(player, (char*)vehicle_types[j], buf, 0); ptr += 2; } for (j = 0; j < MAX_STATION_TYPES; ++j) { snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr)); player_add_info(player, (char*)station_types[j], buf, 0); ptr += 2; } if (ver != 5) { // connections while(ptr + 1 < end && *ptr) { ++ptr; GET_STRING; // client name debug(3, "%s played by %s", str, player->name); GET_STRING; // id INVALID_IF(ptr + 4 > end); ptr += 4; } ++ptr; // record terminated by zero byte } } // spectators while(ptr + 1 < end && *ptr) { ++ptr; GET_STRING; // client name debug(3, "spectator %s", str); GET_STRING; // id INVALID_IF(ptr + 4 > end); ptr += 4; } ++ptr; // record terminated by zero byte server->next_rule = NO_SERVER_RULES; // we're done server->next_player_info = server->num_players; // we're done } else { malformed_packet( server, "invalid type" ); return PKT_ERROR; } server->retry1 = n_retries; // we're done with this packet, reset retry counter return DONE_AUTO; }