From cd13042d23065cae90a02dae4f7602a2b4eb7ce0 Mon Sep 17 00:00:00 2001 From: dholland Date: Sun, 30 Mar 2014 02:46:57 +0000 Subject: goto considered harmful --- hunt/hunt/server.c | 206 +++++++++++++++++++++++++++++------------------------ 1 file changed, 111 insertions(+), 95 deletions(-) (limited to 'hunt') diff --git a/hunt/hunt/server.c b/hunt/hunt/server.c index da7f14d2..9d9ab30b 100644 --- a/hunt/hunt/server.c +++ b/hunt/hunt/server.c @@ -1,4 +1,4 @@ -/* $NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $ */ +/* $NetBSD: server.c,v 1.2 2014/03/30 02:46:57 dholland Exp $ */ /* * Copyright (c) 1983-2003, Regents of the University of California. * All rights reserved. @@ -31,7 +31,7 @@ */ #include -__RCSID("$NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $"); +__RCSID("$NetBSD: server.c,v 1.2 2014/03/30 02:46:57 dholland Exp $"); #include #include @@ -53,8 +53,43 @@ __RCSID("$NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $"); #ifdef INTERNET +/* + * Code for finding and talking to hunt daemons. + */ + +static SOCKET *listv; +static unsigned int listmax; + +static SOCKET test; +static bool initial = true; +static struct in_addr local_address; +struct hostent *hp; +static int brdc; +static SOCKET *brdv; + +static void +serverlist_setup(void) +{ + char local_name[MAXHOSTNAMELEN + 1]; + + if (gethostname(local_name, sizeof(local_name)) < 0) { + leavex(1, "Sorry, I have no hostname."); + } + local_name[sizeof(local_name) - 1] = '\0'; + if ((hp = gethostbyname(local_name)) == NULL) { + leavex(1, "Can't find myself."); + } + memcpy(&local_address, hp->h_addr, sizeof(local_address)); + + listmax = 20; + listv = malloc(listmax * sizeof(listv[0])); + if (listv == NULL) { + leavex(1, "Out of memory."); + } +} + static int -broadcast_vec(int s /*socket*/, struct sockaddr_in **vector) +getbroadcastaddrs(int s /*socket*/, struct sockaddr_in **vector) { int vec_cnt; struct ifaddrs *ifp, *ip; @@ -82,53 +117,83 @@ broadcast_vec(int s /*socket*/, struct sockaddr_in **vector) return vec_cnt; } -SOCKET * -list_drivers(void) +static void +get_responses(int contactsock) { - int option; - u_short msg; u_short port_num; - static SOCKET test; - int test_socket; - socklen_t namelen; - char local_name[MAXHOSTNAMELEN + 1]; - static bool initial = true; - static struct in_addr local_address; - struct hostent *hp; - static int brdc; - static SOCKET *brdv; - int i; unsigned j; - static SOCKET *listv; - static unsigned int listmax; unsigned int listc; struct pollfd set[1]; + socklen_t namelen; - if (initial) { /* do one time initialization */ - if (gethostname(local_name, sizeof local_name) < 0) { - leavex(1, "Sorry, I have no name."); - /* NOTREACHED */ + listc = 0; + namelen = sizeof(test); + 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; } - local_name[sizeof(local_name) - 1] = '\0'; - if ((hp = gethostbyname(local_name)) == NULL) { - leavex(1, "Can't find myself."); - /* NOTREACHED */ + + if (poll(set, 1, 1000) == 1 && + recvfrom(contactsock, &port_num, sizeof(port_num), + 0, (struct sockaddr *) &listv[listc], &namelen) > 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; + continue; } - local_address = * ((struct in_addr *) hp->h_addr); - listmax = 20; - listv = (SOCKET *) malloc(listmax * sizeof (SOCKET)); + if (errno != 0 && errno != EINTR) { + leave(1, "poll/recvfrom"); + } + + /* terminate list with local address */ + listv[listc].sin_family = SOCK_FAMILY; + listv[listc].sin_addr = local_address; + listv[listc].sin_port = htons(0); + + (void) close(contactsock); + initial = false; + break; + } +} + +SOCKET * +list_drivers(void) +{ + int option; + u_short msg; + int contactsock; + int i; + + if (initial) { + /* do one time initialization */ + serverlist_setup(); } else if (Sock_host != NULL) return listv; /* address already valid */ - test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0); - if (test_socket < 0) { + contactsock = socket(SOCK_FAMILY, SOCK_DGRAM, 0); + if (contactsock < 0) { leave(1, "socket system call failed"); - /* NOTREACHED */ } test.sin_family = SOCK_FAMILY; test.sin_port = htons(Test_port); - listc = 0; if (Sock_host != NULL) { /* explicit host given */ if ((hp = gethostbyname(Sock_host)) == NULL) { @@ -136,24 +201,28 @@ list_drivers(void) /* NOTREACHED */ } test.sin_addr = *((struct in_addr *) hp->h_addr); - goto test_one_host; + msg = htons(C_TESTMSG()); + (void) sendto(contactsock, &msg, sizeof msg, 0, + (struct sockaddr *) &test, sizeof(test)); + get_responses(contactsock); + return listv; } if (!initial) { /* favor host of previous session by broadcasting to it first */ test.sin_addr = Daemon.sin_addr; msg = htons(C_PLAYER); /* Must be playing! */ - (void) sendto(test_socket, &msg, sizeof msg, 0, + (void) sendto(contactsock, &msg, sizeof msg, 0, (struct sockaddr *) &test, sizeof(test)); } if (initial) - brdc = broadcast_vec(test_socket, &brdv); + brdc = getbroadcastaddrs(contactsock, &brdv); #ifdef SO_BROADCAST /* Sun's will broadcast even though this option can't be set */ option = 1; - if (setsockopt(test_socket, SOL_SOCKET, SO_BROADCAST, + if (setsockopt(contactsock, SOL_SOCKET, SO_BROADCAST, &option, sizeof option) < 0) { leave(1, "setsockopt broadcast"); /* NOTREACHED */ @@ -164,72 +233,19 @@ list_drivers(void) msg = htons(C_TESTMSG()); for (i = 0; i < brdc; i++) { test.sin_addr = brdv[i].sin_addr; - if (sendto(test_socket, &msg, sizeof msg, 0, + if (sendto(contactsock, &msg, sizeof msg, 0, (struct sockaddr *) &test, sizeof(test)) < 0) { leave(1, "sendto"); - /* NOTREACHED */ } } test.sin_addr = local_address; - if (sendto(test_socket, &msg, sizeof msg, 0, + if (sendto(contactsock, &msg, sizeof msg, 0, (struct sockaddr *) &test, sizeof(test)) < 0) { leave(1, "sendto"); - /* NOTREACHED */ } -get_response: - namelen = sizeof(test); - errno = 0; - set[0].fd = test_socket; - 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; - } - - if (poll(set, 1, 1000) == 1 && - recvfrom(test_socket, &port_num, sizeof(port_num), - 0, (struct sockaddr *) &listv[listc], &namelen) > 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; - continue; - } - - if (errno != 0 && errno != EINTR) { - leave(1, "poll/recvfrom"); - /* NOTREACHED */ - } - - /* terminate list with local address */ - listv[listc].sin_family = SOCK_FAMILY; - listv[listc].sin_addr = local_address; - listv[listc].sin_port = htons(0); - - (void) close(test_socket); - initial = false; - return listv; - } - -test_one_host: - msg = htons(C_TESTMSG()); - (void) sendto(test_socket, &msg, sizeof msg, 0, - (struct sockaddr *) &test, sizeof(test)); - goto get_response; + get_responses(contactsock); + return listv; } #endif /* INTERNET */ -- cgit v1.2.3-56-ge451