/*	Tony Watson (aka Alascom) 12 Nov 2003

	Client program to make a UDP socket connection to a CoD server
	to get the status of a given server and format output in 
	HTML.  Intended to be used as a CGI-Script for www.terrorist.net

	INSTALL: find line 51(or so) in the program, it looks like this;
		remoteHost = "172.16.0.100";
	Edit the IP address to that of your Call of Duty server.
	Then compile with gcc codwatch.c -o codwatch.
	Copy the codwatch program to your CGI-BIN directory and it
	make sure its executable.  The program will make UDP port 28960
	connections to your server to retrieve the status of the server
	every 5 seconds (change META Refresh tag on line 47 if you want
	a different refresh rate).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int getinput(int sock);
int results(char * stats,int * y);

int main(int argc, char *argv[])
{
	int udpSocket = 0,
	    remotePort = 0,
	    status = 0,
	    size = 0,
	    serverLength = 0,
	    c = 0;
	struct sockaddr_in serverName = { 0 };
	struct hostent *hostPtr = NULL;
	char *remoteHost = NULL;
	char mesgout[1024000] = "";
	char * mesgoutptr = mesgout;
	char mesgin[1024000] = "";
	char * mesginptr = mesgin;

	printf("Content-type: text/html\n\n");
	printf("<HTML><HEAD>\n");
	printf("<META HTTP-EQUIV=Refresh CONTENT=\"5;");
	printf(" URL=http://www.terrorist.net/cgi-bin/cod\">\n");
	printf("<BODY bgcolor=\"000000\" text=\"00FF00\">\n");
	printf("<h3><IMAGE SRC=http://www.terrorist.net/images/cod.jpg height=100 align=center>\n");
	printf("CoD.TERRORIST.NET (68.74.97.98)</h3><p>\n\n");
	remoteHost = "172.16.0.100";
	remotePort = 28960;

	udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	hostPtr = gethostbyname(remoteHost);
	serverName.sin_family = AF_INET;
	serverName.sin_port = htons(remotePort);
	memcpy(&serverName.sin_addr, hostPtr->h_addr_list[0], hostPtr->h_length);
	memset(mesgout,0,strlen(mesgout));
	strcpy(mesgout,"    getstatus     ");
	mesgout[0]=0xff;
	mesgout[1]=0xff;
	mesgout[2]=0xff;
	mesgout[3]=0xff;
	mesgout[13]=0x0a;
	mesgout[14]=0x00;
	mesgout[15]=0x00;
	mesgout[16]=0x00;
	mesgout[17]=0x00;
	
 	size=strlen(mesgout);
	status = connect(udpSocket,
			(struct sockaddr *) &serverName,
			sizeof(struct sockaddr_in));
	size = send(udpSocket, mesgout, size,0);
	bzero(mesginptr,sizeof(mesgin));
	getinput(udpSocket);
	return 0;
}


int getinput(int sock)
{
#define BUFFSIZE 1024000

  struct sockaddr_in host;
  char buff[BUFFSIZE];
  int hostsize, x, sel, i;
  unsigned long *pdw;
  unsigned char *ptr;
  struct timeval tv;
  fd_set fds;

  FD_ZERO(&fds);
  FD_SET(sock, &fds);
  tv.tv_sec = 10;
  tv.tv_usec = 0;
  hostsize = sizeof(host);
  
  while( (sel = select(sock+1, &fds, NULL, NULL, &tv)) > 0 )
    {
      tv.tv_sec = 10;
      tv.tv_usec = 0;
      if ( (x = recvfrom(sock, buff, BUFFSIZE, 0, (struct sockaddr *)&host,
			 &hostsize)) <= 0) continue;
      results(buff,&x);
      return 0;
    }

  if (sel == 0) 
  {
    printf("Timeout on wait (no response for 10 seconds):\n");
  }
  else if (sel < 0)
    perror("select");
  return(1);
}

int results(char * stats,int * y)
{
FILE *fp;
char w[32][256];
char p[32][256];
char ch;
int wi=0;
int pi=0;
int i=0;
int j=0;
int x;
int playerloc;
int tabcount;

x=*y;
for (i=19;i<x;i++) {
  if (stats[i]==0x0a) { playerloc=i;break; }
  if (stats[i]==0x5c) { j=0;wi++; }
  else { w[wi][j++]=stats[i]; }
  }
wi++;

/* HORIZONTAL TABLE FORMATTING */
printf("<TABLE><tr><td valign=top>\n");
/* ROW TABLE FORMATTING */
printf("<TABLE><tr><td valign=top>\n");


