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 <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#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;
}

