LCOV - code coverage report
Current view: top level - src - async.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 32 125 25.6 %
Date: 2017-07-01 Functions: 5 11 45.5 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "alloc.h"
       3             : #include "asfd.h"
       4             : #include "async.h"
       5             : #include "handy.h"
       6             : #include "iobuf.h"
       7             : #include "log.h"
       8             : 
       9         136 : void async_free(struct async **as)
      10             : {
      11         285 :         if(!as || !*as) return;
      12         146 :         free_v((void **)as);
      13             : }
      14             : 
      15           0 : static void async_settimers(struct async *as, int sec, int usec)
      16             : {
      17           0 :         as->setsec=sec;
      18           0 :         as->setusec=usec;
      19           0 : }
      20             : 
      21             : // The normal server and client processes will just exit on error within
      22             : // async_io, but the champ chooser server needs to manage client fds and
      23             : // remove them from its list if one of them had a problem.
      24             : static int asfd_problem(struct asfd *asfd)
      25             : {
      26           0 :         asfd->want_to_remove++;
      27           0 :         asfd->as->last_time=asfd->as->now;
      28             :         return -1;
      29             : }
      30             : 
      31           0 : static int async_io(struct async *as, int doread)
      32             : {
      33           0 :         int mfd=-1;
      34             :         fd_set fsr;
      35             :         fd_set fsw;
      36             :         fd_set fse;
      37           0 :         int dosomething=0;
      38             :         struct timeval tval;
      39           0 :         struct asfd *asfd;
      40             :         static int s=0;
      41             : 
      42           0 :         as->now=time(NULL);
      43           0 :         if(!as->last_time) as->last_time=as->now;
      44             : 
      45           0 :         if(as->doing_estimate) goto end;
      46             : 
      47           0 :         FD_ZERO(&fsr);
      48           0 :         FD_ZERO(&fsw);
      49           0 :         FD_ZERO(&fse);
      50             : 
      51           0 :         tval.tv_sec=as->setsec;
      52           0 :         tval.tv_usec=as->setusec;
      53             : 
      54           0 :         for(asfd=as->asfd; asfd; asfd=asfd->next)
      55             :         {
      56           0 :                 if(asfd->attempt_reads)
      57           0 :                         asfd->doread=doread;
      58             :                 else
      59           0 :                         asfd->doread=0;
      60             : 
      61           0 :                 asfd->dowrite=0;
      62             : 
      63           0 :                 if(doread)
      64             :                 {
      65           0 :                         if(asfd->parse_readbuf(asfd))
      66           0 :                                 return asfd_problem(asfd);
      67           0 :                         if(asfd->rbuf->buf || asfd->read_blocked_on_write)
      68           0 :                                 asfd->doread=0;
      69             :                 }
      70             : 
      71           0 :                 if(asfd->writebuflen && !asfd->write_blocked_on_read)
      72           0 :                         asfd->dowrite++; // The write buffer is not yet empty.
      73             : 
      74           0 :                 if(!asfd->doread && !asfd->dowrite) continue;
      75             : 
      76           0 :                 add_fd_to_sets(asfd->fd, asfd->doread?&fsr:NULL,
      77           0 :                         asfd->dowrite?&fsw:NULL, &fse, &mfd);
      78             : 
      79           0 :                 dosomething++;
      80             :         }
      81           0 :         if(!dosomething) goto end;
      82             : /*
      83             :         for(asfd=as->asfd; asfd; asfd=asfd->next)
      84             :         {
      85             :                 printf("%s: %d %d %d %d\n", asfd->desc,
      86             :                         asfd->doread, asfd->dowrite,
      87             :                         asfd->readbuflen, asfd->writebuflen);
      88             :         }
      89             : */
      90             : 
      91           0 :         errno=0;
      92           0 :         s=select(mfd+1, &fsr, &fsw, &fse, &tval);
      93           0 :         if(errno==EAGAIN || errno==EINTR) goto end;
      94             : 
      95           0 :         if(s<0)
      96             :         {
      97           0 :                 logp("select error in %s: %s\n", __func__,
      98             :                         strerror(errno));
      99           0 :                 as->last_time=as->now;
     100           0 :                 return -1;
     101             :         }
     102             : 
     103           0 :         for(asfd=as->asfd; asfd; asfd=asfd->next)
     104             :         {
     105           0 :                 if(FD_ISSET(asfd->fd, &fse))
     106             :                 {
     107           0 :                         switch(asfd->fdtype)
     108             :                         {
     109             :                                 case ASFD_FD_SERVER_LISTEN_MAIN:
     110             :                                 case ASFD_FD_SERVER_LISTEN_STATUS:
     111           0 :                                         as->last_time=as->now;
     112           0 :                                         return -1;
     113             :                                 default:
     114             : #ifdef _AIX
     115             :                                         /* On AIX, for some weird reason,
     116             :                                          * writing the stats file makes the
     117             :                                          * socket show up in fse, despite
     118             :                                          * everything being fine. We ignore
     119             :                                          * it.
     120             :                                          */
     121             :                                         if(strncmp(asfd->desc, "stats file",
     122             :                                                 sizeof("stats file")))
     123             :                                         {
     124             :                                                 logp("%s: had an exception\n",
     125             :                                                         asfd->desc);
     126             :                                                 return asfd_problem(asfd);
     127             :                                         }
     128             : #else
     129           0 :                                         logp("%s: had an exception\n",
     130             :                                                 asfd->desc);
     131           0 :                                         return asfd_problem(asfd);
     132             : #endif /* _AIX */
     133             :                         }
     134             :                 }
     135             : 
     136           0 :                 if(asfd->doread && FD_ISSET(asfd->fd, &fsr)) // Able to read.
     137             :                 {
     138           0 :                         asfd->network_timeout=asfd->max_network_timeout;
     139           0 :                         switch(asfd->fdtype)
     140             :                         {
     141             :                                 case ASFD_FD_SERVER_LISTEN_MAIN:
     142             :                                 case ASFD_FD_SERVER_LISTEN_STATUS:
     143             :                                         // Indicate to the caller that we have
     144             :                                         // a new incoming client.
     145           0 :                                         asfd->new_client++;
     146           0 :                                         break;
     147             :                                 default:
     148           0 :                                         if(asfd->do_read(asfd)
     149           0 :                                           || asfd->parse_readbuf(asfd))
     150           0 :                                                 return asfd_problem(asfd);
     151             :                                         break;
     152             :                         }
     153             :                 }
     154             : 
     155           0 :                 if(asfd->dowrite && FD_ISSET(asfd->fd, &fsw)) // Able to write.
     156             :                 {
     157           0 :                         asfd->network_timeout=asfd->max_network_timeout;
     158           0 :                         if(asfd->do_write(asfd))
     159           0 :                                 return asfd_problem(asfd);
     160             :                 }
     161             : 
     162           0 :                 if((!asfd->doread || !FD_ISSET(asfd->fd, &fsr))
     163           0 :                   && (!asfd->dowrite || !FD_ISSET(asfd->fd, &fsw)))
     164             :                 {
     165             :                         // Be careful to avoid 'read quick' mode.
     166           0 :                         if((as->setsec || as->setusec)
     167           0 :                           && asfd->max_network_timeout>0
     168           0 :                           && as->now-as->last_time>0
     169           0 :                           && asfd->network_timeout--<=0)
     170             :                         {
     171           0 :                                 logp("%s: no activity for %d seconds.\n",
     172             :                                         asfd->desc, asfd->max_network_timeout);
     173           0 :                                 return asfd_problem(asfd);
     174             :                         }
     175             :                 }
     176             :         }
     177             : 
     178             : end:
     179           0 :         as->last_time=as->now;
     180           0 :         return 0;
     181             : }
     182             : 
     183           0 : static int async_read_write(struct async *as)
     184             : {
     185           0 :         return async_io(as, 1 /* Read too. */);
     186             : }
     187             : 
     188           0 : static int async_write(struct async *as)
     189             : {
     190           0 :         return async_io(as, 0 /* No read. */);
     191             : }
     192             : 
     193           0 : static int async_read_quick(struct async *as)
     194             : {
     195             :         int r;
     196           0 :         int savesec=as->setsec;
     197           0 :         int saveusec=as->setusec;
     198           0 :         as->setsec=0;
     199           0 :         as->setusec=0;
     200           0 :         r=as->read_write(as); // Maybe make an as->read(as) function some time.
     201           0 :         as->setsec=savesec;
     202           0 :         as->setusec=saveusec;
     203           0 :         return r;
     204             : }
     205             : 
     206         194 : static void async_asfd_add(struct async *as, struct asfd *asfd)
     207             : {
     208             :         struct asfd *x;
     209         194 :         if(!as->asfd)
     210             :         {
     211         137 :                 as->asfd=asfd;
     212         331 :                 return;
     213             :         }
     214             :         // Add to the end;
     215          88 :         for(x=as->asfd; x->next; x=x->next) { }
     216          57 :         x->next=asfd;
     217             : }
     218             : 
     219           0 : static void async_asfd_remove(struct async *as, struct asfd *asfd)
     220             : {
     221             :         struct asfd *l;
     222           0 :         if(!asfd) return;
     223           0 :         if(as->asfd==asfd)
     224             :         {
     225           0 :                 as->asfd=as->asfd->next;
     226           0 :                 return;
     227             :         }
     228           0 :         for(l=as->asfd; l; l=l->next)
     229             :         {
     230           0 :                 if(l->next!=asfd) continue;
     231           0 :                 l->next=asfd->next;
     232           0 :                 return;
     233             :         }
     234             : }
     235             : 
     236          13 : void async_asfd_free_all(struct async **as)
     237             : {
     238          13 :         struct asfd *a=NULL;
     239          13 :         struct asfd *asfd=NULL;
     240          13 :         if(!as || !*as) return;
     241          26 :         for(asfd=(*as)->asfd; asfd; asfd=a)
     242             :         {
     243          13 :                 a=asfd->next;
     244          13 :                 asfd_free(&asfd);
     245             :         }
     246             :         async_free(as);
     247             : }
     248             : 
     249         146 : static int async_init(struct async *as, int estimate)
     250             : {
     251         146 :         as->setsec=1;
     252         146 :         as->setusec=0;
     253         146 :         as->last_time=0;
     254         146 :         as->doing_estimate=estimate;
     255             : 
     256         146 :         as->read_write=async_read_write;
     257         146 :         as->write=async_write;
     258         146 :         as->read_quick=async_read_quick;
     259             : 
     260         146 :         as->settimers=async_settimers;
     261         146 :         as->asfd_add=async_asfd_add;
     262         146 :         as->asfd_remove=async_asfd_remove;
     263             : 
     264         146 :         return 0;
     265             : }
     266             : 
     267         146 : struct async *async_alloc(void)
     268             : {
     269             :         struct async *as;
     270         146 :         if(!(as=(struct async *)calloc_w(1, sizeof(struct async), __func__)))
     271             :                 return NULL;
     272         146 :         as->init=async_init;
     273         146 :         return as;
     274             : }

Generated by: LCOV version 1.10