ftp.nice.ch/pub/next/games/network/MazeWar.2.0.NIHS.bs.tar.gz#/MazeWar/mazefind.c

This is mazefind.c in view mode; [Download] [Up]

/* $Header: mazefind.c,v 1.5 88/09/07 11:23:42 kent Exp $ */

/* 
 * mazefind.c - find ongoing mazewar games
 * 
 * Author:	Christopher A. Kent
 * 		Western Research Laboratory
 * 		Digital Equipment Corporation
 * Date:	Thu Dec  4 1986
 */

/***********************************************************
Copyright 1986 by Digital Equipment Corporation, Maynard, Massachusetts,

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Digital not be
used in advertising or publicity pertaining to disstribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

/*
 * $Log:	mazefind.c,v $
 * Revision 1.5  88/09/07  11:23:42  kent
 * 
 * 
 * Revision 1.4  88/08/25  09:57:53  kent
 * 
 * 
 * Revision 1.3  88/06/15  16:36:20  kent
 * 
 * 
 * Revision 1.2  87/03/31  14:42:26  kent
 * Portability considerations, especially byteswapping to/from the net.
 * 
 * Revision 1.1  86/12/04  17:19:31  kent
 * Initial revision
 * 
 */

static char rcs_ident[] = "$Header: mazefind.c,v 1.5 88/09/07 11:23:42 kent Exp $";

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>

#include <netinet/in.h>

#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <strings.h>

#include "mazewar.h"

struct answer {
	Sockaddr	source;
	int		srclen;
	RatPacket	packet;
};

Boolean	FoundOne = FALSE;

/* 
 * Broadcast to check out all the games on the net. This is basically
 * findDuke() from init.c.
 */

main()
{
	register int	i;
	int		cnt = 0;
	Sockaddr	rmtAddr;
	struct	timeval	timeout;
	RatPacket	*b = (RatPacket *) malloc(sizeof(RatPacket));
	struct answer	answer;
	int		fds, fd;
	int		ret, cc;
	int		mazePort;
	struct servent	*mazeService;
	char		buf[128];
	Boolean		duke(), freeSlot();
	struct in_addr	inet_makeaddr();
	Sockaddr	*resolveHost();

	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0)
		MFError("can't get socket");
#ifdef	SO_BROADCAST
#ifdef	BSD_43
	{
	int	one = 1;

	if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof one) < 0)
		MFError("can't get broadcast permission");
	}
#else	BSD_43
	if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, NULL, 0) < 0)
		MFError("can't get broadcast permission");
#endif	BSD_43
#endif	SO_BROADCAST

	mazeService = getservbyname(MAZESERVICE, "udp");
	if (mazeService != (struct servent *) NULL)
		mazePort = mazeService->s_port;
	else
		mazePort = htons(MAZEPORT);

	gethostname(buf, sizeof(buf));
	bcopy((char *)resolveHost(buf), (char *) &rmtAddr, sizeof(rmtAddr));
	rmtAddr.sin_addr = inet_makeaddr(inet_netof(rmtAddr.sin_addr),
					BROAD_ADDR);	/* from Makefile */
	rmtAddr.sin_port = mazePort;

	setupSurvey(b);
	ConvertOutgoing(b);
	if (sendto(fd, (char *) b, sizeof(*b), 0, (struct sockaddr *)&rmtAddr,
		    sizeof(rmtAddr)) < 0)
		MFError("survey");

	while (1) {
		fds = (1<<fd);
		timeout.tv_sec = 5;
		timeout.tv_usec = 0;
		ret = select(32, &fds, NULL, NULL, &timeout);
		if (ret < 0)
			MFError("select");
		if (ret == 0)
			break;
		answer.srclen = sizeof(Sockaddr);
		cc = recvfrom(fd, &answer.packet, sizeof(RatPacket),
			0, (struct sockaddr *)&answer.source, &answer.srclen);
		if (cc < 0)
			MFError("recv");
		ConvertIncoming(&answer.packet);
		if (answer.packet.type != RAT_STATUS)
			continue;
		if (!duke(&answer)) {
			RatStatus	rs;

			rs = (RatStatus) &answer.packet.body;
			setupSurvey(b);
			ConvertOutgoing(b);
			if (rs->rats[rs->dukeRat].addr.sin_port == mazePort)
				continue;	/* will answer himself */
				
			if (sendto(fd, b, sizeof(*b), 0,
				(struct sockaddr *)&rs->rats[rs->dukeRat].addr,
				   sizeof(rs->rats[rs->dukeRat].addr)) < 0)
				MFError("resend");
			continue;
		} else
			printAnswer(&answer);
	}
	if (FoundOne == FALSE)
		printf("No one's playing now\n");
	exit(0);
}

MFError(s)
char *s;
{
	fprintf(stderr, "mazefind: %s\n", s);
	perror("mazefind");
	exit(-1);
}

/* 
 * Fill in the RAT_SURVEY packet.
 */

setupSurvey(b)
RatPacket *b;
{
	RatNew	ratSurvey;

	b->type = RAT_SURVEY;
	ratSurvey = (RatNew) &b->body;
	ratSurvey->pass = RAT_PASSWORD;
}

