Module Name:    src
Committed By:   dholland
Date:           Sun Mar 30 04:31:21 UTC 2014

Modified Files:
        src/games/hunt/hunt: hunt.c hunt_private.h server.c

Log Message:
Clean up the handling of the list of hunt daemons.


To generate a diff of this commit:
cvs rdiff -u -r1.50 -r1.51 src/games/hunt/hunt/hunt.c
cvs rdiff -u -r1.6 -r1.7 src/games/hunt/hunt/hunt_private.h
cvs rdiff -u -r1.5 -r1.6 src/games/hunt/hunt/server.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/games/hunt/hunt/hunt.c
diff -u src/games/hunt/hunt/hunt.c:1.50 src/games/hunt/hunt/hunt.c:1.51
--- src/games/hunt/hunt/hunt.c:1.50	Sun Mar 30 03:35:26 2014
+++ src/games/hunt/hunt/hunt.c	Sun Mar 30 04:31:21 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: hunt.c,v 1.50 2014/03/30 03:35:26 dholland Exp $	*/
+/*	$NetBSD: hunt.c,v 1.51 2014/03/30 04:31:21 dholland Exp $	*/
 /*
  * Copyright (c) 1983-2003, Regents of the University of California.
  * All rights reserved.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: hunt.c,v 1.50 2014/03/30 03:35:26 dholland Exp $");
+__RCSID("$NetBSD: hunt.c,v 1.51 2014/03/30 04:31:21 dholland Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -47,7 +47,7 @@ __RCSID("$NetBSD: hunt.c,v 1.50 2014/03/
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <ifaddrs.h>
+#include <assert.h>
 
 #include "hunt_common.h"
 #include "pathnames.h"
@@ -64,7 +64,7 @@ static const char Driver[] = PATH_HUNTD;
 #endif
 
 #ifdef INTERNET
-uint16_t Test_port = TEST_PORT;
+static uint16_t Test_port = TEST_PORT;
 #else
 static const char Sock_name[] = PATH_HUNTSOCKET;
 #endif
@@ -79,7 +79,7 @@ char Buf[BUFSIZ];
 
 /*static*/ int Socket;
 #ifdef INTERNET
-char *Sock_host;
+static char *Sock_host;
 static char *use_port;
 char *Send_message = NULL;
 #endif
@@ -101,17 +101,34 @@ static int in_visual;
 
 extern int cur_row, cur_col;
 
-static void dump_scores(SOCKET);
+static void dump_scores(const struct sockaddr_storage *, socklen_t);
 static long env_init(long);
 static void fill_in_blanks(void);
 static void fincurs(void);
 static void rmnl(char *);
 static void sigterm(int) __dead;
 static void sigusr1(int) __dead;
-static void find_driver(bool);
+static void find_driver(void);
 static void start_driver(void);
 
 extern int Otto_mode;
