home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume34 / fsp / part01 / server_lib.c < prev   
Encoding:
C/C++ Source or Header  |  1992-12-18  |  6.2 KB  |  228 lines

  1.     /*********************************************************************\
  2.     *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  3.     *                                                                     *
  4.     *  You may copy or modify this file in any manner you wish, provided  *
  5.     *  that this notice is always included, and that you hold the author  *
  6.     *  harmless for any loss or damage resulting from the installation or *
  7.     *  use of this software.                                              *
  8.     \*********************************************************************/
  9.  
  10. #include "server_def.h"
  11.  
  12. extern int errno;
  13.  
  14. static int myport = 0;
  15. static int myfd;
  16. static int interrupted = 0;
  17.  
  18. void server_interrupt()
  19. {
  20.     interrupted = 1;
  21.     signal(SIGALRM,server_interrupt);
  22. }
  23.  
  24. /****************************************************************************
  25. *  This is the message filter.  It is called by main with a timeout value.
  26. *  If timeout is -1, it will never time out.  Otherwise, it waits for a
  27. *  message.  If timed out, it returns.  Otherwise it pass it through checks.
  28. *  Those message that passed get sent to the dispatch loop.
  29. ****************************************************************************/
  30.  
  31. server_loop(timeout)
  32.     unsigned long timeout;
  33. {
  34.     unsigned long cur_time;
  35.     HTAB *hp;
  36.     UBUF rbuf;
  37.     struct sockaddr_in from;
  38.     unsigned u, sum, mask;
  39.     int retval, bytes, old;
  40.     unsigned char *s, *d, *t;
  41.  
  42.     while(1)
  43.     {
  44.     mask = 1 << myfd;
  45.     if(interrupted) { dump_htab(); interrupted = 0; }
  46.     retval = _x_select(&mask, timeout);
  47.  
  48.     if(retval == -1) { if(errno == EINTR) continue;
  49.                perror("select"); exit(1); }
  50.  
  51.     if(retval == 1)    /* an incoming message is waiting */
  52.     {
  53.         bytes = sizeof(from);
  54.         if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0,
  55.                     &from,&bytes)) < UBUF_HSIZE) continue;
  56.  
  57.         rbuf.len = ntohs(rbuf.len);
  58.         if(rbuf.len+UBUF_HSIZE > bytes) continue;    /* truncated.  */
  59.  
  60.         if(!(hp = find_host(from.sin_addr.s_addr)))
  61.             { fputs("find host failed\n",stderr); exit(0); }
  62.  
  63.         if(hp->inhibit) continue;
  64.  
  65.         old = 0;
  66.         cur_time = time((time_t *) 0);
  67.  
  68.         if(hp->next_key != rbuf.key)
  69.         {
  70.         if(!hp->active)
  71.         {
  72.             hp->last_key = hp->next_key = rbuf.key;
  73.  
  74.         } else
  75.         {
  76.             if(hp->last_key == rbuf.key)
  77.             {
  78.             if(cur_time < hp->last_acc + 3) continue;
  79.             old = 1;
  80.  
  81.             } else
  82.             {
  83.             if(cur_time < hp->last_acc + 60) continue;
  84.             }
  85.         }
  86.         }
  87.  
  88.         hp->active   =        1;
  89.         hp->last_acc = cur_time;
  90.  
  91.         s = (unsigned char *) &rbuf;
  92.         d = s + bytes;
  93.         u = rbuf.sum; rbuf.sum = 0;
  94.         for(t = s, sum = bytes; t < d; sum += *t++);
  95.         sum = (sum + (sum >> 8)) & 0xff;
  96.         if(sum != u) continue;            /* wrong check sum */
  97.  
  98.         rbuf.pos = ntohl(rbuf.pos);
  99.         server_get_packet(bytes,&rbuf,old,hp,&from);
  100.  
  101.     } else return(0);                /* got a timeout */
  102.     }
  103. }
  104.  
  105. /****************************************************************************
  106. * Routine to return a 16-bit key with random number in the first 8-bits and
  107. * zero in the second 8-bits.
  108. ****************************************************************************/
  109.  
  110. get_next_key()
  111. {
  112.     unsigned long k;
  113.  
  114.     k = random();
  115.     k = k ^ (k >> 8) ^ (k >> 16) ^ (k << 8);
  116.  
  117.     return(k & 0xff00);
  118. }
  119.  
  120. /****************************************************************************
  121. * Generic routine for sending reply back to clients.
  122. *        from: client address structure.
  123. *          ub: pointer to the message buffer.
  124. *  len1, len2: lengths of the two data regions in the message buffer.
  125. ****************************************************************************/
  126.  
  127. server_reply(from,ub,len1,len2)
  128.     struct sockaddr_in *from;
  129.     UBUF *ub;
  130.     int   len1, len2;
  131. {
  132.     unsigned char *s, *t, *d;
  133.     unsigned sum;
  134.  
  135.     if(dbug) fprintf(stderr,"snd (%c,%d,%d,%lu) ---> %d.%d.%d.%d\n",
  136.                 ub->cmd, len1, len2, ub->pos,
  137.                 ((unsigned char *)(&(from->sin_addr.s_addr)))[0],
  138.                 ((unsigned char *)(&(from->sin_addr.s_addr)))[1],
  139.                 ((unsigned char *)(&(from->sin_addr.s_addr)))[2],
  140.                 ((unsigned char *)(&(from->sin_addr.s_addr)))[3]);
  141.  
  142.     ub->len = htons(len1);
  143.     ub->pos = htonl(ub->pos);
  144.  
  145.     ub->sum = 0;
  146.     s = (unsigned char *) ub;
  147.     d = s + (len1 + len2 + UBUF_HSIZE);
  148.     for(t = s, sum = 0; t < d; sum += *t++);
  149.     ub->sum = sum + (sum >> 8);
  150.  
  151.     if(sendto(myfd,(char *)ub,(len1 + len2 + UBUF_HSIZE),0,
  152.             from,sizeof(struct sockaddr_in)) == -1)
  153.                         { perror("sendto"); exit(1); }
  154. }
  155.  
  156. /****************************************************************************
  157. * Send an error string.
  158. ****************************************************************************/
  159.  
  160. send_error(from,ub,msg)
  161.     struct sockaddr_in *from;
  162.     UBUF *ub;
  163.     char *msg;
  164. {
  165.     char *d;
  166.  
  167.     for(d = ub->buf; *d++ = *msg++; );
  168.     ub->cmd = CC_ERR;
  169.  
  170.     server_reply(from,ub,d-ub->buf,0);
  171. }
  172.  
  173. /****************************************************************************
  174. * Send a block of data read from the file 'fp'.  Offset information is
  175. * contained in the input ub message buffer, which also doubles as the output
  176. * message buffer.
  177. ****************************************************************************/
  178.  
  179. send_file(from,ub,fp,has_len,lp)
  180.     struct sockaddr_in *from;
  181.     UBUF *ub;
  182.     FILE *fp;
  183.     int has_len;
  184.     char *lp;
  185. {
  186.     int bytes, len;
  187.  
  188.     if(has_len == 2)    /* recover length field if it exists */
  189.     {
  190.     len  = ((unsigned char *) lp)[0]; len <<= 8;
  191.     len += ((unsigned char *) lp)[1];
  192.     if(len > UBUF_SPACE || len < 0) len = UBUF_SPACE;
  193.  
  194.     } else { len  = UBUF_SPACE; }    /* use default if it doesn't exist */
  195.  
  196.     fseek(fp,ub->pos,0);
  197.     bytes = fread(ub->buf, 1, len, fp);
  198.     server_reply(from,ub,bytes,0);
  199. }
  200.  
  201. /****************************************************************************
  202. * The two UDP socket initialization routines.  One for running alone.
  203. * The other for running under inetd.
  204. ****************************************************************************/
  205.  
  206. init_network(port)
  207.     int port;
  208. {
  209.     myport = port;
  210.  
  211.     if((myfd = _x_udp(&myport)) == -1) { perror("socket open"); exit(1); }
  212.  
  213.     if(dbug)
  214.     {
  215.     fprintf(stderr,"listening on port %d\n",myport);
  216.     fflush(stderr);
  217.     }
  218.  
  219.     signal(SIGALRM,server_interrupt);
  220. }
  221.  
  222. init_inetd()
  223. {
  224.     myfd = dup(0);
  225.  
  226.     signal(SIGALRM,server_interrupt);
  227. }
  228.