summaryrefslogtreecommitdiffstats
path: root/hunt
diff options
context:
space:
mode:
authordholland <dholland@NetBSD.org>2014-03-30 04:31:21 +0000
committerdholland <dholland@NetBSD.org>2014-03-30 04:31:21 +0000
commit4c815854a9d17ac78d0088e0955ada99898b5ca5 (patch)
treec6a5bba1d58bb9a4e3ffc5e69ead86662d65f9d8 /hunt
parentf689b0566f9be25f5e451afb3c21426a10b688f1 (diff)
downloadbsdgames-darwin-4c815854a9d17ac78d0088e0955ada99898b5ca5.tar.gz
bsdgames-darwin-4c815854a9d17ac78d0088e0955ada99898b5ca5.tar.zst
bsdgames-darwin-4c815854a9d17ac78d0088e0955ada99898b5ca5.zip
Clean up the handling of the list of hunt daemons.
Diffstat (limited to 'hunt')
-rw-r--r--hunt/hunt/hunt.c158
-rw-r--r--hunt/hunt/hunt_private.h14
-rw-r--r--hunt/hunt/server.c207
3 files changed, 230 insertions, 149 deletions
diff --git a/hunt/hunt/hunt.c b/hunt/hunt/hunt.c
index 5da57db3..ca481383 100644
--- a/hunt/hunt/hunt.c
+++ b/hunt/hunt/hunt.c
@@ -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/30 03:35:26 dholland Exp $");
#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;
- for (hosts = list_drivers(msg); hosts->sin_port != 0; hosts += 1) {
- struct hostent *hp;
- int num_players;
+ serverlist_query(msg);
+ for (i = 0; i < serverlist_num(); i++) {
+ host = serverlist_gethost(i, &hostlen);
+ num_players = ntohs(serverlist_getresponse(i));
- 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
diff --git a/hunt/hunt/hunt_private.h b/hunt/hunt/hunt_private.h
index db1c8672..7e5ba3a6 100644
--- a/hunt/hunt/hunt_private.h
+++ b/hunt/hunt/hunt_private.h
@@ -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
diff --git a/hunt/hunt/server.c b/hunt/hunt/server.c
index ac7a4fde..a909d2d0 100644
--- a/hunt/hunt/server.c
+++ b/hunt/hunt/server.c
@@ -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/30 03:26:19 dholland Exp $");
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_storage *addr, uint16_t port_num)
* 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 **vector)
}
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 */