+
+static const char *
+lookuphost(const struct sockaddr_storage *host, socklen_t hostlen)
+{
+	static char buf[NI_MAXHOST];
+	int flags, result;
+
+	flags = NI_NOFQDN;
+
+	result = getnameinfo((const struct sockaddr *)host, hostlen,
+			     buf, sizeof(buf), NULL, 0, NI_NOFQDN);
+	if (result) {
+		leavex(1, "getnameinfo: %s", gai_strerror(result));
+	}
+	return buf;
+}
+
 /*
  * main:
  *	Main program for local process
@@ -215,29 +232,36 @@ main(int ac, char **av)
 #endif
 
 #ifdef INTERNET
+	serverlist_setup(Sock_host, Test_port);
+
 	if (Show_scores) {
-		SOCKET *hosts;
+		const struct sockaddr_storage *host;
+		socklen_t hostlen;
 		u_short msg = C_SCORES;
+		unsigned i;
 
-		for (hosts = list_drivers(msg); hosts->sin_port != 0; hosts += 1)
-			dump_scores(*hosts);
+		serverlist_query(msg);
+		for (i = 0; i < serverlist_num(); i++) {
+			host = serverlist_gethost(i, &hostlen);
+			dump_scores(host, hostlen);
+		}
 		exit(0);
 	}
 	if (Query_driver) {
-		SOCKET *hosts;
+		const struct sockaddr_storage *host;
+		socklen_t hostlen;
 		u_short msg = C_MESSAGE;
+		u_short num_players;
+		unsigned i;
+
+		serverlist_query(msg);
+		for (i = 0; i < serverlist_num(); i++) {
+			host = serverlist_gethost(i, &hostlen);
+			num_players = ntohs(serverlist_getresponse(i));
 
-		for (hosts = list_drivers(msg); hosts->sin_port != 0; hosts += 1) {
-			struct hostent *hp;
-			int num_players;
-
-			hp = gethostbyaddr((char *) &hosts->sin_addr,
-					sizeof hosts->sin_addr, AF_INET);
-			num_players = ntohs(hosts->sin_port);
 			printf("%d player%s hunting on %s!\n",
 				num_players, (num_players == 1) ? "" : "s",
-				hp != NULL ? hp->h_name :
-				inet_ntoa(hosts->sin_addr));
+				lookuphost(host, hostlen));
 		}
 		exit(0);
 	}
@@ -267,7 +291,7 @@ main(int ac, char **av)
 
 	for (;;) {
 #ifdef INTERNET
-		find_driver(true);
+		find_driver();
 
 		if (Daemon.sin_port == 0)
 			leavex(1, "Game not found, try again");
@@ -348,73 +372,81 @@ main(int ac, char **av)
 
 #ifdef INTERNET
 static void
-find_driver(bool do_startup)
+find_driver(void)
 {
-	SOCKET *hosts;
-	u_short msg = C_PLAYER;
+	u_short msg;
+	const struct sockaddr_storage *host;
+	socklen_t hostlen;
+	unsigned num;
+	int i, c;
+	char buf[128];
 
+	msg = C_PLAYER;
 #ifdef MONITOR
 	if (Am_monitor) {
 		msg = C_MONITOR;
 	}
 #endif
 
-	hosts = list_drivers(msg);
-	if (hosts[0].sin_port != htons(0)) {
-		int i, c;
-
-		if (hosts[1].sin_port == htons(0)) {
-			Daemon = hosts[0];
+	serverlist_query(msg);
+	num = serverlist_num();
+	if (num == 0) {
+		start_driver();
+		sleep(2);
+		/* try again */
+		serverlist_query(msg);
+		num = serverlist_num();
+		if (num == 0) {
+			/* give up */
 			return;
 		}
-		/* go thru list and return host that matches daemon */
+	}
+
+	if (num == 1) {
+		host = serverlist_gethost(0, &hostlen);
+	} else {
 		clear_the_screen();
 		move(1, 0);
 		put_str("Pick one:");
-		for (i = 0; i < HEIGHT - 4 && hosts[i].sin_port != htons(0);
-								i += 1) {
-			struct hostent *hp;
-			char buf[80];
-
+		for (i = 0; i < HEIGHT - 4 && i < (int)num; i++) {
 			move(3 + i, 0);
-			hp = gethostbyaddr((char *) &hosts[i].sin_addr,
-					sizeof hosts[i].sin_addr, AF_INET);
+			host = serverlist_gethost(i, &hostlen);
 			(void) snprintf(buf, sizeof(buf),
-				"%8c    %.64s", 'a' + i,
-				hp != NULL ? hp->h_name
-				: inet_ntoa(hosts->sin_addr));
+					"%8c    %.64s", 'a' + i,
+					lookuphost(host, hostlen));
 			put_str(buf);
 		}
 		move(4 + i, 0);
 		put_str("Enter letter: ");
 		refresh();
-		while (!islower(c = getchar()) || (c -= 'a') >= i) {
+		while (1) {
+			c = getchar();
+			if (c == EOF) {
+				leavex(1, "EOF on stdin");
+			}
+			if (islower((unsigned char)c) && c - 'a' < i) {
+				break;
+			}
 			beep();
 			refresh();
 		}
-		Daemon = hosts[c];
 		clear_the_screen();
-		return;
+		host = serverlist_gethost(c - 'a', &hostlen);
 	}
-	if (!do_startup)
-		return;
 
-	start_driver();
-	sleep(2);
-	find_driver(false);
+	/* XXX fix this (won't work in ipv6) */
+	assert(hostlen == sizeof(Daemon));
+	memcpy(&Daemon, host, sizeof(Daemon));
 }
 
 static void
