home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume11 / bt / part02 / interface.c next >
C/C++ Source or Header  |  1990-12-11  |  9KB  |  419 lines

  1.  
  2. /* interface.c: Socket communications support& medium- level message
  3.  * passing functions. Copyright (C) 1990 Tom Boutell on original portions.
  4.  * All low- level socket code drawn with appreciation from:
  5.  * SOCK.C
  6.  * Copyright (C)1989 Dr Evil Laboratories
  7.  * This code written by Ray Moody, Roy Riggs, Mitch Adler,
  8.  * Bill Burdick, and Steven Grady
  9.  * No one makes any guarantees about anything.  This file maybe 
  10.  * freely distributed and modified as long as this header remains intact.  
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <sys/types.h>
  15. #include <sys/time.h>
  16. #include <sys/socket.h>
  17. #include <netinet/in.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <signal.h>
  21. #include <netdb.h>
  22. #include <varargs.h>
  23.  
  24. #include "types.h"
  25. #include "pack.h"
  26. #include "bt.h"
  27. #include "interface.h"
  28.  
  29. #define DEBUG
  30. #undef DEBUG
  31. #ifdef DEBUG
  32. #define debug printf
  33. #else
  34. #define debug 0+
  35. #define perror 0+
  36. #endif
  37.  
  38. #define SECONDSLIMIT 0L
  39. #define MICROSECONDSLIMIT 1L
  40.  
  41. #define LINE_LEN 1024
  42. #define LOST_CARRIER_MSG "F"
  43.  
  44. #define NONE (fd_set *) NULL
  45. #define NEVER (struct timeval *) NULL
  46. #define IGNORE (struct sockaddr *) NULL
  47.  
  48. fd_set active;
  49. struct sockaddr_in sc_in;
  50. int s;
  51. char cur_input[LINE_LEN];
  52. char *curhostname = "";
  53. int playerids[20];
  54. char outputline[256];
  55. void setupinterface() {
  56.   int current;
  57.   init_socket(2727);
  58.   playertext=(outputline+1);
  59.   for (current=1; (current<=totalplayers); current++) {
  60.     playerids[current]=new_player(0);
  61.     players[current].live=1;
  62.     printf("Player %d has joined.\n",current);
  63.     outputline[0]=_YOUARE;
  64.     outputline[1]=64+current;
  65.     outputline[2]=0;
  66.     w_p(playerids[current],outputline,strlen(&outputline[0])+1);
  67.     }
  68.  
  69. void tellplayer(player)
  70.   int player;
  71. {
  72.   outputline[0]=_TEXT;
  73.   w_p(playerids[player],outputline,strlen(&outputline[0])+1);
  74.  
  75. void broadcast(messagetype,details)
  76.   char messagetype;
  77.   void* details;
  78. {
  79.   location where;
  80.   int thisplayer;
  81.   int current;
  82.   outputline[0]=messagetype;
  83.   switch (messagetype) {
  84.    
  85.     case _HEXSTATUS:
  86.       where=*(location*)details;
  87.       outputline[1]=64+where.x;
  88.       outputline[2]=64+where.y;
  89.       outputline[3]=64+map[where.x][where.y].terrain;
  90.       packint(4,map[where.x][where.y].population);
  91.       packint(7,map[where.x][where.y].lastuse);
  92.       packint(10,map[where.x][where.y].troops);
  93.       outputline[13]=map[where.x][where.y].owner+64;
  94.       outputline[14]=NULL;
  95.       break;
  96.     case _PLAYERSTATUS:
  97.       thisplayer=*(int*)details;
  98.       outputline[1]=thisplayer+64;
  99.       packint(2,players[thisplayer].action);
  100.       packint(5,players[thisplayer].hexes);
  101.       packint(8,players[thisplayer].troops);
  102.       packint(11,players[thisplayer].population);
  103.       packint(14,players[thisplayer].citadels);
  104.       outputline[17]=players[thisplayer].start.x+64;
  105.       outputline[18]=players[thisplayer].start.y+64;
  106.       outputline[19]=NULL;
  107.       break;
  108.     case _PLAYERDEAD:
  109.       thisplayer=*(int*)details;
  110.       outputline[1]=thisplayer+64;
  111.       outputline[2]=NULL;
  112.       break;
  113.     case _ACTION:
  114.       outputline[1]=NULL;    
  115.       break;
  116.     case _STARTUP:
  117.       outputline[1]=totalplayers+64;
  118.       outputline[2]=NULL;
  119.       break;
  120.     case _TEXT:
  121.       strcpy(&outputline[1],(char*) details);
  122.       break;
  123.     case _END:
  124.       outputline[1]=NULL;
  125.   }
  126.   for (current=0; (current<=totalplayers); current++) {
  127.     if (outputline[0]==_END) {
  128.     }
  129.     if (players[current].live) {
  130.       w_p(playerids[current],outputline,strlen(outputline)+1); 
  131.     }   
  132.   }
  133. }    
  134.  
  135. int getrequest(thisplayer,requesttype,specific)
  136.   int* thisplayer;
  137.   char* requesttype;
  138.   char* specific;
  139. {
  140.   char* received;
  141.   static int sweep;
  142.   int oldsweep;
  143.   sweep++;
  144.   if ((sweep>totalplayers) || (sweep<=0))
  145.     sweep=1;
  146.   oldsweep=sweep;
  147.   while (players[sweep].live==0) {
  148.     sweep++;
  149.     if (sweep>totalplayers)
  150.       sweep=1;
  151.     if (sweep==oldsweep)
  152.       return 0;
  153.   }
  154.   received=read_player(playerids[sweep]);
  155.   *thisplayer=sweep;
  156.   if (*received==NULL)
  157.     return 0;
  158.   *requesttype=received[0];
  159.   strcpy(specific,(received+=1));
  160.   return 1;
  161.   }           
  162.  
  163.  
  164. void shutdowninterface() {
  165.   disconnect_all();
  166. }
  167.   
  168.  
  169. /* - PD Socket code begins here.
  170.  * init_socket() - intialize our socket, port is the port number to use
  171.  *                 call this once at the beginning of your code
  172.  */
  173.  
  174. int init_socket(port)
  175.     int port;
  176. {
  177.     setbuf(stdout, (char *)0);
  178.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  179.         perror("socket");
  180.         return 0;
  181.     }
  182.     sc_in.sin_family = AF_INET;
  183.     sc_in.sin_addr.s_addr = INADDR_ANY;
  184.     sc_in.sin_port = htons((u_short) port);
  185.     if (bind(s, (struct sockaddr *) &sc_in, sizeof(sc_in)) < 0) {
  186.         perror("bind");
  187.         return 0;
  188.     }
  189.     if (listen(s, 5) < 0) {
  190.         perror("listen");
  191.         return 0;
  192.     }
  193.  
  194.     FD_ZERO(&active);
  195.  
  196.     return 1;
  197. }
  198.  
  199.  
  200. /*
  201.  * disconnect_all() - throws everyone off
  202.  */
  203.  
  204. int disconnect_all()
  205. {
  206.     register int i;
  207.     
  208.     for (i = 0; i < FD_SETSIZE; i++) {
  209.         if (FD_ISSET(i, &active))
  210.             (void) disconnect(i);
  211.     }
  212.     return 1;
  213. }
  214.  
  215.  
  216. /*
  217.  * shut-down -- kills all connections and exits the pgm
  218.  */
  219.  
  220. int shut_down()
  221. {
  222.     (void) disconnect_all();
  223.     exit(0);
  224. }
  225.  
  226.  
  227. /* hostfrom() - returns a string containing an ascii name for the host
  228.  *              that the passed socket s is connected to.  Note that the
  229.  *              string is in static space.  If you want to munge with it,
  230.  *              make a copy.
  231.  */
  232.  
  233. char *hostfrom(i)
  234.     int i;
  235. {
  236.     struct sockaddr_in from;
  237.     int fromlen = sizeof(from);
  238.     struct hostent *host;
  239.     struct in_addr addr;
  240.  
  241.     if (getpeername(i, &from, &fromlen) < 0) {
  242.         perror("getpeername");
  243.         return NULL;
  244.     }
  245.     
  246.     addr = from.sin_addr;
  247.     if ((host = gethostbyaddr(&addr, sizeof(addr), AF_INET)) == NULL) {
  248.         debug("gethostbyaddr failed");
  249.         return NULL;
  250.     }
  251.         
  252.     return curhostname = host->h_name;
  253. }
  254.  
  255.  
  256. /*
  257.  * hostname() - returns curhostname
  258.  */
  259.  
  260. char *hostname()
  261. {
  262.     return curhostname;
  263. }
  264.  
  265.  
  266. /*
  267.  * new_player() - call this routine in your main loop to allow new
  268.  *                players to join.  returns a playerId or -1 if no one
  269.  *                wants to join.
  270.  *                if wait == 0, then put your process to sleep until
  271.  *                someone new tries to connect.
  272.  */
  273.  
  274. int new_player(wait)
  275.     int wait;   /* 0 - wait for activity, else don't wait */
  276. {
  277.     fd_set readfds;
  278.     int j;
  279.     struct timeval *pWaitTime, waitTime;
  280.  
  281.     pWaitTime = &waitTime;
  282.     
  283.     if (0 == wait) {
  284.         pWaitTime = NEVER;
  285.     } else {
  286.         pWaitTime->tv_sec = SECONDSLIMIT;
  287.         pWaitTime->tv_usec = MICROSECONDSLIMIT;
  288.     }
  289.  
  290.     bcopy((char *) &active, (char *) &readfds, sizeof(active));
  291.  
  292.     FD_SET(s, &readfds);
  293.  
  294.     if (select(FD_SETSIZE, &readfds, NONE, NONE, pWaitTime) < 0) {
  295.         perror("select");
  296.         return -1;
  297.     }
  298.     if (FD_ISSET(s, &readfds)) {
  299.         if ((j = accept(s, IGNORE, (int *) 0)) < 0) {
  300.             return -1;
  301.         }
  302.         FD_SET(j, &active);
  303.         curhostname = hostfrom(j);
  304.         debug("Test Host=%s\n", curhostname);
  305.         return j;
  306.     } else {
  307.         return -1;
  308.     }
  309. }
  310.  
  311.  
  312. /*
  313.  * disconnect() - drop the player with the given id
  314.  */
  315.  
  316. int disconnect(id)
  317.     int id;
  318. {
  319.     if (FD_ISSET(id, &active)) {
  320.         debug("** Just dropped %d\n", id);
  321.         FD_CLR(id, &active);
  322.         if (close(id) < 0) {
  323.             perror("close");
  324.             return 0;
  325.         }
  326.     } else {
  327.         debug("** Just tried to drop someone not connected\n");
  328.         return 0;
  329.     }
  330.     return 1;
  331. }
  332.  
  333.  
  334. /*
  335.  * read_player() - This routine returns the next string from the player
  336.  *                 connected to descriptor playerFd. If there is no
  337.  *                 input it returns the empty string. If the connection
  338.  *                 is lost the string LOST_CARRIER_MSG is returned.
  339.  *                 NOTE: control characters are replaced by spaces
  340.  *                       and it is null terminated at the first nl/cr
  341.  */
  342.  
  343. char *read_player(playerFd)
  344.     int playerFd;
  345. {
  346.     fd_set readfds;
  347.     struct timeval waitTime;
  348.     
  349.     waitTime.tv_sec = SECONDSLIMIT;
  350.     waitTime.tv_usec = MICROSECONDSLIMIT;
  351.  
  352.     bcopy((char *) &active, (char *) &readfds, sizeof(active));
  353.  
  354.     if (select(FD_SETSIZE, &readfds, NONE, NONE, &waitTime) < 0) {
  355.         perror("select");
  356.         return("");
  357.     }
  358.  
  359.     if (FD_ISSET(playerFd, &readfds)) {
  360.         int nbytes, i;
  361.         
  362.         nbytes = read(playerFd, cur_input, LINE_LEN);
  363.         if (nbytes < 0) {
  364.             perror("read");
  365.             disconnect(playerFd);
  366.             return(LOST_CARRIER_MSG);
  367.         } else if (nbytes == 0) {
  368.             disconnect(playerFd);
  369.             return(LOST_CARRIER_MSG);
  370.         } else {
  371. /* Don't need control editing    for(i=0; i<nbytes; ++i) {
  372.                 if (iscntrl(cur_input[i])) {
  373.                     if (cur_input[i]=='\n' ||
  374.                         cur_input[i]=='\r')
  375.                         cur_input[i] = '\n';
  376.                     else
  377.                         cur_input[i] = ' ';
  378.                 }
  379.             }
  380. */
  381.             if (nbytes != LINE_LEN) {
  382.                 cur_input[nbytes] = '\0';
  383.             } else {
  384.                 cur_input[LINE_LEN - 1] = '\0';
  385.             }
  386.  
  387.             return((char *) cur_input);
  388.         }
  389.     }
  390.     return("");
  391. }
  392.  
  393.  
  394. /*
  395.  * write_player() - write to id, a string with the given length
  396.  */
  397.  
  398. int w_p(id, str, len)
  399.     int id, len;
  400.     char *str;
  401. {
  402.     if (id > -1) {
  403.         if (!FD_ISSET(id, &active)) {
  404.             debug("** Tried to write to closed id #%d.\n", id);
  405.             return 0;
  406.         } else if (write(id, str, len) < 0) {
  407.             perror("Write");
  408.             return 0;
  409.         }
  410.     }
  411.     return 1;
  412. }
  413.  
  414.  
  415.  
  416.  
  417.