home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume11
/
bt
/
part02
/
interface.c
next >
Wrap
C/C++ Source or Header
|
1990-12-11
|
9KB
|
419 lines
/* interface.c: Socket communications support& medium- level message
* passing functions. Copyright (C) 1990 Tom Boutell on original portions.
* All low- level socket code drawn with appreciation from:
* SOCK.C
* Copyright (C)1989 Dr Evil Laboratories
* This code written by Ray Moody, Roy Riggs, Mitch Adler,
* Bill Burdick, and Steven Grady
* No one makes any guarantees about anything. This file maybe
* freely distributed and modified as long as this header remains intact.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <netdb.h>
#include <varargs.h>
#include "types.h"
#include "pack.h"
#include "bt.h"
#include "interface.h"
#define DEBUG
#undef DEBUG
#ifdef DEBUG
#define debug printf
#else
#define debug 0+
#define perror 0+
#endif
#define SECONDSLIMIT 0L
#define MICROSECONDSLIMIT 1L
#define LINE_LEN 1024
#define LOST_CARRIER_MSG "F"
#define NONE (fd_set *) NULL
#define NEVER (struct timeval *) NULL
#define IGNORE (struct sockaddr *) NULL
fd_set active;
struct sockaddr_in sc_in;
int s;
char cur_input[LINE_LEN];
char *curhostname = "";
int playerids[20];
char outputline[256];
void setupinterface() {
int current;
init_socket(2727);
playertext=(outputline+1);
for (current=1; (current<=totalplayers); current++) {
playerids[current]=new_player(0);
players[current].live=1;
printf("Player %d has joined.\n",current);
outputline[0]=_YOUARE;
outputline[1]=64+current;
outputline[2]=0;
w_p(playerids[current],outputline,strlen(&outputline[0])+1);
}
}
void tellplayer(player)
int player;
{
outputline[0]=_TEXT;
w_p(playerids[player],outputline,strlen(&outputline[0])+1);
}
void broadcast(messagetype,details)
char messagetype;
void* details;
{
location where;
int thisplayer;
int current;
outputline[0]=messagetype;
switch (messagetype) {
case _HEXSTATUS:
where=*(location*)details;
outputline[1]=64+where.x;
outputline[2]=64+where.y;
outputline[3]=64+map[where.x][where.y].terrain;
packint(4,map[where.x][where.y].population);
packint(7,map[where.x][where.y].lastuse);
packint(10,map[where.x][where.y].troops);
outputline[13]=map[where.x][where.y].owner+64;
outputline[14]=NULL;
break;
case _PLAYERSTATUS:
thisplayer=*(int*)details;
outputline[1]=thisplayer+64;
packint(2,players[thisplayer].action);
packint(5,players[thisplayer].hexes);
packint(8,players[thisplayer].troops);
packint(11,players[thisplayer].population);
packint(14,players[thisplayer].citadels);
outputline[17]=players[thisplayer].start.x+64;
outputline[18]=players[thisplayer].start.y+64;
outputline[19]=NULL;
break;
case _PLAYERDEAD:
thisplayer=*(int*)details;
outputline[1]=thisplayer+64;
outputline[2]=NULL;
break;
case _ACTION:
outputline[1]=NULL;
break;
case _STARTUP:
outputline[1]=totalplayers+64;
outputline[2]=NULL;
break;
case _TEXT:
strcpy(&outputline[1],(char*) details);
break;
case _END:
outputline[1]=NULL;
}
for (current=0; (current<=totalplayers); current++) {
if (outputline[0]==_END) {
}
if (players[current].live) {
w_p(playerids[current],outputline,strlen(outputline)+1);
}
}
}
int getrequest(thisplayer,requesttype,specific)
int* thisplayer;
char* requesttype;
char* specific;
{
char* received;
static int sweep;
int oldsweep;
sweep++;
if ((sweep>totalplayers) || (sweep<=0))
sweep=1;
oldsweep=sweep;
while (players[sweep].live==0) {
sweep++;
if (sweep>totalplayers)
sweep=1;
if (sweep==oldsweep)
return 0;
}
received=read_player(playerids[sweep]);
*thisplayer=sweep;
if (*received==NULL)
return 0;
*requesttype=received[0];
strcpy(specific,(received+=1));
return 1;
}
void shutdowninterface() {
disconnect_all();
}
/* - PD Socket code begins here.
* init_socket() - intialize our socket, port is the port number to use
* call this once at the beginning of your code
*/
int init_socket(port)
int port;
{
setbuf(stdout, (char *)0);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 0;
}
sc_in.sin_family = AF_INET;
sc_in.sin_addr.s_addr = INADDR_ANY;
sc_in.sin_port = htons((u_short) port);
if (bind(s, (struct sockaddr *) &sc_in, sizeof(sc_in)) < 0) {
perror("bind");
return 0;
}
if (listen(s, 5) < 0) {
perror("listen");
return 0;
}
FD_ZERO(&active);
return 1;
}
/*
* disconnect_all() - throws everyone off
*/
int disconnect_all()
{
register int i;
for (i = 0; i < FD_SETSIZE; i++) {
if (FD_ISSET(i, &active))
(void) disconnect(i);
}
return 1;
}
/*
* shut-down -- kills all connections and exits the pgm
*/
int shut_down()
{
(void) disconnect_all();
exit(0);
}
/* hostfrom() - returns a string containing an ascii name for the host
* that the passed socket s is connected to. Note that the
* string is in static space. If you want to munge with it,
* make a copy.
*/
char *hostfrom(i)
int i;
{
struct sockaddr_in from;
int fromlen = sizeof(from);
struct hostent *host;
struct in_addr addr;
if (getpeername(i, &from, &fromlen) < 0) {
perror("getpeername");
return NULL;
}
addr = from.sin_addr;
if ((host = gethostbyaddr(&addr, sizeof(addr), AF_INET)) == NULL) {
debug("gethostbyaddr failed");
return NULL;
}
return curhostname = host->h_name;
}
/*
* hostname() - returns curhostname
*/
char *hostname()
{
return curhostname;
}
/*
* new_player() - call this routine in your main loop to allow new
* players to join. returns a playerId or -1 if no one
* wants to join.
* if wait == 0, then put your process to sleep until
* someone new tries to connect.
*/
int new_player(wait)
int wait; /* 0 - wait for activity, else don't wait */
{
fd_set readfds;
int j;
struct timeval *pWaitTime, waitTime;
pWaitTime = &waitTime;
if (0 == wait) {
pWaitTime = NEVER;
} else {
pWaitTime->tv_sec = SECONDSLIMIT;
pWaitTime->tv_usec = MICROSECONDSLIMIT;
}
bcopy((char *) &active, (char *) &readfds, sizeof(active));
FD_SET(s, &readfds);
if (select(FD_SETSIZE, &readfds, NONE, NONE, pWaitTime) < 0) {
perror("select");
return -1;
}
if (FD_ISSET(s, &readfds)) {
if ((j = accept(s, IGNORE, (int *) 0)) < 0) {
return -1;
}
FD_SET(j, &active);
curhostname = hostfrom(j);
debug("Test Host=%s\n", curhostname);
return j;
} else {
return -1;
}
}
/*
* disconnect() - drop the player with the given id
*/
int disconnect(id)
int id;
{
if (FD_ISSET(id, &active)) {
debug("** Just dropped %d\n", id);
FD_CLR(id, &active);
if (close(id) < 0) {
perror("close");
return 0;
}
} else {
debug("** Just tried to drop someone not connected\n");
return 0;
}
return 1;
}
/*
* read_player() - This routine returns the next string from the player
* connected to descriptor playerFd. If there is no
* input it returns the empty string. If the connection
* is lost the string LOST_CARRIER_MSG is returned.
* NOTE: control characters are replaced by spaces
* and it is null terminated at the first nl/cr
*/
char *read_player(playerFd)
int playerFd;
{
fd_set readfds;
struct timeval waitTime;
waitTime.tv_sec = SECONDSLIMIT;
waitTime.tv_usec = MICROSECONDSLIMIT;
bcopy((char *) &active, (char *) &readfds, sizeof(active));
if (select(FD_SETSIZE, &readfds, NONE, NONE, &waitTime) < 0) {
perror("select");
return("");
}
if (FD_ISSET(playerFd, &readfds)) {
int nbytes, i;
nbytes = read(playerFd, cur_input, LINE_LEN);
if (nbytes < 0) {
perror("read");
disconnect(playerFd);
return(LOST_CARRIER_MSG);
} else if (nbytes == 0) {
disconnect(playerFd);
return(LOST_CARRIER_MSG);
} else {
/* Don't need control editing for(i=0; i<nbytes; ++i) {
if (iscntrl(cur_input[i])) {
if (cur_input[i]=='\n' ||
cur_input[i]=='\r')
cur_input[i] = '\n';
else
cur_input[i] = ' ';
}
}
*/
if (nbytes != LINE_LEN) {
cur_input[nbytes] = '\0';
} else {
cur_input[LINE_LEN - 1] = '\0';
}
return((char *) cur_input);
}
}
return("");
}
/*
* write_player() - write to id, a string with the given length
*/
int w_p(id, str, len)
int id, len;
char *str;
{
if (id > -1) {
if (!FD_ISSET(id, &active)) {
debug("** Tried to write to closed id #%d.\n", id);
return 0;
} else if (write(id, str, len) < 0) {
perror("Write");
return 0;
}
}
return 1;
}