LICENSE: The Artistic License 2.0 /* * qstat.h * by Steve Jankowski * steve@qstat.org * http://www.qstat.org * * Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski */ { /* World in Confict PROTOCOL */ WIC_PROTOCOL_SERVER, /* id */ "WICS", /* type_prefix */ "wics", /* type_string */ "-wics", /* type_option */ "World in Conflict", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ TF_TCP_CONNECT|TF_QUERY_ARG_REQUIRED|TF_QUERY_ARG, /* flags */ "N/A", /* game_rule */ "WICPROTOCOL", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_wic_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_wic_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_wic_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_wic_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_wic_packet, /* packet_func */ }, /* * qstat 2.8 * by Steve Jankowski * * World in Conflict Protocol * Copyright 2007 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms * */ #include #ifndef _WIN32 #include #endif #include #include #include #include "debug.h" #include "qstat.h" #include "packet_manip.h" query_status_t send_wic_request_packet( struct qserver *server ) { char buf[256]; int serverport = get_param_i_value( server, "port", 0 ); char *password = get_param_value( server, "password", "N/A" ); change_server_port( server, serverport, 1 ); if ( get_player_info ) { server->flags |= TF_PLAYER_QUERY|TF_RULES_QUERY; sprintf( buf, "%s\x0d\x0a/listsettings\x0d\x0a/listplayers\x0d\x0a/exit\x0d\x0a", password ); server->saved_data.pkt_index = 2; } else { server->flags |= TF_STATUS_QUERY; sprintf( buf, "%s\x0d\x0a/listsettings\x0d\x0a/exit\x0d\x0a", password ); server->saved_data.pkt_index = 1; } return send_packet( server, buf, strlen( buf ) ); } query_status_t deal_with_wic_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *s, *end, *team = NULL; int mode = server->n_servers, slot, score; char name[256], role[256]; debug( 2, "processing 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 ); server->n_requests++; if ( 0 == pktlen ) { // Invalid password return REQ_ERROR; } gettimeofday( &server->packet_time1, NULL); rawpkt[pktlen]= '\0'; end = &rawpkt[pktlen]; s = rawpkt; while ( NULL != s ) { int len = strlen( s ); *(s + len - 2) = '\0'; // strip off \x0D\x0A debug( 2, "Line[%d]: %s", mode, s ); if ( 0 == mode ) { // Settings // TODO: make parse safe if ( 0 == strncmp( s, "Settings: ", 9 ) ) { // Server Rule char *key = s + 10; char *value = strchr( key, ' ' ); *value = '\0'; value++; debug( 2, "key: '%s' = '%s'", key, value ); if ( 0 == strcmp( "myGameName", key ) ) { server->server_name = strdup( value ); } else if ( 0 == strcmp( "myMapFilename", key ) ) { server->map_name = strdup( value ); } else if ( 0 == strcmp( "myMaxPlayers", key ) ) { server->max_players = atoi( value ); } else if ( 0 == strcmp( "myCurrentNumberOfPlayers", key ) ) { server->num_players = atoi( value); } else { add_rule( server, key, value, NO_FLAGS ); } } else if ( 0 == strcmp( "Listing players", s ) ) { // end of rules request server->saved_data.pkt_index--; mode++; } else if ( 0 == strcmp( "Exit confirmed.", s ) ) { server->n_servers = mode; return DONE_FORCE; } } else if ( 1 == mode ) { // Player info if ( 0 == strncmp( s, "Team: ", 6 ) ) { team = s + 6; debug( 2, "Team: %s", team ); } else if ( 4 == sscanf( s, "Slot: %d Role: %s Score: %d Name: %255[^\x0d\x0a]", &slot, role, &score, name ) ) { // Player info struct player *player = add_player( server, server->n_player_info ); if ( NULL != player ) { player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; player->name = strdup( name ); player->score = score; player->team_name = team; player->tribe_tag = strdup( role ); // Indicate if its a bot player->type_flag = ( 0 == strcmp( name, "Computer: Balanced" ) ) ? 1 : 0; } debug( 2, "player %d, role %s, score %d, name %s", slot, role, score, name ); } else if ( 3 == sscanf( s, "Slot: %d Role: Score: %d Name: %255[^\x0d\x0a]", &slot, &score, name ) ) { // Player info struct player *player = add_player( server, server->n_player_info ); if ( NULL != player ) { player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; player->name = strdup( name ); player->score = score; player->team_name = team; // Indicate if its a bot player->type_flag = ( 0 == strcmp( name, "Computer: Balanced" ) ) ? 1 : 0; } debug( 2, "player %d, score %d, name %s", slot, score, name ); } else if ( 0 == strcmp( "Exit confirmed.", s ) ) { server->n_servers = mode; return DONE_FORCE; } } s += len; if ( s + 1 < end ) { s++; // next line } else { s = NULL; } } server->n_servers = mode; if ( 0 == server->saved_data.pkt_index ) { server->map_name = strdup( "N/A" ); return DONE_FORCE; } return INPROGRESS; }