-dump_scores(SOCKET host)
+dump_scores(const struct sockaddr_storage *host, socklen_t hostlen)
 {
-	struct hostent *hp;
 	int s;
 	char buf[BUFSIZ];
-	int cnt;
+	ssize_t cnt;
 
-	hp = gethostbyaddr((char *) &host.sin_addr, sizeof host.sin_addr,
-								AF_INET);
-	printf("\n%s:\n", hp != NULL ? hp->h_name : inet_ntoa(host.sin_addr));
+	printf("\n%s:\n", lookuphost(host, hostlen));
 	fflush(stdout);
 
 	s = socket(SOCK_FAMILY, SOCK_STREAM, 0);
@@ -597,12 +629,16 @@ fincurs(void)
  *	tty stats, and print errno.
  */
 void
-leave(int eval, const char *mesg)
+leave(int exitval, const char *fmt, ...)
 {
 	int serrno = errno;
+	va_list ap;
+
 	fincurs();
+	va_start(ap, fmt);
 	errno = serrno;
-	err(eval, "%s", mesg ? mesg : "");
+	verr(exitval, fmt, ap);
+	va_end(ap);
 }
 
 /*
@@ -611,10 +647,14 @@ leave(int eval, const char *mesg)
  *	tty stats.
  */
 void
-leavex(int eval, const char *mesg)
+leavex(int exitval, const char *fmt, ...)
 {
+	va_list ap;
+
 	fincurs();
-	errx(eval, "%s", mesg ? mesg : "");
+	va_start(ap, fmt);
+	verrx(exitval, fmt, ap);
+	va_end(ap);
 }
 
 static long

Index: src/games/hunt/hunt/hunt_private.h
diff -u src/games/hunt/hunt/hunt_private.h:1.6 src/games/hunt/hunt/hunt_private.h:1.7
--- src/games/hunt/hunt/hunt_private.h:1.6	Sun Mar 30 03:35:26 2014
+++ src/games/hunt/hunt/hunt_private.h	Sun Mar 30 04:31:21 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: hunt_private.h,v 1.6 2014/03/30 03:35:26 dholland Exp $	*/
+/*	$NetBSD: hunt_private.h,v 1.7 2014/03/30 04:31:21 dholland Exp $	*/
 
 /*
  * Copyright (c) 1983-2003, Regents of the University of California.
@@ -66,8 +66,6 @@ extern bool no_beep;
 #ifdef INTERNET
 /* XXX this pile had to be made public to split off server.c; fix them up */
 extern SOCKET Daemon;
-extern uint16_t Test_port;
-extern char *Sock_host;
 #endif
 
 /*
@@ -80,8 +78,8 @@ void do_connect(char *, char, long);
 /* in hunt.c */
 __dead void bad_con(void);
 __dead void bad_ver(void);
-__dead void leave(int, const char *);
-__dead void leavex(int, const char *);
+__dead __printflike(2, 3) void leave(int, const char *, ...);
+__dead __printflike(2, 3) void leavex(int, const char *, ...);
 void intr(int);
 
 /* in otto.c */
@@ -95,5 +93,9 @@ void do_message(void);
 
 /* in server.c */
 #ifdef INTERNET
-SOCKET *list_drivers(unsigned short msg);
+void serverlist_setup(const char *, uint16_t);
+void serverlist_query(unsigned short msg);
+unsigned serverlist_num(void);
+const struct sockaddr_storage *serverlist_gethost(unsigned, socklen_t *);
+unsigned short serverlist_getresponse(unsigned);
 #endif

Index: src/games/hunt/hunt/server.c
diff -u src/games/hunt/hunt/server.c:1.5 src/games/hunt/hunt/server.c:1.6
--- src/games/hunt/hunt/server.c:1.5	Sun Mar 30 03:26:19 2014
+++ src/games/hunt/hunt/server.c	Sun Mar 30 04:31:21 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: server.c,v 1.5 2014/03/30 03:26:19 dholland Exp $	*/
+/*	$NetBSD: server.c,v 1.6 2014/03/30 04:31:21 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.5 2014/03/30 03:26:19 dholland Exp $");
+__RCSID("$NetBSD: server.c,v 1.6 2014/03/30 04:31:21 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
@@ -60,13 +60,16 @@ __RCSID("$NetBSD: server.c,v 1.5 2014/03
 static SOCKET *daemons;
 static unsigned int numdaemons, maxdaemons;
 
+static SOCKET *brdv;
+static int brdc;
+
 static bool initial = true;
 static struct in_addr local_address;
-static int brdc;
-static SOCKET *brdv;
+static const char *explicit_host;
+static uint16_t port;
 
-static void
-serverlist_setup(void)
+void
+serverlist_setup(const char *explicit_host_arg, uint16_t port_arg)
 {
 	char local_name[MAXHOSTNAMELEN + 1];
 	struct hostent *hp;
@@ -86,6 +89,11 @@ serverlist_setup(void)
 	if (daemons == NULL) {
 		leavex(1, "Out of memory.");
 	}
+
+	if (explicit_host_arg) {
+		explicit_host = explicit_host_arg;
+	}
+	port = port_arg;
 }
 
 static void
@@ -111,6 +119,19 @@ add_daemon_addr(const struct sockaddr_st
 	 * Note that we do *not* convert from network to host
 	 * order since the port number we were sent *should*
 	 * already be in network order.
+	 *
+	 * The result may be either the port number for the hunt
+	 * socket or the port number for the stats socket... or the
+	 * number of players connected and not a port number at all,
+	 * depending on the packet type.
+	 *
+	 * For now at least it is ok to stuff it in here, because the
+	 * usage of the various different packet types and the
+	 * persistence of the results vs. the program exiting does not
+	 * cause us to get confused. If the game is made more
+	 * self-contained in the future we'll need to be more careful
+	 * about this, especially if we make the caching of results
+	 * less scattershot.
 	 */
 	daemons[numdaemons] = *sin;
 	daemons[numdaemons].sin_port = port_num;
@@ -166,6 +187,74 @@ getbroadcastaddrs(struct sockaddr_in **v
 }
 
 static void
+send_messages(int contactsock, unsigned short msg)
+{
+	struct sockaddr_in contactaddr;
+	struct hostent *hp;
+	uint16_t wiremsg;
+	int option;
+	int i;
+
+	contactaddr.sin_family = SOCK_FAMILY;
+	contactaddr.sin_port = htons(port);
+
+	if (explicit_host != NULL) {	/* explicit host given */
+		hp = gethostbyname(explicit_host);
+		if (hp == NULL) {
+			leavex(1, "%s: Unknown host", explicit_host);
+		}
+		memcpy(&contactaddr.sin_addr, hp->h_addr,
+		       sizeof(contactaddr.sin_addr));
+		wiremsg = htons(msg);
+		(void) sendto(contactsock, &wiremsg, sizeof(wiremsg), 0,
+			      (struct sockaddr *)&contactaddr,
+			      sizeof(contactaddr));
+		return;
+	}
+
+	if (!initial) {
+		/* favor host of previous session by contacting it first */
+		contactaddr.sin_addr = Daemon.sin_addr;
+
+		/* Must be playing! */
+		assert(msg == C_PLAYER);
+		wiremsg = htons(msg);
+
+		(void) sendto(contactsock, &wiremsg, sizeof(wiremsg), 0,
+		    (struct sockaddr *)&contactaddr, sizeof(contactaddr));
+	}
+
+	if (initial)
+		brdc = getbroadcastaddrs(&brdv);
+
+#ifdef SO_BROADCAST
+	/* Sun's will broadcast even though this option can't be set */
+	option = 1;
+	if (setsockopt(contactsock, SOL_SOCKET, SO_BROADCAST,
+	    &option, sizeof option) < 0) {
+		leave(1, "setsockopt broadcast");
+		/* NOTREACHED */
+	}
+#endif
+
+	/* send broadcast packets on all interfaces */
+	wiremsg = htons(msg);
+	for (i = 0; i < brdc; i++) {
+		contactaddr.sin_addr = brdv[i].sin_addr;
+		if (sendto(contactsock, &wiremsg, sizeof(wiremsg), 0,
+		    (struct sockaddr *)&contactaddr,
+		    sizeof(contactaddr)) < 0) {
+			leave(1, "sendto");
+		}
+	}
+	contactaddr.sin_addr = local_address;
+	if (sendto(contactsock, &wiremsg, sizeof(wiremsg), 0,
+	    (struct sockaddr *)&contactaddr, sizeof(contactaddr)) < 0) {
+		leave(1, "sendto");
+	}
+}
+
+static void
 get_responses(int contactsock)
 {
 	struct pollfd set[1];
@@ -217,102 +306,52 @@ get_responses(int contactsock)
 		add_daemon_addr(&addr, port_num);
 	}
 
-	/* 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 *
-list_drivers(unsigned short msg)
+void
+serverlist_query(unsigned short msg)
 {
-	struct hostent *hp;
-	struct sockaddr_in contactaddr;
-	int option;
-	uint16_t wiremsg;
 	int contactsock;
-	int i;
-
-	if (initial) {
-		/* do one time initialization */
-		serverlist_setup();
-	}
 
