home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************\
- * Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) *
- * *
- * You may copy or modify this file in any manner you wish, provided *
- * that this notice is always included, and that you hold the author *
- * harmless for any loss or damage resulting from the installation or *
- * use of this software. *
- \*********************************************************************/
-
- #include "server_def.h"
-
- extern int errno;
-
- static int myport = 0;
- static int myfd;
- static int interrupted = 0;
-
- void server_interrupt()
- {
- interrupted = 1;
- signal(SIGALRM,server_interrupt);
- }
-
- /****************************************************************************
- * This is the message filter. It is called by main with a timeout value.
- * If timeout is -1, it will never time out. Otherwise, it waits for a
- * message. If timed out, it returns. Otherwise it pass it through checks.
- * Those message that passed get sent to the dispatch loop.
- ****************************************************************************/
-
- server_loop(timeout)
- unsigned long timeout;
- {
- unsigned long cur_time;
- HTAB *hp;
- UBUF rbuf;
- struct sockaddr_in from;
- unsigned u, sum, mask;
- int retval, bytes, old;
- unsigned char *s, *d, *t;
-
- while(1)
- {
- mask = 1 << myfd;
- if(interrupted) { dump_htab(); interrupted = 0; }
- retval = _x_select(&mask, timeout);
-
- if(retval == -1) { if(errno == EINTR) continue;
- perror("select"); exit(1); }
-
- if(retval == 1) /* an incoming message is waiting */
- {
- bytes = sizeof(from);
- if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0,
- &from,&bytes)) < UBUF_HSIZE) continue;
-
- rbuf.len = ntohs(rbuf.len);
- if(rbuf.len+UBUF_HSIZE > bytes) continue; /* truncated. */
-
- if(!(hp = find_host(from.sin_addr.s_addr)))
- { fputs("find host failed\n",stderr); exit(0); }
-
- if(hp->inhibit) continue;
-
- old = 0;
- cur_time = time((time_t *) 0);
-
- if(hp->next_key != rbuf.key)
- {
- if(!hp->active)
- {
- hp->last_key = hp->next_key = rbuf.key;
-
- } else
- {
- if(hp->last_key == rbuf.key)
- {
- if(cur_time < hp->last_acc + 3) continue;
- old = 1;
-
- } else
- {
- if(cur_time < hp->last_acc + 60) continue;
- }
- }
- }
-
- hp->active = 1;
- hp->last_acc = cur_time;
-
- s = (unsigned char *) &rbuf;
- d = s + bytes;
- u = rbuf.sum; rbuf.sum = 0;
- for(t = s, sum = bytes; t < d; sum += *t++);
- sum = (sum + (sum >> 8)) & 0xff;
- if(sum != u) continue; /* wrong check sum */
-
- rbuf.pos = ntohl(rbuf.pos);
- server_get_packet(bytes,&rbuf,old,hp,&from);
-
- } else return(0); /* got a timeout */
- }
- }
-
- /****************************************************************************
- * Routine to return a 16-bit key with random number in the first 8-bits and
- * zero in the second 8-bits.
- ****************************************************************************/
-
- get_next_key()
- {
- unsigned long k;
-
- k = random();
- k = k ^ (k >> 8) ^ (k >> 16) ^ (k << 8);
-
- return(k & 0xff00);
- }
-
- /****************************************************************************
- * Generic routine for sending reply back to clients.
- * from: client address structure.
- * ub: pointer to the message buffer.
- * len1, len2: lengths of the two data regions in the message buffer.
- ****************************************************************************/
-
- server_reply(from,ub,len1,len2)
- struct sockaddr_in *from;
- UBUF *ub;
- int len1, len2;
- {
- unsigned char *s, *t, *d;
- unsigned sum;
-
- if(dbug) fprintf(stderr,"snd (%c,%d,%d,%lu) ---> %d.%d.%d.%d\n",
- ub->cmd, len1, len2, ub->pos,
- ((unsigned char *)(&(from->sin_addr.s_addr)))[0],
- ((unsigned char *)(&(from->sin_addr.s_addr)))[1],
- ((unsigned char *)(&(from->sin_addr.s_addr)))[2],
- ((unsigned char *)(&(from->sin_addr.s_addr)))[3]);
-
- ub->len = htons(len1);
- ub->pos = htonl(ub->pos);
-
- ub->sum = 0;
- s = (unsigned char *) ub;
- d = s + (len1 + len2 + UBUF_HSIZE);
- for(t = s, sum = 0; t < d; sum += *t++);
- ub->sum = sum + (sum >> 8);
-
- if(sendto(myfd,(char *)ub,(len1 + len2 + UBUF_HSIZE),0,
- from,sizeof(struct sockaddr_in)) == -1)
- { perror("sendto"); exit(1); }
- }
-
- /****************************************************************************
- * Send an error string.
- ****************************************************************************/
-
- send_error(from,ub,msg)
- struct sockaddr_in *from;
- UBUF *ub;
- char *msg;
- {
- char *d;
-
- for(d = ub->buf; *d++ = *msg++; );
- ub->cmd = CC_ERR;
-
- server_reply(from,ub,d-ub->buf,0);
- }
-
- /****************************************************************************
- * Send a block of data read from the file 'fp'. Offset information is
- * contained in the input ub message buffer, which also doubles as the output
- * message buffer.
- ****************************************************************************/
-
- send_file(from,ub,fp,has_len,lp)
- struct sockaddr_in *from;
- UBUF *ub;
- FILE *fp;
- int has_len;
- char *lp;
- {
- int bytes, len;
-
- if(has_len == 2) /* recover length field if it exists */
- {
- len = ((unsigned char *) lp)[0]; len <<= 8;
- len += ((unsigned char *) lp)[1];
- if(len > UBUF_SPACE || len < 0) len = UBUF_SPACE;
-
- } else { len = UBUF_SPACE; } /* use default if it doesn't exist */
-
- fseek(fp,ub->pos,0);
- bytes = fread(ub->buf, 1, len, fp);
- server_reply(from,ub,bytes,0);
- }
-
- /****************************************************************************
- * The two UDP socket initialization routines. One for running alone.
- * The other for running under inetd.
- ****************************************************************************/
-
- init_network(port)
- int port;
- {
- myport = port;
-
- if((myfd = _x_udp(&myport)) == -1) { perror("socket open"); exit(1); }
-
- if(dbug)
- {
- fprintf(stderr,"listening on port %d\n",myport);
- fflush(stderr);
- }
-
- signal(SIGALRM,server_interrupt);
- }
-
- init_inetd()
- {
- myfd = dup(0);
-
- signal(SIGALRM,server_interrupt);
- }
-