home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume15
/
xstratego
/
part02
/
socket.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-27
|
6KB
|
259 lines
/*
* Socket.h
*
* Initial handshake and pecking order determination module.
*/
#include "stratego.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
static struct sockaddr_in channel;
static void read_player_data (), write_player_data ();
static void read_data (), write_data ();
static void perror_exit (label)
char *label;
{
perror (label);
exit (-1);
}
static int generate_port (name)
char *name;
{
int port = 1;
while (*name != '\0')
port *= (*name++ & 0xFF);
return (port & ~0x8000) | 0x4000;
}
static void setup_channel (machine, port_name)
char *machine;
char *port_name;
{
struct hostent *hostentry;
if ((hostentry = gethostbyname (machine)) == NULL) {
fprintf (stderr, "%s: No such host\n", machine);
exit (-1);
}
channel.sin_family = AF_INET;
channel.sin_port = htons (generate_port (port_name));
channel.sin_addr = (*(struct in_addr *) hostentry->h_addr);
}
static int connect_socket (machine, port_name)
char *machine;
char *port_name;
{
int s, retries;
setup_channel (machine, port_name);
for (retries = 60; retries > 0; retries--) {
if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
perror_exit ("connect_socket: socket()");
if (connect (s, (struct sockaddr *) &channel, sizeof (channel))
>=0) break;
sleep (2);
close(s);
}
return retries ? s : -1;
}
static int make_socket (machine, port_name)
char *machine;
char *port_name;
{
int s, size;
struct sockaddr_in get_chan;
setup_channel (machine, port_name);
if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
perror_exit ("make_socket: socket()");
if (bind (s, (struct socketaddr *) &channel, sizeof (channel)) < 0)
return -1;
if (listen (s, 1) < 0)
perror_exit ("make_socket: listen()");
size = sizeof (get_chan);
if ((s = accept (s, &get_chan, &size)) < 0)
perror_exit ("make_socket: accept()");
return s;
}
void setup_communication (name, opponent, machine)
char *name, *opponent, *machine;
{
struct hostent *hostentry;
char new_port[20];
int fd, cmp;
Boolean master;
char *port, *ptr;
time_t start;
strcpy (players[0].name, name);
strcpy (players[0].login, cuserid (NULL));
if (gethostname (players[0].machine, MAXHOSTNAMELEN) < 0)
perror_exit ("Can't find your machine name.\n");
/* Strip domain name from machine name (if any) */
for (ptr = players[0].machine; *ptr != '\0' && *ptr != '.'; ptr++)
;
*ptr = '\0';
if (getdomainname (players[0].domain, NAME_LENGTH) < 0)
perror_exit ("Can't find your domain name.\n");
if ((hostentry = gethostbyname (machine)) == NULL)
perror_exit ("Can't find opponents machine name.\n");
strcpy (players[1].login, opponent);
strncpy (players[1].machine, hostentry->h_name, MAXHOSTNAMELEN);
players[1].machine[MAXHOSTNAMELEN - 1] = '\0';
/* Strip domain name from machine name (if any) */
for (ptr = players[1].machine; *ptr != '\0' && *ptr != '.'; ptr++)
;
*ptr = '\0';
if ((cmp = strcmp (players[0].login, players[1].login)) == 0)
cmp = strcmp (players[0].machine, players[1].machine);
master = (cmp <= 0) ? True : False;
if (master == True) {
machine = players[0].machine;
port = players[0].login;
printf ("Waiting for response from \"%s@%s\"...",
players[1].login, players[1].machine);
fflush (stdout);
if ((fd = make_socket (machine, port)) < 0) {
if (cmp != 0)
perror_exit ("Cannot setup communications channel to opponent");
master = False;
}
}
if (master == False) {
machine = players[1].machine;
port = players[1].login;
printf ("Connecting to \"%s@%s\"...", port, machine);
fflush (stdout);
if ((fd = connect_socket (machine, port)) < 0)
perror_exit ("Cannot setup communications channel to opponent");
}
printf ("\n\nConnected.\n");
fflush (stdout);
if (master == False) {
read_data (fd, new_port, sizeof (new_port));
close (fd);
start = time (NULL);
do {
fd = connect_socket (machine, new_port);
} while (fd == -1 && time (NULL) < start + 5);
if (fd == -1)
perror_exit ("Cannot reconnect to opponent");
write_player_data (fd, &players[0]);
read_player_data (fd, &players[1]);
players[0].has_first_move = !players[1].has_first_move;
}
else {
sprintf (new_port, "comm%u", time(0));
write_data (fd, new_port, sizeof (new_port));
close (fd);
if ((fd = make_socket (machine, new_port)) < 0)
perror_exit ("Cannot recontact opponent");
srand ((time (NULL) ^ getpid ()) >> 3);
players[0].has_first_move = (rand () >> 4) & 0x01;
read_player_data (fd, &players[1]);
write_player_data (fd, &players[0]);
}
players[1].fd = fd;
signal (SIGIO, SIG_IGN);
fcntl (fd, F_SETFL, FASYNC);
fcntl (fd, F_SETOWN, getpid ());
}
static void read_player_data (fd, player)
int fd;
PLAYER *player;
{
read_data (fd, player->name, sizeof (player->name));
read_data (fd, player->login, sizeof (player->login));
read_data (fd, player->machine, sizeof (player->machine));
read_data (fd, player->domain, sizeof (player->domain));
read_data (fd, &player->has_first_move, sizeof (player->has_first_move));
}
static void write_player_data (fd, player)
int fd;
PLAYER *player;
{
write_data (fd, player->name, sizeof (player->name));
write_data (fd, player->login, sizeof (player->login));
write_data (fd, player->machine, sizeof (player->machine));
write_data (fd, player->domain, sizeof (player->domain));
write_data (fd, &player->has_first_move, sizeof(player->has_first_move));
}
static void read_data (fd, output, length)
int fd, length;
char *output;
{
int bytes;
if ((bytes = read (fd, output, length)) != length) {
fprintf (stderr, "Read %d instead of %d bytes.\n", bytes,
length);
perror_exit ("read_data: read()");
}
}
static void write_data (fd, input, length)
int fd, length;
char *input;
{
while (length > 0) {
int r, persist = 30;
while ((r = write (fd, input, length)) < 0) {
if (--persist == 0)
perror_exit ("write_data: write()");
sleep (2);
}
input += r;
length -= r;
}
}