/* START PLAYER INFO DISPLAY */
printf("<table border=1>\n");
printf("<tr><td>PLAYERS ONLINE</td></tr>\n");
printf("<tr><td>Kills</td><td>Ping</td><td>Name</td></tr>\n");
pi=0;j=0;
for (i=playerloc+1;i<=x;i++) {
  if (stats[i]==0x0a) { p[pi][j]='\0';j=0;pi++; }
  else { p[pi][j++]=stats[i]; }
  }
pi++;
for(i=0;i<pi;i++) {
  printf("<TR><TD>");
  for(j=0;j<strlen(p[i]);j++) {
    if (p[i][j]==0x20&&tabcount<2) { 
      tabcount++;
      printf("</td><td>");
      }
    ch=p[i][j];
    putchar(ch);
    }
  printf("</td></tr>\n");
  tabcount=0;
  }
printf("</table>\n");
/* END OF PLAYER INFO DISPLAY */

/* ROW TABLE FORMATTING */
printf("<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td><td valign=top>\n");

/* DISPLAY SCHEDULE INFO FROM TEXT FILE */
printf("<table border=1><tr><td>SCHEDULED GAMES</td></tr>\n");
printf("<tr><td>Date</td><td>Time</td><td>User</td></tr>\n<tr><td>");
fp=fopen("/var/www/cgi-bin/schedule.inc","r");
while ((i=getc(fp))!=EOF) {
  if ((i!=0x0a)&&(i!=',')) {
    putc(i,stdout);
    }
  else {
    if (i==0x0a) { printf("</td></tr>\n<tr><td>"); }
    if (i==',') { printf("</td><td>"); }
    }
  }
fclose(fp);
printf("</td></tr></table>\n");

/* END SCHEDULED GAMES DISPLAY */

/* END ROW TABLE FORMATTING */
printf("</td></tr></table><P><P>\n");

/* HORIZONTAL TABLE FORMATTING */
printf("</td></tr><tr><td>\n");

/* START SERVER SETTINGS DISPLAY */
printf("<TABLE border=1><tr><td>SERVER SETTINGS</td></tr>\n");
for(i=1;i<31;i+=2) {
  if (!strcmp(w[i],"g_gametype")) {
    if (!strcmp(w[i+1],"dm")) { printf("<tr><td>GameType</td><td>DeathMatch</td></tr>\n"); }
    if (!strcmp(w[i+1],"tdm")) { printf("<tr><td>GameType</td><td>Team DeathMatch</td></tr>\n"); }
    if (!strcmp(w[i+1],"re")) { printf("<tr><td>GameType</td><td>Retrieval</td></tr>\n"); }
    if (!strcmp(w[i+1],"sd")) { printf("<tr><td>GameType</td><td>Search & Destroy</td></tr>\n"); }
    if (!strcmp(w[i+1],"del")) { printf("<tr><td>GameType</td><td>Behind Enemy Lines</td></tr>\n"); }
    }
  else {
    printf("</tr><td>%s</td><td>%s</td></tr>\n",w[i],w[i+1]);
    }
  }
printf("\n</table></td>\n");
/* END SERVER SETTINGS DISPLAY */

/* END HORIZONTAL TABLE FORMATTING */
printf("</td></tr></table>\n");


printf("</BODY></HTML>\n");
}