-	if (!initial && Sock_host != NULL) {
-		/* address already valid */
-		return daemons;
+	if (!initial && explicit_host != NULL) {
+		/* already did the work, no point doing it again */
+		return;
 	}
 
 	contactsock = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
 	if (contactsock < 0) {
 		leave(1, "socket system call failed");
 	}
-	contactaddr.sin_family = SOCK_FAMILY;
-	contactaddr.sin_port = htons(Test_port);
 
-	if (Sock_host != NULL) {	/* explicit host given */
-		if ((hp = gethostbyname(Sock_host)) == NULL) {
-			leavex(1, "Unknown host");
-			/* NOTREACHED */
-		}
-		memcpy(&contactaddr.sin_addr, hp->h_addr,
-		       sizeof(contactaddr.sin_addr));
-		wiremsg = htons(msg);
-		(void) sendto(contactsock, &wiremsg, sizeof(wiremsg), 0,
-			      (struct sockaddr *)&contactaddr,
-			      sizeof(contactaddr));
-		get_responses(contactsock);
-		(void) close(contactsock);
-		return daemons;
-	}
+	send_messages(contactsock, msg);
+	get_responses(contactsock);
 
-	if (!initial) {
-		/* 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,
-		    (struct sockaddr *)&contactaddr, sizeof(contactaddr));
-	}
+	(void) close(contactsock);
+}
 
-	if (initial)
-		brdc = getbroadcastaddrs(&brdv);
+unsigned
+serverlist_num(void)
+{
+	return numdaemons;
+}
 
-#ifdef SO_BROADCAST
-	/* Sun's will broadcast even though this option can't be set */
-	option = 1;
-	if (setsockopt(contactsock, SOL_SOCKET, SO_BROADCAST,
-	    &option, sizeof option) < 0) {
-		leave(1, "setsockopt broadcast");
-		/* NOTREACHED */
-	}
-#endif
+const struct sockaddr_storage *
+serverlist_gethost(unsigned i, socklen_t *len_ret)
+{
+	struct sockaddr_in *ret;
 
-	/* send broadcast packets on all interfaces */
-	wiremsg = htons(msg);
-	for (i = 0; i < brdc; i++) {
-		contactaddr.sin_addr = brdv[i].sin_addr;
-		if (sendto(contactsock, &wiremsg, sizeof(wiremsg), 0,
-		    (struct sockaddr *)&contactaddr,
-		    sizeof(contactaddr)) < 0) {
-			leave(1, "sendto");
-		}
-	}
-	contactaddr.sin_addr = local_address;
-	if (sendto(contactsock, &wiremsg, sizeof(wiremsg), 0,
-	    (struct sockaddr *)&contactaddr, sizeof(contactaddr)) < 0) {
-		leave(1, "sendto");
-	}
+	assert(i < numdaemons);
+	ret = &daemons[i];
+	*len_ret = sizeof(*ret);
+	return (struct sockaddr_storage *)ret;
+}
 
-	get_responses(contactsock);
-	(void) close(contactsock);
-	return daemons;
+unsigned short
+serverlist_getresponse(unsigned i)
+{
+	assert(i < numdaemons);
+	return daemons[i].sin_port;
 }
 
 #endif /* INTERNET */

Reply via email to