Server stat tool and script

Server stat tool and script

Postby orbitaldecay » 26 Jul 2011, 01:56

Hey all. I wrote a simple program for querying servers for connected players, game time remaining, etc on version 1.1. Feel free to do whatever you want with it. I'm using it with some bash scripts to make graphs of my server usage. It only compiles under *nix (gcc retool.c -o retool), but shouldn't be hard to port if you know any C.

Basically you use it like
{l Code}: {l Select All Code}
./retool <server ip> <server port> <fields>

where fields is a string of numbers representing stats you'd like it to spit out. See below for example.

Edit: Quick note, the port which the server receives queries on is +1 from the game port. For example, play.redeclipse.net (74.82.3.216) runs on game port 28801. You would direct queries to port 28802. If you wanted to know the number of connected clients and the maximum number of connected clients, you could run "./retool 74.82.3.216 28802 06".

{l Code}: {l Select All Code}
/* retool.c - a server stat tool for red eclipse v1.1 */

#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>

void parse_stats(unsigned char *buf, size_t len, int *stats);

int main(int argc, char **argv)
{
    struct sockaddr_in  si_other;
    int                 slen;
    char                buf[64];
    int                 stats[10];
    int                 sock;
    int                 result;
    int                 i, k;

    if (argc != 4)
    {
        fprintf(stderr, "usage: ./retool <server ip> <port> <stats>\n");
        exit(1);
    }

    slen = sizeof(si_other);
    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == -1)
    {
        fprintf(stderr, "Cannot create socket.\n");
        exit(1);
    }

    memset((char *) &si_other, 0, slen);

    si_other.sin_family = AF_INET;
    si_other.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], &si_other.sin_addr) == 0)
    {
        fprintf(stderr, "Failed to locate %s!.\n", argv[1]);
        exit(1);
    }
   
    /* ^shrugs^ - it works */
    buf[0] = 0x81;
    buf[1] = 0xE1;
    buf[2] = 0x38;
    buf[3] = 0x02;

    result = sendto(sock, buf, 4, 0, (struct sockaddr *)&si_other, slen);
    if (result == -1)
    {
        fprintf(stderr, "Sending failed.\n");
        exit(1);
    }

    result = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&si_other, &slen);
    if (result == -1)
    {
        fprintf(stderr, "Receiving failed.\n");
        exit(1);
    }

    parse_stats(buf, sizeof(buf), stats);

    char *field = argv[3];
    for (i = 0; i < strlen(argv[3]); i++)
    {

    /*
        Fields:
   
        0   Connected Clients
        1   Always equal to 8
        2   Game Version
        3   Game Mode
        4   Mutators
        5   Time Remaining (in seconds)
        6   Max Clients
        7   Passworded?
        8   Numgamevars
        9   Numgamemods
    */

        if ((field[i] >= '0') || (field[i] <= '9'))
            printf("%d ", stats[field[i] - '0']);
    }
    printf("\n");
    fflush(stdout);
    exit(0);
}


/* See engine/server.cpp line 161 of v1.1 */
void parse_stats(unsigned char *buf, size_t len, int *stats) {

    int             i, c, n, k;
   
    i = 4;
    k = 0;

    while ((k < 10) && (i < len))
    {
        c = (char)buf[i];
        i++;
        if ((c == -128) && (i + 2 < len))
        {
            stats[k] = buf[i];
            stats[k] |= buf[i + 1] << 8;
            i+=2;
        }
        else if ((c == -127) && (i + 4 < len))
        {
            stats[k] = buf[i];
            stats[k] |= buf[i + 1] << 8;
            stats[k] |= buf[i + 2] << 16;
            stats[k] |= buf[i + 3] << 24;
            i+=4;
        }
        else
        {
            stats[k] = c;
        }
        k++;
    }
}


Example bash script:
{l Code}: {l Select All Code}
#!/bin/bash

IP=$1
PORT=$2

# Which fields to include in the output.  Fields are output in the order
# in which they are provided.  They correspond to the following attributes:
#
#    0   Connected Clients
#    1   Always equal to 8
#    2   Game Version
#    3   Game Mode
#    4   Mutators
#    5   Time Remaining (in seconds)
#    6   Max Clients
#    7   Does server have password?
#    8   Numgamevars
#    9   Numgamemods

# This will output connected players, max players, time remaining (in that order)
FIELDS="065"

STATS="$(./retool $IP $PORT $FIELDS)"
printf "Players %d/%d (%ds remaining)\n" ${STATS[0]} ${STATS[1]} ${STATS[2]}
exit 0
[ Wazu Clan ][ irc.wazuclan.com #wazuclan ][ http://www.orbitaldecay.com ]
User avatar
orbitaldecay
 
Posts: 180
Joined: 12 May 2011, 00:32
Location: Baltimore, MD, US

Re: Server stat tool and script

Postby riidom » 26 Jul 2011, 02:50

I dont understand much of that, but would it be possible with that to make a server list (like you said, with player number, time left etc - or in other words, like ingame in server menu) that is watchable from redeclipse.net ?

Because... that would be pretty cool I think! ;)
User avatar
riidom
 
Posts: 218
Joined: 25 Jan 2010, 02:02

Re: Server stat tool and script

Postby orbitaldecay » 26 Jul 2011, 02:57

Sure, the code I wrote doesn't talk to the master server at all, but that wouldn't be hard to write.
[ Wazu Clan ][ irc.wazuclan.com #wazuclan ][ http://www.orbitaldecay.com ]
User avatar
orbitaldecay
 
Posts: 180
Joined: 12 May 2011, 00:32
Location: Baltimore, MD, US

Re: Server stat tool and script

Postby sireus » 26 Jul 2011, 09:53

Nice! I wrote something like that in Perl, but C is better :D
orbitaldecay {l Wrote}:
{l Code}: {l Select All Code}
/* ^shrugs^ - it works */


Yeah, you can send anything you like, 1 byte is sufficient if you don't actually use it. AFAIK, the serverbrowser uses it to measure ping (btw, that's something you could do too ;) )
You probably know that already, but you can also retrieve the map name, server description, and a list with the names of all players on the server. That's the stuff after numgamemods.
sireus
 
Posts: 109
Joined: 24 May 2011, 20:10

Re: Server stat tool and script

Postby qreeves » 26 Jul 2011, 10:43

Quinton "quin" Reeves | Lead Developer, Red Eclipse | http://redeclipse.net/ | http://www.facebook.com/redeclipse.net
User avatar
qreeves
 
Posts: 1294
Joined: 17 Mar 2011, 03:46
Location: Queensland, Australia

Re: Server stat tool and script

Postby orbitaldecay » 27 Jul 2011, 13:19

Sweet, thanks :D
[ Wazu Clan ][ irc.wazuclan.com #wazuclan ][ http://www.orbitaldecay.com ]
User avatar
orbitaldecay
 
Posts: 180
Joined: 12 May 2011, 00:32
Location: Baltimore, MD, US

Who is online

Users browsing this forum: No registered users and 0 guests