/* 
 * Check if this guy's the duke of his game.
 */

Boolean
duke(a)
struct answer	*a;
{
	RatStatus	test;

	test = (RatStatus) &a->packet.body;
	return !bcmp((char *) &test->rats[test->dukeRat].addr.sin_addr,
			(char *) &a->source.sin_addr, sizeof(struct in_addr));
}

/* 
 * Decode an answer packet.
 */

printAnswer(a)
struct answer	*a;
{
	RatStatus	status;
	RatId		ratId;
	RatInfo		rat;
	struct hostent	*host;

	status = (RatStatus) &a->packet.body;
	
	if (FoundOne == FALSE) {
		FoundOne = TRUE;
		printf("Current game(s):\n");
		printf("\t%-20s\t%s\t\thost\n", "Name", "score");
	} else
		printf("\n");
	for(ratId = 0; ratId < MAXRATS; ratId++) {
		rat = (RatInfo) &status->rats[ratId];
		if (rat->playing == FALSE)
			continue;

		if (ratId == status->dukeRat)
			printf("duke");
		printf("\t");

		printf("%-20s\t%d\t\t", rat->name, rat->score);

		host = gethostbyaddr((char *)&rat->addr.sin_addr,
				sizeof(struct in_addr), AF_INET);
		if (host != NULL)
			printf("%s\n", host->h_name);
		else
			printf("%s\n", inet_ntoa(rat->addr.sin_addr));
	}
}

/*
 * Resolve the specified host name into an internet address.  The "name" may
 * be either a character string name, or an address in the form a.b.c.d where
 * the pieces are octal, decimal, or hex numbers.  Returns a pointer to a
 * sockaddr_in struct (note this structure is statically allocated and must
 * be copied), or NULL if the name is unknown.
 */

Sockaddr *
resolveHost(name)
register char *name;
{
	register struct hostent *fhost;
	struct in_addr fadd;
	static Sockaddr sa;

	if ((fhost = gethostbyname(name)) != NULL) {
		sa.sin_family = fhost->h_addrtype;
		sa.sin_port = 0;
		bcopy(fhost->h_addr, &sa.sin_addr, fhost->h_length);
	} else {
		fadd.s_addr = inet_addr(name);
		if (fadd.s_addr != -1) {
			sa.sin_family = AF_INET;	/* grot */
			sa.sin_port = 0;
			sa.sin_addr.s_addr = fadd.s_addr;
		} else
			return(NULL);
	}
	return(&sa);
}

/* 
 * Convert the contents of a packet to network order before sending.
 */

ConvertOutgoing(p)
RatPacket *p;
{
	char		buf[64];
	RatId		ratId;
	RatLocation	ratLoc;
	RatKill		ratKill;
	RatDead		ratDead;
	RatStatus	ratStatus;
	RatNew		ratNew;
	RatGone		ratGone;
	RatQuery	ratQuery;
	RatAlive	ratAlive;
	RatMove		ratMove;

	switch(p->type) {
	case RAT_LOCATION:
		ratLoc = (RatLocation) &p->body;
		ratLoc->ratId = htonl(ratLoc->ratId);
		ratLoc->xLoc =  htons(ratLoc->xLoc);
		ratLoc->yLoc =  htons(ratLoc->yLoc);
		ratLoc->dir =   htons(ratLoc->dir);
		ratLoc->score = htonl(ratLoc->score);
		break;

	case RAT_KILL:
		ratKill = (RatKill) &p->body;
		ratKill->ratId = htonl(ratKill->ratId);
		ratKill->xLoc  = htons(ratKill->xLoc);
		ratKill->yLoc  = htons(ratKill->yLoc);
		ratKill->dir   = htons(ratKill->dir);
		break;

	case RAT_DEAD:
		ratDead = (RatDead) &p->body;
		ratDead->ratId = htonl(ratDead->ratId);
		ratDead->killedBy = htonl(ratDead->killedBy);
		break;

	case RAT_STATUS:
		ratStatus = (RatStatus) &p->body;
		ratStatus->dukeRat = htonl(ratStatus->dukeRat);
		for (ratId = 0; ratId < MAXRATS; ratId++) {
			RatInfo	ratInfo;

			ratInfo = &ratStatus->rats[ratId];
			ratInfo->playing = htons(ratInfo->playing);
			ratInfo->xLoc = htons(ratInfo->xLoc);
			ratInfo->yLoc = htons(ratInfo->yLoc);
			ratInfo->dir = htons(ratInfo->dir);
			ratInfo->score = htonl(ratInfo->score);
			ratInfo->addr.sin_family =
				ntohs(ratInfo->addr.sin_family);
			/* don't touch address or name */
		}
		break;

	case RAT_NEW:
		ratNew = (RatNew) &p->body;
		ratNew->pass = htons(ratNew->pass);
		ratNew->xLoc = htons(ratNew->xLoc);
		ratNew->yLoc = htons(ratNew->yLoc);
		ratNew->dir  = htons(ratNew->dir);
		ratNew->addr.sin_family =
			htons(ratNew->addr.sin_family);
		/* don't touch address or name */
		break;

	case RAT_GOING:
		ratGone = (RatGone) &p->body;
		ratGone->ratId = htonl(ratGone->ratId);
		break;

	case RAT_QUERY:
		ratQuery = (RatQuery) &p->body;
		ratQuery->ratId = htonl(ratQuery->ratId);
		break;

	case RAT_ALIVE:
		ratAlive = (RatAlive) &p->body;
		ratAlive->ratId = htonl(ratAlive->ratId);
		break;

	case RAT_SURVEY:
		ratNew = (RatNew) &p->body;
		ratNew->pass = htons(ratNew->pass);
		ratNew->xLoc = htons(ratNew->xLoc);
		ratNew->yLoc = htons(ratNew->yLoc);
		ratNew->dir  = htons(ratNew->dir);
		/* don't touch address or name */
		break;

	case RAT_MOVE:
		ratMove = (RatMove) &p->body;
		ratMove->ratId = htonl(ratMove->ratId);
		break;

	default:
		sprintf(buf, "ConvertOutgoing bad type %d (%d)",
			p->type, htons(p->type));
		MFError(buf);
	}
	p->type = htonl(p->type);
}

