diff options
author | dholland <dholland@NetBSD.org> | 2014-03-30 03:26:19 +0000 |
---|---|---|
committer | dholland <dholland@NetBSD.org> | 2014-03-30 03:26:19 +0000 |
commit | 8f20cf89a10b5bedaf26510e49b5159f36f108d3 (patch) | |
tree | bcf49c2e9a259f2b09c8172fe5b744eff0caf4dc /hunt | |
parent | c26df524baa361cedefd86bcc34e5c479948d386 (diff) | |
download | bsdgames-darwin-8f20cf89a10b5bedaf26510e49b5159f36f108d3.tar.gz bsdgames-darwin-8f20cf89a10b5bedaf26510e49b5159f36f108d3.tar.zst bsdgames-darwin-8f20cf89a10b5bedaf26510e49b5159f36f108d3.zip |
more cleanup
Diffstat (limited to 'hunt')
-rw-r--r-- | hunt/hunt/server.c | 171 |
1 files changed, 117 insertions, 54 deletions
diff --git a/hunt/hunt/server.c b/hunt/hunt/server.c index 7a60af09..ac7a4fde 100644 --- a/hunt/hunt/server.c +++ b/hunt/hunt/server.c @@ -1,4 +1,4 @@ -/* $NetBSD: server.c,v 1.4 2014/03/30 02:58:25 dholland Exp $ */ +/* $NetBSD: server.c,v 1.5 2014/03/30 03:26:19 dholland Exp $ */ /* * Copyright (c) 1983-2003, Regents of the University of California. * All rights reserved. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: server.c,v 1.4 2014/03/30 02:58:25 dholland Exp $"); +__RCSID("$NetBSD: server.c,v 1.5 2014/03/30 03:26:19 dholland Exp $"); #include <sys/param.h> #include <sys/stat.h> @@ -40,11 +40,11 @@ __RCSID("$NetBSD: server.c,v 1.4 2014/03/30 02:58:25 dholland Exp $"); #include <ctype.h> #include <err.h> #include <errno.h> -#include <curses.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <assert.h> #include <ifaddrs.h> #include "hunt_common.h" @@ -57,8 +57,8 @@ __RCSID("$NetBSD: server.c,v 1.4 2014/03/30 02:58:25 dholland Exp $"); * Code for finding and talking to hunt daemons. */ -static SOCKET *listv; -static unsigned int listmax; +static SOCKET *daemons; +static unsigned int numdaemons, maxdaemons; static bool initial = true; static struct in_addr local_address; @@ -80,15 +80,64 @@ serverlist_setup(void) } memcpy(&local_address, hp->h_addr, sizeof(local_address)); - listmax = 20; - listv = malloc(listmax * sizeof(listv[0])); - if (listv == NULL) { + numdaemons = 0; + maxdaemons = 20; + daemons = malloc(maxdaemons * sizeof(daemons[0])); + if (daemons == NULL) { leavex(1, "Out of memory."); } } +static void +add_daemon_addr(const struct sockaddr_storage *addr, uint16_t port_num) +{ + const struct sockaddr_in *sin; + + if (addr->ss_family != AF_INET) { + return; + } + sin = (const struct sockaddr_in *)addr; + + assert(numdaemons <= maxdaemons); + if (numdaemons == maxdaemons) { + maxdaemons += 20; + daemons = realloc(daemons, maxdaemons * sizeof(daemons[0])); + if (daemons == NULL) { + leave(1, "realloc"); + } + } + + /* + * Note that we do *not* convert from network to host + * order since the port number we were sent *should* + * already be in network order. + */ + daemons[numdaemons] = *sin; + daemons[numdaemons].sin_port = port_num; + numdaemons++; +} + +static bool +have_daemon_addr(const struct sockaddr_storage *addr) +{ + unsigned j; + const struct sockaddr_in *sin; + + if (addr->ss_family != AF_INET) { + return false; + } + sin = (const struct sockaddr_in *)addr; + + for (j = 0; j < numdaemons; j++) { + if (sin->sin_addr.s_addr == daemons[j].sin_addr.s_addr) { + return true; + } + } + return false; +} + static int -getbroadcastaddrs(int s /*socket*/, struct sockaddr_in **vector) +getbroadcastaddrs(struct sockaddr_in **vector) { int vec_cnt; struct ifaddrs *ifp, *ip; @@ -119,58 +168,66 @@ getbroadcastaddrs(int s /*socket*/, struct sockaddr_in **vector) static void get_responses(int contactsock) { - u_short port_num; - unsigned j; - unsigned int listc; struct pollfd set[1]; + struct sockaddr_storage addr; socklen_t addrlen; + int r; + uint16_t port_num; + ssize_t portlen; + + /* forget all old responses */ + numdaemons = 0; - listc = 0; - addrlen = sizeof(listv[0]); errno = 0; set[0].fd = contactsock; set[0].events = POLLIN; for (;;) { - if (listc + 1 >= listmax) { - SOCKET *newlistv; - - listmax += 20; - newlistv = realloc(listv, listmax * sizeof(*listv)); - if (newlistv == NULL) - leave(1, "realloc"); - listv = newlistv; + r = poll(set, 1, 1000); + if (r < 0) { + if (errno == EINTR) { + continue; + } + leave(1, "poll"); + } + if (r == 0) { + break; } - if (poll(set, 1, 1000) == 1 && - recvfrom(contactsock, &port_num, sizeof(port_num), - 0, (struct sockaddr *) &listv[listc], &addrlen) > 0) { - /* - * Note that we do *not* convert from network to host - * order since the port number *should* be in network - * order: - */ - for (j = 0; j < listc; j += 1) - if (listv[listc].sin_addr.s_addr - == listv[j].sin_addr.s_addr) - break; - if (j == listc) - listv[listc++].sin_port = port_num; + addrlen = sizeof(addr); + portlen = recvfrom(contactsock, &port_num, sizeof(port_num), 0, + (struct sockaddr *)&addr, &addrlen); + if (portlen < 0) { + if (errno == EINTR) { + continue; + } + leave(1, "recvfrom"); + } + if (portlen == 0) { + leavex(1, "recvfrom: Unexpected EOF"); + } + if ((size_t)portlen != sizeof(port_num)) { + /* trash, ignore it */ continue; } - - if (errno != 0 && errno != EINTR) { - leave(1, "poll/recvfrom"); + if (have_daemon_addr(&addr)) { + /* this shouldn't happen */ + continue; } - /* terminate list with local address */ - listv[listc].sin_family = SOCK_FAMILY; - listv[listc].sin_addr = local_address; - listv[listc].sin_port = htons(0); + add_daemon_addr(&addr, port_num); + } - (void) close(contactsock); - initial = false; - break; + /* terminate list with local address */ + { + struct sockaddr_in sin; + + sin.sin_family = SOCK_FAMILY; + sin.sin_addr = local_address; + sin.sin_port = htons(0); + add_daemon_addr((struct sockaddr_storage *)&sin, htons(0)); } + + initial = false; } SOCKET * @@ -186,8 +243,12 @@ list_drivers(unsigned short msg) if (initial) { /* do one time initialization */ serverlist_setup(); - } else if (Sock_host != NULL) - return listv; /* address already valid */ + } + + if (!initial && Sock_host != NULL) { + /* address already valid */ + return daemons; + } contactsock = socket(SOCK_FAMILY, SOCK_DGRAM, 0); if (contactsock < 0) { @@ -208,11 +269,12 @@ list_drivers(unsigned short msg) (struct sockaddr *)&contactaddr, sizeof(contactaddr)); get_responses(contactsock); - return listv; + (void) close(contactsock); + return daemons; } if (!initial) { - /* favor host of previous session by broadcasting to it first */ + /* favor host of previous session by contacting it first */ contactaddr.sin_addr = Daemon.sin_addr; wiremsg = htons(C_PLAYER); /* Must be playing! */ (void) sendto(contactsock, &wiremsg, sizeof(wiremsg), 0, @@ -220,7 +282,7 @@ list_drivers(unsigned short msg) } if (initial) - brdc = getbroadcastaddrs(contactsock, &brdv); + brdc = getbroadcastaddrs(&brdv); #ifdef SO_BROADCAST /* Sun's will broadcast even though this option can't be set */ @@ -236,20 +298,21 @@ list_drivers(unsigned short msg) wiremsg = htons(msg); for (i = 0; i < brdc; i++) { contactaddr.sin_addr = brdv[i].sin_addr; - if (sendto(contactsock, &msg, sizeof msg, 0, + if (sendto(contactsock, &wiremsg, sizeof(wiremsg), 0, (struct sockaddr *)&contactaddr, sizeof(contactaddr)) < 0) { leave(1, "sendto"); } } contactaddr.sin_addr = local_address; - if (sendto(contactsock, &msg, sizeof msg, 0, + if (sendto(contactsock, &wiremsg, sizeof(wiremsg), 0, (struct sockaddr *)&contactaddr, sizeof(contactaddr)) < 0) { leave(1, "sendto"); } get_responses(contactsock); - return listv; + (void) close(contactsock); + return daemons; } #endif /* INTERNET */ |