/* * listen.c Copyright 1999 Christopher M Sedore. All Rights Reserved. * Please see the "COPYING" file for license details. * * Unfortunately, this is a bit of a mish-mash. It contains routines to * asynchronously listen on a socket, accept a connection, and connect. * It also contains the signal handling code. */ #include "main.h" extern volatile int timerCallback; static int curConnected=0,maxConnections=512; int lsock=-1; int mypid; void my_accept(struct myaiocb *,int); int my_listen(int port) { int s; struct sockaddr_in sa; int val=1; struct myaiocb *cb; signal_setup(); s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&val,4); bzero(&sa,sizeof(struct sockaddr_in)); sa.sin_port=htons(port); bind(s,(struct sockaddr *)&sa,sizeof(sa)); listen(s,128); if (ioctl(s,FIOASYNC,&val)) { perror("ioctl"); } if (ioctl(s,FIONBIO,&val)) { perror("ioctl"); } lsock=s; cb=(struct myaiocb *) malloc(sizeof(struct myaiocb)); bzero(cb,sizeof(struct myaiocb)); cb->cb.aio_fildes=s; cb->cb.aio_buf=&cb->cb.aio_offset; cb->cb.aio_nbytes=2; cb->callback=(void *)my_accept; if (aio_read((struct aiocb *)cb)<0) { perror("listensock"); } return s; } void setsocktimeouts(int s) { struct timeval tv; tv.tv_sec=60; tv.tv_usec=0; if (setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(struct timeval)) || setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(struct timeval))) perror("socktimeouts"); } void my_accept(struct myaiocb *cb,int unused) { struct sockaddr_in sa; int l,s; struct context *cc; int val=1; struct incoming_entry *ie; char buf[80]; l=sizeof(sa); if ((s=accept(lsock,(struct sockaddr *)&sa,&l))<0) { perror("accept"); return; } setsockopt(s,SOL_SOCKET,TCP_NODELAY,&val,4); val=0; setsockopt(s,SOL_SOCKET,SO_LINGER,&val,4); setsocktimeouts(s); if (ioctl(s,FIONBIO,&val)) { perror("ioctl"); } if ((ie=IncomingCheck(sa.sin_addr.s_addr))==NULL) { sprintf(buf,"502 %s - %s\r\n", GetConfigString("ReportedHostname"), GetConfigString("DenyBanner")); write(s,buf,strlen(buf)); close(s); aio_read((struct aiocb *)cb); return; } /* if (ie->connected+1>ie->maxConnections) { sprintf(buf,"400 %s - Only allowed %i concurrent connections\r\n", GetConfigString("ReportedHostName"), ie->maxConnections); write(s,buf,strlen(buf)); close(s); aio_read((struct aiocb *)cb); return; } if (curConnected+1>maxConnections) { sprintf(buf,"502 System connection limit at %i.\r\n", ie->maxConnections); write(s,buf,strlen(buf)); close(s); aio_read((struct aiocb *)cb); return; } */ cc=(struct context *)malloc(sizeof(struct context)); bzero(cc,sizeof(struct context)); TAILQ_INSERT_TAIL(&ie->activeConns,cc,clist); ie->connected++; cc->incoming=ie; cc->bufsz=8192; cc->obufsz=9248; cc->cb.cb.aio_fildes=s; cc->cb.cb.aio_buf=cc->bp=cc->buf; cc->cb.cb.aio_nbytes=cc->bufsz; cc->flags|=PERM_CONNECT|PERM_FEED|PERM_MAINT; /* { char fname[64]; sprintf(fname,"/tmp/%u.%u",getpid(),s); cc->cb.logfd=open(fname,O_CREAT|O_TRUNC|O_RDWR); } */ sprintf(cc->obuf,"200 %s - %s - %i - ready\r\n", GetConfigString("ReportedHostName"), GetConfigString("AcceptBanner"), ie->connected); cc->obuflen=strlen(cc->obuf); cc->callback=NntpMain; WriteConn(cc); aio_read((struct aiocb *)cb); return; } int AsyncConnect(unsigned int addr,unsigned int port) { struct sockaddr_in sin,sinl; int val=1,error; int s; sin.sin_addr.s_addr=addr; sin.sin_port=htons((short)port); sin.sin_family=AF_INET; s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); if (s<0) return -1; if (ioctl(s,FIONBIO,&val)) { perror("ioctl"); } bzero(&sinl,sizeof(struct sockaddr_in)); if (bind(s,(struct sockaddr *)&sinl,sizeof(struct sockaddr_in))) return -1; setsockopt(s,SOL_SOCKET,TCP_NODELAY,&val,4); val=0; setsockopt(s,SOL_SOCKET,SO_LINGER,&val,4); error=connect(s,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)); if (ioctl(s,FIONBIO,&val)) { perror("ioctl"); } if ((!error) || ((error) && (errno==EINPROGRESS))) { setsocktimeouts(s); return s; } perror("asyncconnect"); close(s); return -1; } void sig_term() { Shutdown(); } void sig_io() { printf("sigio\n"); } void sig_ignore() { } void sig_alarm() { timerCallback=1; } static int b_mask; static int ub_mask; int signal_setup() { struct sigaction nact; nact.sa_handler=sig_io; sigemptyset(&nact.sa_mask); nact.sa_flags=0; sigaction(SIGIO,&nact,NULL); nact.sa_handler=sig_term; sigaction(SIGTERM,&nact,NULL); sigaction(SIGINT,&nact,NULL); sigaction(SIGQUIT,&nact,NULL); // sigaction(SIGSEGV,&nact,NULL); // sigaction(SIGBUS,&nact,NULL); nact.sa_handler=sig_alarm; sigaction(SIGALRM,&nact,NULL); ualarm(500000,5000000); nact.sa_handler=sig_ignore; sigaction(SIGPIPE,&nact,NULL); b_mask=0; ub_mask=sigmask(SIGUSR1)|sigmask(SIGUSR2)| sigmask(SIGINFO)|sigmask(SIGINT)|sigmask(SIGCONT); mypid=getpid(); } int BlockTimer() { sigset_t mask; sigaddset(&mask,SIGALRM); sigprocmask(SIG_BLOCK,&mask,NULL); } int UnblockTimer() { sigset_t mask; sigaddset(&mask,SIGALRM); sigprocmask(SIG_UNBLOCK,&mask,NULL); }