home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char sccsid[] = "@(#)netio.c 1.2 92/05/28 SMI" ;
- /* from netio.c 1.4 90/05/02 SMI */
- #endif
-
- /*
- * Copyright (c) 1986 by Sun Microsystems, Inc.
- */
-
- /*
- * this is generic network stuff. Communications functions are:
- *
- * init_netio(username,mastername)
- * intialize communications. Called before notifier is started up.
- *
- * net_start_message(who)
- * start building out-going message, if who=NULL, then this is
- * a broadcast message. Implicit flush if who is different than
- * previous addressee.
- *
- * net_flush()
- * flush outgoing message queue
- *
- * send_status(obj)
- * add object's status to outgoing message
- *
- * net_blow_away(weapon, object)
- * called when we've shot object
- *
- * net_remove_player(id)
- * remove player from game
- *
- * net_request_missile()
- * ask master for missile assignment
- *
- * net_poll()
- * called every 5 seconds to do bookkeeping
- *
- * handle_message(me, fd)
- * deal with an incoming message
- *
- *
- *
- */
-
-
-
- /* NOTES:
- *
- * There is no more daemon. The first player to join a local net
- * becomes the master for that net. The master for a net can
- * be slaved to the master for a game.
- *
- * Algorithms:
- *
- * when the program starts up, it sends a net_joining packet out and
- * starts the game as object id #0. If, after 5 seconds, no NET_WELCOME
- * packet arrives, it makes itself the master for the subnet.
- *
- * if a NET_WELCOME response is received within five seconds, the program
- * becomes a slave. It also moves its own status info into the assigned
- * slot.
- *
- * When the master receives a net_joining message, it responds with a
- * net_welcome message followed by a list of object descriptions for
- * all the other players in the game. It also sends the object
- * description for this player to all the other players.
- *
- * Every ten seconds, the master polls all the players on its subnet
- * to make sure they're alive. If not, a net_died message is sent out.
- *
- * If player #1 doesn't hear a poll from the master in 20 seconds, it
- * takes over as master.
- *
- *
- * If a program is a master and it has been given a hostname
- * as an argument, it tries to contact the master on that host. If
- * this is successful, it becomes a "subnet master". This is like
- * a slave except that it still has certain duties:
- *
- * o It relays net_joining messages to the master.
- *
- */
-
-
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/uio.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <sys/time.h>
- #ifdef XV
- #include <xview/notify.h>
- #else
- #include <sunwindow/notify.h>
- #endif XV
- #include <errno.h>
- #include <net/if.h>
- #include <sys/ioctl.h>
-
- #include "dstar.h"
- #include "netio.h"
-
-
-
- typedef int fd ;
-
- static FILE *iolog ;
-
-
- extern int debug_level ;
-
- static fd Socket ;
-
- static struct sockaddr_in Sock ;
-
- static struct sockaddr_in myaddr ;
-
- static char outbuf[MESSAGE_LENGTH] ;
- static char *Mastername ;
- static char *outptr ;
- static int outlen ;
- static struct sockaddr_in outaddress ;
-
- static Notify_value handle_message() ;
-
-
-
- /*
- * INTERNAL ROUTINES:
- *
- * report_problem - print object id, port & net address
- *
- * transmit(address, message, len)
- * - send an output packet
- *
- * broadcast(message, len)
- * - send packet to everybody
- *
- * net_flush() - deliver current message
- *
- * add_message(message, len)
- * - buffer up message
- *
- * request_rebroadcast(address, message,len)
- * - ask somebody to broadcast something
- *
- * rehash_netlists() - rebuild net lists if there's a change
- */
-
-
-
-
- static
- report_problem(id,addr)
- int id ;
- register struct sockaddr_in *addr ;
- {
- printf("sending to %d at %d, %d.%d.%d.%d\n", id, addr->sin_port,
- addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2,
- addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4) ;
- }
-
-
-
- dump_lists()
- {
- register Object *object = &objects[0] ;
- int i ;
- static char *classes[] = {"empty","static","player","missile"} ;
- static char *states[] = {"active","sleeping","dead"} ;
-
- fprintf(iolog, "object lists:\n") ;
- for(i = 0; i<MAX_PLAYERS; ++i )
- {
- if(object->class != OBJ_EMPTY)
- printf(" %2d: %-20.20s %-7.7s %-8.8s %-20.20s\n",
- i, object->name, classes[(int) object->class],
- states[(int) object->status],
- object->target != NULL ? object->target->name : "" ) ;
- ++object ;
- }
- }
-
-
-
-
-
- static
- request_rebroadcast(address, message,len)
- register struct sockaddr_in *address ;
- register char *message ;
- register int len ;
- {
- int iret ;
- struct msghdr msg_hdr ;
- struct iovec iovecs[2] ;
- Net_broadcast b_msg ;
-
- b_msg.type = NET_BROADCAST ;
- b_msg.len = sizeof(b_msg) + len ;
- b_msg.id = Me->id ;
- b_msg.sequence = ++sequence_number ;
-
- iovecs[0].iov_base = (char *) &b_msg ;
- iovecs[0].iov_len = sizeof(b_msg) ;
- iovecs[1].iov_base = message ;
- iovecs[1].iov_len = len ;
-
- msg_hdr.msg_name = (char *) address ;
- msg_hdr.msg_namelen = sizeof(struct sockaddr_in) ;
- msg_hdr.msg_iov = iovecs ;
- msg_hdr.msg_iovlen = 2 ;
- msg_hdr.msg_accrights = NULL ;
- msg_hdr.msg_accrightslen = 0 ;
-
- iret = sendmsg(Socket, &msg_hdr, 0) ;
- if(iret < 0)
- perror("dstard: sendto") ;
- }
-
-
-
- rebroadcast(header)
- Net_broadcast *header ;
- {
- Sock.sin_family = AF_INET ;
- Sock.sin_port = htons(DSTAR_PORT) ;
- Sock.sin_addr.s_addr = Me->net_addr ;
- transmit(&Sock, ((char *)header)+sizeof(Net_broadcast),
- header->len - sizeof(Net_broadcast)) ;
- }
-
-
-
-
-
-
-
-
- rehash_netlists()
- {
- register Object *object, *obj1 ;
- register Object *last_net, *last_subnet ;
- int i,j ;
- int count = 0 ;
-
- object = &objects[0] ;
- for(i = MAX_PLAYERS; i--; )
- {
- object->net_status = UNKNOWN ;
- object->next_net = NULL ;
- object->next_subnet = NULL ;
- ++object ;
- }
- master_id = -1 ;
-
- last_net = NULL ;
-
- poll_master = 0 ;
-
- object = &objects[0] ;
- for(i = 0; i<MAX_PLAYERS; ++i)
- {
- if( object->class == OBJ_PLAYER )
- {
- if( object == Me && count == 1 )
- poll_master = 1 ;
- else
- ++count ;
-
- if( object->net_status == UNKNOWN )
- {
- if( last_net == NULL )
- {
- object->net_status = MASTER ;
- master_id = object->id ;
- }
- else
- {
- object->net_status = SUBMASTER ;
- last_net->next_net = object ;
- }
- obj1 = last_subnet = last_net = object ;
- object->net_num = 0 ;
-
- ++obj1 ;
- for(j = i+1; j<MAX_PLAYERS; ++j)
- {
- if(obj1->class == OBJ_PLAYER &&
- obj1->net_addr == object->net_addr)
- {
- ++object->net_num ;
- last_subnet->next_subnet = obj1 ;
- obj1->net_status = SLAVE ;
- last_subnet = obj1 ;
- }
- ++obj1 ;
- }
- }
- }
- ++object ;
- }
-
- need_rehash = 0 ;
-
- #ifdef DEBUG
- if(debug_level >= 2)
- {
- fprintf(iolog,"new net lists:\n") ;
- object = &objects[master_id] ;
- for(object = &objects[master_id];
- object != NULL;
- object = object->next_net)
- {
- fprintf(iolog, " net %6.6lx\n",object->net_addr) ;
- for(obj1 = object; obj1 != NULL; obj1 = obj1->next_subnet)
- fprintf(iolog, " %2d: %s\n",obj1->id, obj1->name) ;
- }
- }
- #endif DEBUG
- }
-
-
-
-
- static
- transmit(address,message,len)
- register struct sockaddr_in *address ;
- register char *message ;
- register int len ;
- {
- register int iret ;
-
- iret = sendto(Socket, message, len, 0, address,
- sizeof(struct sockaddr_in)) ;
- if(iret < 0)
- perror("dstard: sendto") ;
- }
-
-
-
-
-
-
-
- /****
- * this function makes sure that the provided message gets to all the players
- * in the game. If there's less than a certain number of players
- * on each local net, the message is sent individually. If there's more
- * players than the threshold, the message is broadcast.
- ****/
-
- static
- broadcast(message,len)
- register char *message ;
- register int len ;
- {
- register int id ;
- register int i,j ;
- register Object *object = &objects[master_id] ;
- register Object *obj2 ;
-
-
- /* send to all other players, active or dead */
-
- if( need_rehash )
- rehash_netlists() ;
-
- if( master_id == -1 )
- return ;
-
-
- for( object = &objects[master_id];
- object != NULL;
- object = object->next_net )
- {
- if(object->net_num <= BROADCAST_THRESH)
- {
- for(obj2 = object; obj2 != NULL; obj2 = obj2->next_subnet)
- {
- #ifdef DEBUG
- if(obj2->class != OBJ_PLAYER)
- {
- fprintf(iolog,
- "%s got into netlists somehow\n",object->name) ;
- rehash_netlists() ;
- }
- #endif DEBUG
- if( obj2 != Me )
- transmit(&obj2->address, message, len) ;
- }
- }
- else if(object->net_addr == Me->net_addr)
- {
- bzero(&Sock, sizeof(Sock)) ;
- Sock.sin_family = AF_INET ;
- Sock.sin_port = htons(DSTAR_PORT) ;
- Sock.sin_addr.s_addr = object->net_addr ;
- transmit(&Sock, message, len) ;
- }
- else
- {
- request_rebroadcast(&object->address, message, len) ;
- }
- }
- }
-
-
-
-
- net_flush()
- {
- int iret ;
-
- #ifdef DEBUG
- if(Me->id == -1)
- {
- fprintf(iolog, "attempt to transmit while not in game\n") ;
- }
- #endif DEBUG
-
- if(outlen > 0)
- {
- if(Me->id != -1)
- if( outaddress.sin_addr.S_un.S_addr != 0 )
- transmit(&outaddress, outbuf, outlen) ;
- else
- broadcast(outbuf, outlen) ;
-
- outptr = &outbuf[0] ;
- outlen = 0 ;
- }
- }
-
-
-
-
- net_start_message(who)
- register Object *who ;
- {
- register u_long newaddr ;
-
- if( who == NULL )
- newaddr = 0 ;
- else
- newaddr = who->address.sin_addr.S_un.S_addr ;
-
- if( newaddr != outaddress.sin_addr.S_un.S_addr &&
- outlen > 0 )
- net_flush() ;
-
- if( who == NULL )
- outaddress.sin_addr.S_un.S_addr = 0 ;
- else
- outaddress = who->address ;
- }
-
-
-
-
- add_message(message, len)
- register Net_null *message ;
- register int len ;
- {
- int iret ;
-
- if(len + outlen > MESSAGE_LENGTH)
- net_flush() ;
-
- bcopy(message, outptr, len) ;
- outptr += len ;
- outlen += len ;
- }
-
-
-
-
-
-
-
-
- static
- join_game()
- {
- Net_joining outmsg ;
- struct hostent *host ;
- register Object *object = &objects[0] ;
- register int i ;
-
- for(i = MAX_PLAYERS; i--; )
- {
- if( object->class != OBJ_EMPTY && object != Me )
- {
- special_remove_player(object) ;
- object->class = OBJ_EMPTY ;
- }
- ++object ;
- }
-
- Me->id = -1 ;
- Me->target = NULL ;
- Me->net_status = UNKNOWN ;
-
-
-
-
- /* look for other people playing the game */
-
- outmsg.type = NET_JOINING ;
- outmsg.len = sizeof(Net_joining) ;
- outmsg.id = -1 ;
- outmsg.sequence = ++sequence_number ;
- strcpy(outmsg.name, Me->name) ;
- outmsg.class = Me->class ;
- outmsg.address = myaddr ;
-
- bzero(&Sock, sizeof(Sock)) ;
- Sock.sin_family = AF_INET ;
- Sock.sin_port = htons(DSTAR_PORT) ;
-
- if(Mastername == NULL) /* broadcast */
- {
- Sock.sin_addr.s_addr = Me->net_addr ;
- transmit(&Sock, &outmsg, sizeof(outmsg)) ;
- }
- else /* send direct to master */
- {
- host = gethostbyname(Mastername) ;
- Sock.sin_addr = *(struct in_addr *) host->h_addr ;
- request_rebroadcast(&Sock, &outmsg, sizeof(outmsg)) ;
- }
-
- #ifdef DEBUG
- if(debug_level >= 1)
- {
- fprintf(iolog, "join game: my name = %s\n",Me->name ) ;
- }
- #endif DEBUG
- }
-
-
-
-
-
-
-
-
-
- /* EXTERNAL ROUTINES:
- *
- * init_netio(username,mastername)
- * intialize communications. Called before notifier is started up.
- *
- * net_blow_away(weapon, object)
- * called when we've shot object
- *
- * send_status(obj, who)
- * send status to specific player
- *
- * send_status_all(obj)
- * send status to everybody
- *
- * net_remove_player(id)
- * remove player from game
- *
- * net_request_missile()
- * ask master for missile assignment
- *
- * net_poll()
- * called every 5 seconds to do bookkeeping
- */
-
-
-
-
- init_netio(username, mastername)
- char *username ;
- char *mastername ;
- {
- int iret, i ;
- int flags ;
- int nfds, mask, sockmask ;
- int done ;
- struct hostent *host ;
- struct timeval timeout ;
- struct sockaddr_in broadaddr ;
-
-
-
- #ifdef DEBUG
- if( status_display )
- putchar('\f') ;
- #endif DEBUG
-
-
-
- iolog = stderr ;
-
-
-
- /* create socket for i/o */
-
- Socket = socket(AF_INET, SOCK_DGRAM, 0) ;
- #ifdef COMMENT
- printf("socket done, fd=%d\n",Socket) ;
- #endif COMMENT
- if(Socket<0) {
- perror("Dstar: Init_netio") ;
- exit(1) ;
- }
-
-
- /* make it non-blocking */
-
- flags = fcntl(Socket, F_GETFL, 0) ;
- flags |= FNDELAY ;
- fcntl(Socket, F_SETFL, flags) ;
-
-
-
- /* give it a port & address */
-
- bzero(&Sock, sizeof(Sock)) ;
-
- Sock.sin_family = AF_INET ;
- Sock.sin_port = htons(DSTAR_PORT) ;
- Sock.sin_addr.s_addr = INADDR_ANY ;
-
- iret = bind(Socket, &Sock, sizeof(Sock)) ;
- #ifdef COMMENT
- printf("bind done, iret=%d\n",iret) ;
- #endif COMMENT
- if(iret) {
- perror("dstar: socket") ;
- exit(1) ;
- }
-
- sequence_number = 0 ;
-
-
-
- gethostname(Hostname, 64) ;
- #ifdef COMMENT
- printf("hostname = %s\n",Hostname) ;
- #endif COMMENT
-
- host = gethostbyname(Hostname) ;
- myaddr.sin_family = AF_INET ;
- myaddr.sin_port = htons(DSTAR_PORT) ;
- myaddr.sin_addr = *(struct in_addr *) host->h_addr ;
- #ifdef COMMENT
- printf("dstar net address is %d.%d.%d.%d\n",
- myaddr.sin_addr.S_un.S_un_b.s_b1, myaddr.sin_addr.S_un.S_un_b.s_b2,
- myaddr.sin_addr.S_un.S_un_b.s_b3, myaddr.sin_addr.S_un.S_un_b.s_b4) ;
- #endif COMMENT
-
-
-
- outptr = &outbuf[0] ;
- outlen = 0 ;
- outaddress.sin_addr.S_un.S_addr = 0 ;
-
-
- /* initialize the stuff that special_init didn't do */
-
- sprintf(Me->name, "%s@%s", username, Hostname) ;
- Me->address = myaddr ;
- Me->sequence = ++sequence_number ;
- Me->last_rep = Now ;
- #ifdef COMMENT
- Me->net_addr = myaddr.sin_addr.s_addr & 0xffffff00 ;
- #endif COMMENT
- getbroad(Socket, 1, &broadaddr) ;
- report_problem(0,&broadaddr) ;
- Me->net_addr = broadaddr.sin_addr.s_addr ;
-
- Mastername = mastername ;
-
- puts("checking network for other players...") ;
-
- join_game() ;
-
-
- /* set up to receive messages */
-
- (void) notify_set_input_func(&Socket, handle_message, Socket) ;
- }
-
-
-
-
-
-
-
-
- send_status(obj)
- register Object *obj ;
- {
- Net_current_status outmsg ;
- int iret ;
-
- outmsg.type = NET_CURRENT_STATUS ;
- outmsg.len = sizeof(Net_current_status) ;
- outmsg.id = Me->id ;
- outmsg.sequence = ++sequence_number ;
- outmsg.obj_id = obj->id ;
- bcopy(obj->name, outmsg.name, NAMELEN) ;
- outmsg.team = obj->team ;
- outmsg.score = obj->score ;
- outmsg.class = obj->class ;
- outmsg.status = obj->status ;
- outmsg.flags = obj->flags ;
- outmsg.Posn = obj->Posn ;
- outmsg.Forward = obj->Forward ;
- outmsg.Up = obj->Up ;
- outmsg.Right = obj->Right ;
- outmsg.Delta = obj->Delta ;
- outmsg.Pointing = obj->Pointing ;
- outmsg.Speed = obj->Speed ;
- outmsg.target = (obj->target != NULL) ? obj->target->id : -1 ;
- outmsg.description = obj->description ;
- outmsg.address = obj->address ;
- outmsg.net_addr = obj->net_addr ;
-
- add_message(&outmsg, sizeof(outmsg)) ;
-
- obj->last_rep = Now ;
- }
-
-
-
-
-
-
-
- net_remove_player(id)
- int id ;
- {
- Net_died died_msg ;
-
- net_start_message( NULL ) ;
- died_msg.type = NET_DIED ;
- died_msg.len = sizeof(Net_died) ;
- died_msg.id = Me->id ;
- died_msg.sequence = ++sequence_number ;
- died_msg.his_id = id ;
- add_message(&died_msg, sizeof(died_msg)) ;
-
- #ifdef DEBUG
- if(debug_level >= 1)
- fprintf(iolog, "net_remove_player: %2d: %s\n",
- id, objects[id].name ) ;
- #endif DEBUG
-
- remove_player(&died_msg) ;
-
- #ifdef DEBUG
- if(status_display)
- status_update() ;
- #endif DEBUG
- }
-
-
-
- net_blow_away(weapon, object)
- Object *weapon, *object ;
- {
- Net_just_scored outmsg ;
-
- net_start_message( NULL ) ;
- outmsg.type = NET_JUST_SCORED ;
- outmsg.len = sizeof(Net_just_scored) ;
- outmsg.id = Me->id ;
- outmsg.sequence = ++sequence_number ;
- outmsg.weapon_id = weapon->id ;
- outmsg.his_id = object->id ;
-
- add_message(&outmsg,sizeof(outmsg)) ;
-
- player_scored(&outmsg) ;
-
- #ifdef DEBUG
- if(debug_level >= 1)
- fprintf(iolog, "net_blow_away: %2d: %s with %s\n",
- object->id, object->name, weapon->name ) ;
- #endif DEBUG
- }
-
-
-
-
- net_request_missile()
- {
- Net_request_missile msg ;
-
- msg.type = NET_REQUEST_MISSILE ;
- msg.len = sizeof(Net_request_missile) ;
- msg.id = Me->id ;
- msg.sequence = ++sequence_number ;
- if(Me->net_status != MASTER)
- {
- net_start_message( &objects[master_id] ) ;
- add_message(&msg, sizeof(msg)) ;
- net_flush() ;
- }
- else
- new_missile(&msg) ;
- }
-
-
-
-
- net_rename(newid)
- int newid ;
- {
- Net_rename msg ;
-
- msg.type = NET_RENAME ;
- msg.len = sizeof(msg) ;
- msg.id = Me->id ;
- msg.sequence = ++sequence_number ;
- msg.new_id = newid ;
-
- net_start_message( NULL ) ;
- add_message(&msg, sizeof(msg) ) ;
-
- rename(&msg) ;
- }
-
-
-
-
-
-
-
-
-
- /*
- * INPUT MESSAGE HANDLING:
- *
- * add_new_player(...) - handle NET_JOINING
- *
- * welcome(hdr) - handle NET_WELCOME message
- *
- * reassure_master(header) - handle NET_ARE_YOU_THERE
- *
- * player_scored(header) - handle NET_JUST_SCORED
- *
- * new_status(header) - accept new status
- *
- * new_missile(header) - handle NET_REQUEST_MISSILE
- *
- * remove_player(header) - handle NET_DIED
- *
- */
-
-
-
-
-
-
-
-
-
- static
- welcome(header)
- register Net_welcome *header ;
- {
- register Object *object = &objects[0] ;
- int i ;
-
- for(i = MAX_PLAYERS; i--; )
- {
- if( object->class != OBJ_EMPTY && object != Me )
- {
- special_remove_player(object) ;
- object->class = OBJ_EMPTY ;
- }
- ++object ;
- }
-
-
-
- object = &objects[header->player_id] ;
-
- if(Me != object)
- {
- *object = *Me ;
- Me->class = OBJ_EMPTY ;
- Me = object ;
- }
-
- Me->id = header->player_id ;
- Me->team = header->team ;
- Me->target = NULL ;
- game_type = header->game_type ;
-
- special_welcome() ;
-
- #ifdef DEBUG
- if(status_display)
- status_update() ;
- if(debug_level >= 1)
- fprintf(iolog, "welcome: from %2d: %s\n", header->id,
- objects[header->id].name ) ;
- #endif DEBUG
-
- printf("my id = %d\n",Me->id) ;
- }
-
-
-
-
-
- static
- reassure_master(header)
- Net_are_you_there *header ;
- {
- int i ;
-
- #ifdef DEBUG
- printf("got a timeout message from %2d: %s\n",
- header->id, objects[header->id].name) ;
- #endif DEBUG
- net_start_message( &objects[header->id] ) ;
- send_status(Me) ;
- for(i=0; i<MAX_MISSILES; ++i)
- if(missiles[i] != NULL)
- send_status(missiles[i]) ;
- net_flush() ;
- }
-
-
-
-
-
- static
- player_scored(header)
- Net_just_scored *header ;
- {
- register Object *object = &objects[header->weapon_id] ;
- register Object *victim = &objects[header->his_id] ;
- register Object *killer = &objects[header->id] ;
-
- if( object->status != OBJ_ACTIVE )
- return ;
-
- if(victim == Me)
- printf("just got blown away by %s",killer->name) ;
- else if(killer == Me)
- printf("just blew away %s",victim->name) ;
- else
- printf("%s just got blown away by %s", victim->name, killer->name);
-
- if( object->class == OBJ_MISSILE )
- printf(" with a missile\n") ;
- else
- putchar('\n') ;
-
- if(victim->f_vector[F_KILLED] != NULL)
- (*victim->f_vector[F_KILLED])(object,victim,killer) ;
-
- if(killer->f_vector[F_SCORED] != NULL)
- (*killer->f_vector[F_SCORED])(object,victim,killer) ;
-
- #ifdef DEBUG
- if(status_display)
- status_update() ;
- #endif DEBUG
- }
-
-
-
-
- static
- accept_new_status(header)
- register Net_current_status *header ;
- {
- register Object *object = &objects[header->obj_id] ;
- extern fptr fighter_vector[VECTOR_LENGTH],
- missile_vector[VECTOR_LENGTH],
- static_vector[VECTOR_LENGTH] ;
-
-
- if(header->obj_id == Me->id)
- fprintf(iolog,
- "got a message about me from %s\n",objects[header->id].name) ;
-
-
- else if( Me->net_status == MASTER &&
- ( object->class == OBJ_EMPTY ||
- object->address.sin_addr.s_addr !=
- header->address.sin_addr.s_addr ) )
- {
- /* someone has put themselves into the game without
- sending a NET_JOINING MESSAGE. They probably timed
- out and didn't know they were killed. Send them
- a new NET_WELCOME message to re-sync them. */
-
- #ifdef DEBUG
- fprintf(iolog, "re-syncing %2d: %s\n",header->id, header->name) ;
- if(debug_level >= 1)
- if( object->class == OBJ_EMPTY )
- fprintf(iolog, "because slot is empty\n") ;
- else
- fprintf(iolog,
- "because message came from %s@%8.8lx, should have been %s@%8.8lx\n",
- header->name, header->address.sin_addr.s_addr,
- object->name, object->address.sin_addr.s_addr) ;
- #endif DEBUG
- add_new_player((object->class == OBJ_EMPTY) ? header->id : -1,
- header->name,
- &header->address,
- header->sequence,
- header->class ) ;
- #ifdef DEBUG
- if(debug_level >= 1)
- dump_lists() ;
- #endif DEBUG
- }
-
-
-
- else
- {
- if(object->class == OBJ_EMPTY)
- {
- object->id = header->obj_id ;
- bcopy(header->name, object->name, NAMELEN) ;
- object->team = header->team ;
- object->class = header->class ;
- object->status = header->status ;
- object->address = header->address ;
- object->net_addr = header->net_addr ;
- switch(header->class)
- {
- case OBJ_PLAYER:
- printf("new player: %d, %s\n",header->obj_id,header->name) ;
- bcopy(fighter_vector,object->f_vector,sizeof(fighter_vector)) ;
- break ;
- case OBJ_MISSILE:
- bcopy(missile_vector,object->f_vector,sizeof(missile_vector)) ;
- break ;
- case OBJ_STATIC:
- printf("new object: %d, %s\n",header->obj_id,header->name) ;
- bcopy(static_vector,object->f_vector,sizeof(static_vector)) ;
- break ;
- }
-
- if( object->class == OBJ_PLAYER )
- need_rehash = 1 ;
- special_add_player(object) ;
- #ifdef DEBUG
- if(debug_level >= 1)
- dump_lists() ;
- #endif DEBUG
- }
-
- (*object->f_vector[F_NEWSTAT])(object, header) ;
- }
- }
-
-
-
-
-
-
-
-
- new_status(object, header)
- register Object *object ;
- register Net_current_status *header ;
- {
- bcopy(header->name, object->name, NAMELEN) ;
- object->score = header->score ;
- object->status = header->status ;
- object->flags = header->flags ;
- object->Posn = header->Posn ;
- object->Forward = header->Forward ;
- object->Up = header->Up ;
- object->Right = header->Right ;
- object->Delta = header->Delta ;
- object->Pointing = header->Pointing ;
- object->Speed = header->Speed ;
- object->target =
- (header->target != -1) ? &objects[header->target] : NULL ;
- object->description = header->description ;
- object->last_rep = Now ;
- special_new_status(object) ;
- }
-
-
-
-
-
-
-
-
- static
- remove_player(header)
- Net_died *header ;
- {
- register Object *object = &objects[header->his_id] ;
- register Object *tmp ;
- int done ;
- int new_master ;
-
- if(header->his_id == Me->id && header->id != Me->id)
- {
- printf("Hey! %s just pronounced me dead\n",objects[header->id].name) ;
- join_game() ;
- return ;
- }
-
- if(object->class == OBJ_EMPTY)
- return ;
-
-
-
- if(header->id == header->his_id)
- printf("%s leaving game\n",object->name) ;
- else if (objects[header->his_id].class != OBJ_MISSILE)
- printf("%s removed by %s\n",object->name,objects[header->id].name) ;
-
- special_remove_player(object) ;
-
- object->class = OBJ_EMPTY ;
-
- need_rehash = 1 ;
-
- #ifdef DEBUG
- if(debug_level >= 1)
- dump_lists() ;
- #endif DEBUG
-
- if( header->his_id == master_id && poll_master )
- take_over() ;
-
- #ifdef DEBUG
- if(status_display)
- status_update() ;
- #endif DEBUG
- }
-
-
-
- static
- rename(header)
- Net_rename *header ;
- {
- register Object *oldobj = &objects[header->id] ;
- register Object *newobj = &objects[header->new_id] ;
-
- #ifdef DEBUG
- if(debug_level >= 1)
- fprintf(iolog,
- (newobj->class != OBJ_EMPTY) ?
- "error: %d: %s taking over non-empty slot %d\n" :
- "%d: %s taking over slot %d\n",
- header->id, oldobj->name, header->new_id) ;
- #endif DEBUG
-
- *newobj = *oldobj ;
- newobj->id = header->new_id ;
-
- oldobj->class = OBJ_EMPTY ;
-
- need_rehash = 1 ;
- }
-
-
-
- static Notify_value
- handle_message(me, fd)
- int *me ;
- int fd ;
- {
- struct sockaddr_in from ;
- int fromlen, msglen ;
- int iret ;
- char buf[MESSAGE_LENGTH] ;
- int done = 0 ;
- register char *ptr ;
- register Net_null *header ;
- extern fptr fighter_vector[VECTOR_LENGTH] ;
-
- #ifdef DEBUG
- if(me != &Socket)
- {
- fprintf(iolog,"? wrong value for handle in handle_message") ;
- return(NOTIFY_IGNORED) ;
- }
-
- if(fd != Socket)
- {
- fprintf(iolog,"? wrong value for fd in handle_message") ;
- return(NOTIFY_IGNORED) ;
- }
- #endif DEBUG
-
-
- while(!done)
- {
- fromlen = sizeof(from) ;
- msglen = recvfrom(Socket, buf, sizeof(buf), 0, &from, &fromlen) ;
- if(msglen<0)
- {
- done = 1 ;
- if(errno != EWOULDBLOCK)
- perror("dstar: recvfrom") ;
- }
- else
- {
- ptr = &buf[0] ;
- while(msglen > 0)
- {
- header = (Net_null *) ptr ;
-
- if(msglen < sizeof(Net_null) || msglen < header->len)
- {
- fprintf(iolog,
- "incomplete record in message, msglen=%d, len=%d\n",
- msglen, header->len) ;
- if(msglen < sizeof(Net_null))
- msglen = 0 ;
- }
- else if( header->id != Me->id ||
- from.sin_addr.s_addr != Me->address.sin_addr.s_addr)
- {
- if(header->id >= 0)
- {
- objects[header->id].sequence = header->sequence ;
- objects[header->id].last_rep = Now ;
- }
-
- switch(header->type)
- {
- default:
- printf("got an unknown header type: %d\n",
- (int) header->type) ;
- break ;
-
- case NET_NULL:
- puts("null") ;
- break ;
-
- case NET_JOINING:
- if(Me->net_status == UNKNOWN)
- become_master() ;
-
- if(Me->net_status == SUBMASTER)
- {
- net_start_message(&objects[master_id]) ;
- add_message(header, header->len) ;
- }
- else if(Me->net_status == MASTER)
- add_new_player( -1,
- ((Net_joining *)header)->name,
- &((Net_joining *)header)->address,
- ((Net_joining *)header)->sequence,
- ((Net_joining *)header)->class ) ;
- break ;
-
- case NET_WELCOME:
- if(Me->net_status == UNKNOWN)
- Me->net_status = SLAVE ;
- welcome(header) ;
- break ;
-
- case NET_ARE_YOU_THERE:
- reassure_master(header) ;
- break ;
-
- case NET_JUST_SCORED:
- if(Me->net_status != UNKNOWN)
- player_scored(header) ;
- break ;
-
- case NET_NEW_SCORES:
- puts("new scores") ;
- break ;
-
- case NET_CURRENT_STATUS:
- if(Me->net_status != UNKNOWN)
- accept_new_status(header) ;
- break ;
-
- case NET_REQUEST_MISSILE:
- if(Me->net_status != MASTER)
- puts("?request missile") ;
- else
- new_missile(header) ;
- break ;
-
- case NET_MISSILE:
- if(Me->net_status != UNKNOWN)
- missile_armed(((Net_missile *)header)->missile_id) ;
- #ifdef DEBUG
- if(status_display)
- status_update() ;
- #endif DEBUG
- break ;
-
- case NET_DIED:
- if(Me->net_status == UNKNOWN)
- join_game() ;
- else
- remove_player(header) ;
- break ;
-
- case NET_RENAME:
- rename(header) ;
- break ;
-
- case NET_BROADCAST:
- rebroadcast(header) ;
- break ;
- }
- }
-
- ptr += header->len ;
- msglen -= header->len ;
- }
- }
- }
-
- if( Me->id != -1 )
- net_flush() ;
-
- return(NOTIFY_DONE) ;
- }
-
-
-
-
-
-
- static int
- getbroad(fd, n, addrs)
- int fd, n ;
- struct sockaddr_in *addrs ;
- {
- int iret, i ;
- struct ifconf ifc ;
- u_char buffer[1024] ;
- struct sockaddr_in *sin ;
- int num_freq ;
- int nret = 0 ;
-
-
-
- /*
- * get list of interfaces
- */
-
- ifc.ifc_len = sizeof(buffer) ;
- ifc.ifc_buf = (caddr_t) buffer ;
-
- if( ioctl(fd, SIOCGIFCONF, &ifc) < 0)
- return -1 ;
-
-
- /*
- * for each interface...
- */
-
- num_freq = ifc.ifc_len/sizeof(struct ifreq) ;
-
- for(i=0; i<num_freq; ++i)
- {
- /*
- * copy the interface structure to a work area
- */
- sin = (struct sockaddr_in *) &ifc.ifc_req[i].ifr_addr ;
-
- if( ifc.ifc_req[i].ifr_addr.sa_family == AF_INET )
- {
- /*
- * get the flags
- */
- if( ioctl(fd, SIOCGIFFLAGS, &ifc.ifc_req[i]) >= 0)
- {
- /*
- * if it's an interface that supports broadcast...
- */
- if( (ifc.ifc_req[i].ifr_flags & IFF_BROADCAST) &&
- (ifc.ifc_req[i].ifr_flags & IFF_UP) )
- {
- /*
- * get the broadcast address
- */
- if( ioctl(fd, SIOCGIFBRDADDR, &ifc.ifc_req[i]) >= 0)
- {
- ++nret ;
- *addrs++ = *sin ;
- }
- }
- }
- }
- }
- return nret ;
- }
-
-
-
-
- #ifdef DEBUG
-
- status_update()
- {
- register int i ;
- register Object *object = &objects[0] ;
- static char *classes[] = {"empty","static","player","missile"} ;
- static char *states[] = {"active","sleeping","dead"} ;
-
- printf("\033[3;1H \n\n\n") ;
- for(i = 0; i<MAX_PLAYERS; ++i)
- {
- int i2 = i ; Object *obj2 = object ;
- if(object->class != OBJ_EMPTY)
- printf(" %2d: %-20.20s %-7.7s %-8.8s %-20.20s %4d\033[K\n",
- i, object->name, classes[(int) object->class],
- states[(int) object->status],
- object->target != NULL ? object->target->name : "",
- Now.tv_sec - object->last_rep.tv_sec ) ;
- else
- printf("\033[K\n") ;
- ++object ;
- }
- printf("\n\n\n") ;
- }
-
-
- #endif DEBUG
-