X-Git-Url: http://git.shiar.net/netris.git/blobdiff_plain/45dc9d995860486f1758dcf79fd2d8cd8dfb210a..e7c197505ec760eb3754f3b6d1fbbc33c66a9316:/server.c diff --git a/server.c b/server.c index 6fe46f0..c33a541 100644 --- a/server.c +++ b/server.c @@ -15,12 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: game.c,v 1.39 1999/05/16 06:56:27 mhw Exp $ */ #define NOEXT #include "netris.h" + #include #include #include @@ -32,92 +31,59 @@ #include #include +#include "util.h" + #define HEADER_SIZE sizeof(netint4[3]) static struct option options[] = { - { "wait", 0, 0, 'w' }, - { "port", 1, 0, 'p' }, - { "min-players",1, 0, 'm' }, - { "max-players",1, 0, 'x' }, - { "continuous", 1, 0, 'c' }, - { "speed", 1, 0, 'i' }, - { "seed", 1, 0, 's' }, - { "verbose", 0, 0, 'v' }, - { "info", 0, 0, 'H' }, - { "help", 0, 0, 'h' }, - { 0, 0, 0, 0 } + { "wait", 0, 0, 'w' }, + { "port", 1, 0, 'p' }, + { "quadra", 1, 0, 'q' }, + { "min-players", 1, 0, 'm' }, + { "max-players", 1, 0, 'x' }, + { "continuous", 1, 0, 'c' }, + { "speed", 1, 0, 'i' }, + { "seed", 1, 0, 's' }, + { "verbose", 0, 0, 'v' }, + { "info", 0, 0, 'H' }, + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } }; static char minplayers = 2; +static char maxplayers = 8; static char playercount; static char verbose = 0; struct sockaddr_in addr; -static char *gameNames[GT_len] = { "OnePlayer", "ClassicTwo" }; - -ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event); +MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event); static EventGenRec netGen[MAX_SCREENS] = { - { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE } }; + { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE } +}; static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event); -static EventGenRec alarmGen = - { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm }; +static EventGenRec alarmGen = { + &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm +}; static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event); -static EventGenRec connGen = - { NULL, 0, FT_read, -1, ConnGenFunc, EM_connect }; +static EventGenRec connGen = { + NULL, 0, FT_read, -1, ConnGenFunc, EM_connect +}; static EventGenRec *nextGen = &alarmGen; static sigjmp_buf close_env; -ExtFunc volatile void die(char *msg) -{ - perror(msg); - exit(1); -} //die - -ExtFunc int MyRead(int fd, void *data, int len) -{ - int result, left; - - left = len; - while (left > 0) { - result = read(fd, data, left); - if (result > 0) { - data = ((char *)data) + result; - left -= result; - } - else if (errno != EINTR) - return result; - } - return len; -} //MyRead - -ExtFunc int MyWrite(int fd, void *data, int len) -{ - int result, left; - - left = len; - while (left > 0) { - result = write(fd, data, left); - if (result > 0) { - data = ((char *)data) + result; - left -= result; - } - else if (errno != EINTR) - return result; - } - return len; -} //MyWrite - -ExtFunc void SendPacketTo(short playa, short uid, NetPacketType type, int size, void *data) +void SendPacketTo(short playa, short uid, NetPacketType type, int size, void *data) { //send to someone netint4 header[3]; if (netGen[playa].fd >= 0) { + if (verbose) + fprintf(stderr, ": send %d from %d to %d\n", type, uid, playa); header[0] = hton4(uid); header[1] = hton4(type); header[2] = hton4(size + HEADER_SIZE); @@ -126,58 +92,30 @@ ExtFunc void SendPacketTo(short playa, short uid, NetPacketType type, int size, if (size > 0 && data && MyWrite(netGen[playa].fd, data, size) != size) die("write"); } -} //SendPacketTo +} static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event) { return E_alarm; -} //AlarmGenFunc - -ExtFunc void AddEventGen(EventGenRec *gen) -{ - assert(gen->next == NULL); - assert(nextGen->next != (void*)0xffffffff); - gen->next = nextGen->next; - nextGen->next = gen; -} //AddEventGen +} -ExtFunc void RemoveEventGen(EventGenRec *gen) -{ - // assert(gen->next != NULL); /* Be more forgiving, for SIGINTs */ - if (gen->next) { - while (nextGen->next != gen) - nextGen = nextGen->next; - nextGen->next = gen->next; - gen->next = NULL; - } -} //RemoveEventGen - -ExtFunc void AtExit(void (*handler)(void)) -{ //setup something to do at exit (^C) -#ifdef HAS_ON_EXIT - on_exit((void *)handler, NULL); -#else - atexit(handler); -#endif -} //AtExit - -ExtFunc void SCloseNet(short playa) +void SCloseNet(short playa) { //kick some connection's ass! MyEvent event; if (netGen[playa].fd >= 0) { if (Players[playa].alive >= 0) { SendPacketTo(playa, 0, NP_endConn, 0, NULL); - do{} while (WaitMyEvent(&event, EM_net) != E_lostConn); + do {} while (WaitMyEvent(&event, EM_net) != E_lostConn); } //say bye to player close(netGen[playa].fd); netGen[playa].fd = -1; } if (netGen[playa].next) RemoveEventGen(&netGen[playa]); -} //SCloseNet +} -ExtFunc void CloseNets(void) +void CloseNets(void) { //nou oogjes dicht en snaveltjes toe int i; @@ -185,62 +123,9 @@ ExtFunc void CloseNets(void) for (i = 1; i < MAX_SCREENS; i++) SCloseNet(i); //bye everybuddy fprintf(stderr, "* All Done\n\n"); -} //CloseNets - -ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask) -{ //poll - int i, retry = 0; - fd_set fds[FT_len]; - EventGenRec *gen; - int result, anyReady, anySet; - struct timeval tv; - - for (;;) { - for (i = 0; i < FT_len; ++i) - FD_ZERO(&fds[i]); - anyReady = anySet = 0; - gen = nextGen; - do { - if (gen->mask & mask) { - if (gen->ready) - anyReady = 1; - if (gen->fd >= 0) { - FD_SET(gen->fd, &fds[gen->fdType]); - anySet = 1; - } - } - gen = gen->next; - } while (gen != nextGen); - if (anySet) { - tv.tv_sec = 0; - tv.tv_usec = (retry && !anyReady) ? 500000 : 0; - result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write], - &fds[FT_except], anyReady ? &tv : NULL); - } - else { - if (retry && !anyReady) - sleep(1); - result = 0; - } - gen = nextGen; - do { - if ((gen->mask & mask) - && (gen->ready || (result > 0 && gen->fd >= 0 - && FD_ISSET(gen->fd, &fds[gen->fdType])))) { - gen->ready = 0; - event->type = gen->func(gen, event); - if (event->type != E_none) { - nextGen = gen->next; - return event->type; - } - } - gen = gen->next; - } while (gen != nextGen); - retry = 1; - } -} //WaitMyEvent +} -ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event) +MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event) { //receive int result; short uid, type, size; @@ -274,7 +159,7 @@ ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event) return E_lostConn; } //client sent quit signal return E_net; -} //NetGenFunc +} static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event) @@ -286,7 +171,7 @@ static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event) addrLen = sizeof(addr); for (new = 1; new <= MAX_SCREENS; new++) if (netGen[new].fd < 0) break; - if (new > Game.maxplayers) return; + if (new > maxplayers) return; if ((netGen[new].fd = accept(gen->fd, (struct sockaddr *)&addr, &addrLen)) < 0) @@ -304,7 +189,7 @@ static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event) sprintf(Players[new].host, "%s", inet_ntoa(addr.sin_addr)); if (addr.sin_family == AF_INET) { host = gethostbyaddr((void *)&addr.sin_addr, - sizeof(struct in_addr), AF_INET); + sizeof(struct in_addr), AF_INET); if (host) { strncpy(Players[new].host, host->h_name, sizeof(Players[new].host) - 1); @@ -313,9 +198,9 @@ static MyEventType ConnGenFunc(EventGenRec *gen, MyEvent *event) } } //E_connect return E_connect; -} //ConnGenFunc +} -ExtFunc void CountPlayers(void) +void CountPlayers(void) { //count number of players/teams int i, j; playercount = 0; @@ -327,17 +212,19 @@ ExtFunc void CountPlayers(void) } //player of same team counted before playercount++; } //player alive -} //CountPlayers +} -ExtFunc int StartServer(void) +int StartServer(void) { MyEvent event; netint2 currentpiece[MAX_SCREENS]; int playersReady = 0; int paused = 1; int i; - char teams[10][7] = { "", "Green", "Cyan", "Blue", "Purple", - "Red", "Grey", "White", "*Orange" }; + char teams[10][7] = { + "", "Green", "Cyan", "Blue", "Purple", + "Red", "Grey", "White", "*Orange" + }; do { switch (WaitMyEvent(&event, EM_any)) { @@ -360,13 +247,14 @@ ExtFunc int StartServer(void) netint4 versiondata[2]; char data[255]; int major; + int protocolVersion; memcpy(versiondata, event.u.net.data, sizeof(versiondata)); major = ntoh4(versiondata[0]); protocolVersion = ntoh4(versiondata[1]); if (major != MAJOR_VERSION - || protocolVersion != PROTOCOL_VERSION) { + || protocolVersion != PROTOCOL_VERSION) { snprintf(data, sizeof(data), "Version mismatch: received %d.%d", major, protocolVersion); @@ -386,10 +274,16 @@ ExtFunc int StartServer(void) event.u.net.data, event.u.net.size); if (Players[event.u.net.sender].team < 1 || Players[event.u.net.sender].team > 7) { - Players[event.u.net.sender].team = - event.u.net.sender % 7 + 1; - SendPacketTo(event.u.net.sender, - event.u.net.sender, NP_team, + int team; + + for (team = 1; team < 7; team++) { + for (i = 1; i < MAX_SCREENS; i++) + if ((Players[i].alive > 0) && (Players[i].team == team)) + break; //team in use + if (i==MAX_SCREENS) break; + } //find unused team + Players[event.u.net.sender].team = team; + SendPacketTo(event.u.net.sender, event.u.net.sender, NP_team, sizeof(Players[event.u.net.sender].team), &Players[event.u.net.sender].team); } //invalid team @@ -408,7 +302,7 @@ ExtFunc int StartServer(void) { static struct { int playerflags; - int maxplayers; //1 + int gravity; //1 int started; //2 int continuous; //3 long seed; //4 @@ -417,7 +311,7 @@ ExtFunc int StartServer(void) memcpy(&data, &Players[event.u.net.sender].flags, sizeof(data.playerflags)); - memcpy(&data.maxplayers, &Game, + memcpy(&data.gravity, &Game, sizeof(data) - sizeof(data.playerflags)); SendPacketTo(event.u.net.sender, 0, NP_gamedata, sizeof(data), &data); @@ -425,18 +319,11 @@ ExtFunc int StartServer(void) for (i = 1; i < MAX_SCREENS; i++) if (netGen[i].fd >= 0 && i != event.u.net.sender) { SendPacketTo(event.u.net.sender, i, - NP_newPlayer, sizeof(Player) - - sizeof(Players[0].spy) - - sizeof(Players[0].small), - &Players[i]); - SendPacketTo(event.u.net.sender, i, - NP_newPiece, sizeof(currentpiece[i]), - ¤tpiece[i]); - SendPacketTo(i, event.u.net.sender, - NP_newPlayer, sizeof(Player) - - sizeof(Players[0].spy) - - sizeof(Players[0].small), - &Players[event.u.net.sender]); + NP_newPlayer, sizeof(_Player), &Players[i]); + SendPacketTo(event.u.net.sender, i, NP_newPiece, + sizeof(Players[i].curShape), &Players[i].curShape); + SendPacketTo(i, event.u.net.sender, NP_newPlayer, + sizeof(_Player), &Players[event.u.net.sender]); } //send (to) players fprintf(stderr, "> Joined player #%d: %s <%s> (%s)\n", event.u.net.sender, @@ -457,8 +344,8 @@ ExtFunc int StartServer(void) } //give go ahead break; //NP_playerdata case NP_newPiece: - memcpy(¤tpiece[event.u.net.sender], - event.u.net.data, sizeof(currentpiece[0])); + memcpy(&Players[event.u.net.sender].curShape, + event.u.net.data, sizeof(Players[0].curShape)); goto sendtoall; case NP_argghhh: Players[event.u.net.sender].alive = 0; @@ -481,7 +368,7 @@ ExtFunc int StartServer(void) sendtoall: // if (event.u.net.type >= NP_pause) if (event.u.net.type >= NP_rotright - && Game.started < 2) + && Game.started < 2) break; for (i = 1; i < MAX_SCREENS; i++) if (i != event.u.net.sender) @@ -534,56 +421,36 @@ ExtFunc int StartServer(void) } //game (ready to) start(ed) } while (1); fprintf(stderr, "* Exiting server\n"); -} //StartServer +} -ExtFunc void Header(void) +void SHeader(void) { fprintf(stderr, - "NETRIS Server %s\t(c) 2002 Shiar \n\n", - version_string); -} //Header + "NETRIS Server %s\t(c) 2002 Shiar \n\n", + version_string); +} -ExtFunc void Usage(void) +void SUsage(void) { - Header(); + SHeader(); fprintf(stderr, - "Usage: netris \n" - "\n" - " -h, --help\t\tPrint this usage information\n" - " -H, --info\t\tShow distribution and warranty information\n" - "\n" - " -p, --port \tSet port number (default is %d)\n" - "\n" - " -s, --seed \tStart with given random seed\n" - " -i, --speed \tSet the initial step-down interval, in seconds\n" - " -m, --min-players <2>\tNumber of players required before starting the game\n" - " -x, --max-players <8>\tMaximum number of players allowed in the game\n" - " -c, --continuous\tDon'n quit the game\n" - "\n", DEFAULT_PORT); + "Usage: netris \n" + "\n" + " -h, --help\t\tPrint this usage information\n" + " -H, --info\t\tShow distribution and warranty information\n" + "\n" + " -p, --port \tSet port number (default is %d)\n" + "\n" + " -s, --seed \tStart with given random seed\n" + " -i, --speed \tSet the initial step-down interval, in seconds\n" + " -m, --min-players <2>\tNumber of players required before starting the game\n" + " -x, --max-players <8>\tMaximum number of players allowed in the game\n" + " -c, --continuous\tDon'n quit the game\n" + "\n", DEFAULT_PORT); } -ExtFunc void DistInfo(void) -{ - Header(); - fprintf(stderr, - "This program is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program; if not, write to the Free Software\n" - "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" - "\n"); -} //DistInfo - -ExtFunc void WriteConf(void) +void WriteConf(void) { FILE *file_out; @@ -597,44 +464,48 @@ ExtFunc void WriteConf(void) fclose(file_out); fprintf(stderr, "Wrote new game configuration to %s\n", CONFIG_FILE); -} //WriteConf +} -ExtFunc void HandleOption(char tag, char *value) +void HandleOption(char tag, char *value) { switch (tag) { - case 'v': //verbose + case 'v': //verbose verbose = 1; break; - case 'p': //port + case 'p': //port port = atoi(value); break; - case 'c': //min-players + case 'c': //min-players Game.continuous = atoi(value); break; - case 'm': //min-players + case 'm': //min-players minplayers = atoi(value); break; - case 'x': //max-players - Game.maxplayers = atoi(value); - if (Game.maxplayers >= MAX_SCREENS) - Game.maxplayers = MAX_SCREENS; + case 'x': //max-players + maxplayers = atoi(value); + if (maxplayers >= MAX_SCREENS) + maxplayers = MAX_SCREENS; + break; + case 'q': //quadra-style gravity + Game.gravity ^= 1; break; - case 'i': //speed (of level 1) + case 'i': //speed (of level 1) Game.initspeed = atof(value) * 1e6; break; - case 's': //seed + case 's': //seed Game.seed = atoi(value); break; - case 'H': //info + case 'H': //info + SHeader(); DistInfo(); exit(0); - case 'h': //help - Usage(); exit(0); + case 'h': //help + SUsage(); exit(0); default: break; } -} //HandleParam +} -ExtFunc void ReadConf(char *filename) +void ReadConf(char *filename) { FILE *file_in; char buf[513]; @@ -648,8 +519,8 @@ ExtFunc void ReadConf(char *filename) if ((ch = strchr(buf, '#'))) *ch = '\0'; // truncate string from # char for (i = strlen(buf)-1; i >= 0; i--) - if (buf[i] == ' ' || buf[i] == '\t' - || buf[i] == '\n' || buf[i] == 13) + if (buf[i] == ' ' || buf[i] == '\t' + || buf[i] == '\n' || buf[i] == 13) buf[i] = '\0'; else break; @@ -667,23 +538,24 @@ ExtFunc void ReadConf(char *filename) fprintf(stderr, "Unable to open config file %s.\n", filename); } //defaults -} //ReadConf +} -ExtFunc void CatchInt(int sig) +void CatchInt(int sig) { siglongjmp(close_env, 1); } -ExtFunc int main(int argc, char **argv) +int main(int argc, char **argv) { char ch; if (sigsetjmp(close_env, 1)) exit(0); signal(SIGINT, CatchInt); port = DEFAULT_PORT; - Game.maxplayers = 8; + maxplayers = 8; Game.initspeed = DEFAULT_INTERVAL; Game.seed = time(0); + Game.gravity = 0; { int i; @@ -695,16 +567,17 @@ ExtFunc int main(int argc, char **argv) // ReadConf(optarg); // else ReadConf(CONFIG_FILE); - while ((ch = getopt_long(argc, argv, - "hHvp:i:s:c:m:x:", options, NULL)) != -1) + while ((ch = getopt_long( + argc, argv, "hHvqp:i:s:c:m:x:", options, NULL + )) != -1) HandleOption(ch, optarg); if (optind < argc) { - Usage(); + SUsage(); exit(1); } // WriteConf(); - Header(); + SHeader(); { int i; @@ -726,7 +599,7 @@ ExtFunc int main(int argc, char **argv) die("socket"); val1 = 1; setsockopt(connGen.fd, SOL_SOCKET, SO_REUSEADDR, - (void *)&val1, sizeof(val1)); + (void *)&val1, sizeof(val1)); if (bind(connGen.fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) die("bind"); if (listen(connGen.fd, 1) < 0) @@ -740,7 +613,3 @@ ExtFunc int main(int argc, char **argv) return 0; } -/* - * vi: ts=4 ai - * vim: noai si - */