/* This file is in the public domain. */ #include #include #include #include #include #include extern const char *__progname; #include "oq.h" #include "util.h" #include "listen.h" #include "structs.h" #include "pollloop.h" #include "netfd.h" #define IRINGSIZE 16000 typedef struct netfd NETFD; struct netfd { int fd; int ioid; LISTEN *l; char *text; OQ oq; int tmofd; int tmoid; unsigned char iring[IRINGSIZE]; unsigned int irh; unsigned int irt; unsigned int irn; int procid; } ; static void reset_timeout(NETFD *nf) { struct itimerval itv; itv.it_value.tv_sec = 60; itv.it_value.tv_usec = 0; itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; write(nf->tmofd,&itv,sizeof(itv)); } static void netfd_destroy(NETFD *nf) { close(nf->fd); remove_poll_id(nf->ioid); listen_deref(nf->l); free(nf->text); oq_flush(&nf->oq); close(nf->tmofd); remove_poll_id(nf->tmoid); free(nf); } static int rtest_netfd_data(void *nfv) { return(((NETFD *)nfv)->irn < IRINGSIZE); } static int wtest_netfd_data(void *nfv) { return(oq_nonempty(&((NETFD *)nfv)->oq)); } static void rd_netfd_data(void *nfv) { NETFD *nf; int want; int got; nf = nfv; want = IRINGSIZE - nf->irn; if (want > IRINGSIZE-nf->irh) want = IRINGSIZE - nf->irh; got = read(nf->fd,&nf->iring[nf->irh],want); if (got < 0) { switch (errno) { case EINTR: case NONBLOCKING: return; } fprintf(stderr,"%s: %s: read: %s\n",__progname,nf->text,strerror(errno)); netfd_destroy(nf); return; } nf->irh += got; nf->irn += got; if (nf->irh > IRINGSIZE) abort(); if (nf->irh == IRINGSIZE) nf->irh = 0; // XXX next line for debugging printf("read %d from %s\n",got,nf->text); } static void wr_netfd_data(void *nfv) { NETFD *nf; int w; nf = nfv; w = oq_writev(&nf->oq,nf->fd); if (w < 0) { switch (errno) { case EINTR: case NONBLOCKING: return; break; } fprintf(stderr,"%s: %s: writev: %s\n",__progname,nf->text,strerror(errno)); netfd_destroy(nf); return; } oq_dropdata(&nf->oq,w); reset_timeout(nf); } static void rd_netfd_tmo(void *nfv) { netfd_destroy(nfv); } static int netfd_process(void *nfv) { NETFD *nf; nf = nfv; if (nf->irn < 1) return(BLOCK_NIL); return(BLOCK_NIL); // XXX XXX XXX } void netfd_new(int fd, LISTEN *l, char *text) { NETFD *nf; listen_ref(l); nf = malloc(sizeof(NETFD)); nf->fd = fd; nf->ioid = add_poll_fd(fd,&rtest_netfd_data,&wtest_netfd_data,&rd_netfd_data,&wr_netfd_data,nf); nf->l = l; nf->text = text; oq_init(&nf->oq); nf->tmofd = socket(AF_TIMER,SOCK_STREAM,0); nf->tmoid = add_poll_fd(nf->tmofd,&rwtest_always,&rwtest_never,&rd_netfd_tmo,0,nf); nf->irh = 0; nf->irt = 0; nf->irn = 0; nf->procid = add_block_fn(&netfd_process,nf); reset_timeout(nf); // XXX next two lines for debuggign help only oq_queue_point(&nf->oq,text,strlen(text)); oq_queue_point(&nf->oq,"\r\n",2); }