/*
 *	$Source: /mit/jik/sipbsrc/src/gameserver/RCS/master.c,v $
 *	$Header: /mit/jik/sipbsrc/src/gameserver/RCS/master.c,v 1.10 1992/03/03 02:17:58 jik Exp $
 */

#ifndef lint
static char *rcsid_master_c = "$Header: /mit/jik/sipbsrc/src/gameserver/RCS/master.c,v 1.10 1992/03/03 02:17:58 jik Exp $";
#endif lint

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <syslog.h>
#include <string.h>
#ifdef _AIX
#include <sys/select.h>
#endif

#include "messagecodes.h"
#define MAXLINE 1000

int M_num_of_players = 0;
int M_max_fd = GAMESERVER_FD;
fd_set M_select_mask;
char *program_name = NULL;

static unsigned long nlen;		/* for network byte order */


/* ARGSUSED */
main(argc, argv)
     int argc;
     char **argv;
{
	extern int M_num_of_players, M_max_fd;
	extern fd_set M_select_mask;
	fd_set readfds;
	int num, fd;

	FD_ZERO(&M_select_mask);
	FD_SET(GAMESERVER_FD, &M_select_mask);
	program_name = rindex(argv[0], '/');
	if (!program_name) program_name = argv[0];
	else program_name++;
#ifdef mips
	openlog(program_name, LOG_PID);
#else
	openlog(program_name, LOG_PID, LOG_LOCAL3);
#endif
	syslog(LOG_INFO, "starting");
	syslog(LOG_DEBUG, "initializing");
	initialize_game();
	syslog(LOG_DEBUG, "done initialization");
	while(1) {
		readfds = M_select_mask;
		num = select(M_max_fd + 1, &readfds, NULL, NULL, NULL);
		if (num > 0) {
			for (fd = 0; fd <= M_max_fd; fd++) {
				if (FD_ISSET(fd, &readfds)) {
					if (fd == GAMESERVER_FD) listen_to_server();
					else listen_to_player(fd);
				}
			}
		}
	}
}


listen_to_server()
{
	unsigned char message_code;
	short message_length;
	struct sockaddr_in sin, nbosin;
	char *response;
	int new_s;
/*	char buf[MAXLINE];*/

	if (safe_read(GAMESERVER_FD, (char *) &message_code,
		      sizeof(message_code)) < 0) {
		remove_server();
		return;
	}
	switch (message_code) {
	  case MC_NEW_PLAYER:
		if (new_player_is_ok()) {
			new_s = socket(AF_INET, SOCK_STREAM, 0);
			if (new_s < 0) {
				message_code = MC_ERROR;
				write(GAMESERVER_FD, &message_code, sizeof(message_code));
				return;
			}
			message_code = MC_OK;
			write(GAMESERVER_FD, &message_code, sizeof(message_code));
			if (safe_read(GAMESERVER_FD, (char *) &nbosin,
				      sizeof(nbosin)) < 0) {
				remove_server();
				return;
			}
			bcopy(&nbosin, &sin, sizeof(nbosin));
			sin.sin_family = ntohs(nbosin.sin_family);
			if (connect(new_s, &sin, sizeof(sin)) < 0) {
				close(new_s);
				return;
			}
			FD_SET(new_s, &M_select_mask);
			M_num_of_players++;
			if (new_s > M_max_fd) M_max_fd = new_s;
			new_player(new_s,M_max_fd, M_select_mask);
		}
		else {
			message_code = MC_ERROR;
			write(GAMESERVER_FD, &message_code, sizeof(message_code));
		}
		break;
	      case MC_GAME_QUERY:
		/* query_response puts the response in network order */
		message_length = query_response(&response);
		if (message_length < 0) {
			message_code = MC_ERROR;
			write(GAMESERVER_FD, &message_code, sizeof(message_code));
			return;
		}
		message_code = MC_QUERY_RESPONSE;
		write(GAMESERVER_FD, &message_code, sizeof(message_code));
		nlen = htonl(message_length);
		write(GAMESERVER_FD, &nlen, sizeof(nlen));
		if (message_length > 0)
		  write(GAMESERVER_FD, response, message_length);
		break;
	      default:
		syslog(LOG_ERR, "gameserver sent bad message code: %d",
		       message_code);
		break;
	}
}

remove_server()
{
	extern fd_set M_select_mask;

	FD_CLR(GAMESERVER_FD, &M_select_mask);
	close(GAMESERVER_FD);
}

remove_player(player)
     int player;
{
	extern fd_set M_select_mask;
	extern int M_max_fd;
	
	close(player);
	FD_CLR(player, &M_select_mask);
	if (! --M_num_of_players) {
		exit(0);
	}
	if (player == M_max_fd)
	     --M_max_fd;
}