/* 
 * Convert the contents of a packet to host order after ConvertIncoming.
 */

ConvertIncoming(p)
RatPacket *p;
{
	char		buf[64];
	RatId		ratId;
	RatLocation	ratLoc;
	RatKill		ratKill;
	RatDead		ratDead;
	RatStatus	ratStatus;
	RatNew		ratNew;
	RatGone		ratGone;
	RatQuery	ratQuery;
	RatAlive	ratAlive;
	RatMove		ratMove;

	p->type = ntohl(p->type);
	switch(p->type) {
	case RAT_LOCATION:
		ratLoc = (RatLocation) &p->body;
		ratLoc->ratId = ntohl(ratLoc->ratId);
		ratLoc->xLoc =  ntohs(ratLoc->xLoc);
		ratLoc->yLoc =  ntohs(ratLoc->yLoc);
		ratLoc->dir =   ntohs(ratLoc->dir);
		ratLoc->score = ntohl(ratLoc->score);
		break;

	case RAT_KILL:
		ratKill = (RatKill) &p->body;
		ratKill->ratId = ntohl(ratKill->ratId);
		ratKill->xLoc  = ntohs(ratKill->xLoc);
		ratKill->yLoc  = ntohs(ratKill->yLoc);
		ratKill->dir   = ntohs(ratKill->dir);
		break;

	case RAT_DEAD:
		ratDead = (RatDead) &p->body;
		ratDead->ratId = ntohl(ratDead->ratId);
		ratDead->killedBy = ntohl(ratDead->killedBy);
		break;

	case RAT_STATUS:
		ratStatus = (RatStatus) &p->body;
		ratStatus->dukeRat = ntohl(ratStatus->dukeRat);
		for (ratId = 0; ratId < MAXRATS; ratId++) {
			RatInfo	ratInfo;

			ratInfo = &ratStatus->rats[ratId];
			ratInfo->playing = ntohs(ratInfo->playing);
			ratInfo->xLoc = ntohs(ratInfo->xLoc);
			ratInfo->yLoc = ntohs(ratInfo->yLoc);
			ratInfo->dir = ntohs(ratInfo->dir);
			ratInfo->score = ntohl(ratInfo->score);
			ratInfo->addr.sin_family =
				ntohs(ratInfo->addr.sin_family);
			/* don't touch address or name */
		}
		break;

	case RAT_NEW:
		ratNew = (RatNew) &p->body;
		ratNew->pass = ntohs(ratNew->pass);
		ratNew->xLoc = ntohs(ratNew->xLoc);
		ratNew->yLoc = ntohs(ratNew->yLoc);
		ratNew->dir  = ntohs(ratNew->dir);
		ratNew->addr.sin_family =
			ntohs(ratNew->addr.sin_family);
		/* don't touch address or name */
		break;

	case RAT_GOING:
		ratGone = (RatGone) &p->body;
		ratGone->ratId = ntohl(ratGone->ratId);
		break;

	case RAT_QUERY:
		ratQuery = (RatQuery) &p->body;
		ratQuery->ratId = ntohl(ratQuery->ratId);
		break;

	case RAT_ALIVE:
		ratAlive = (RatAlive) &p->body;
		ratAlive->ratId = ntohl(ratAlive->ratId);
		break;

	case RAT_SURVEY:
		ratNew = (RatNew) &p->body;
		ratNew->pass = ntohs(ratNew->pass);
		ratNew->xLoc = ntohs(ratNew->xLoc);
		ratNew->yLoc = ntohs(ratNew->yLoc);
		ratNew->dir  = ntohs(ratNew->dir);
		/* don't touch address or name */
		break;

	case RAT_MOVE:
		ratMove = (RatMove) &p->body;
		ratMove->ratId = ntohl(ratMove->ratId);
		break;

	default:
		sprintf(buf, "ConvertIncoming bad type %d (%d)",
			p->type, ntohs(p->type));
		MFError(buf);
	}
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.