LCOV - code coverage report
Current view: top level - src - asfd.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 133 371 35.8 %
Date: 2019-12-31 08:05:25 Functions: 18 40 45.0 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "alloc.h"
       3             : #include "asfd.h"
       4             : #include "async.h"
       5             : #include "cmd.h"
       6             : #include "fsops.h"
       7             : #include "handy.h"
       8             : #include "iobuf.h"
       9             : #include "log.h"
      10             : #include "server/protocol2/champ_chooser/incoming.h"
      11             : 
      12             : // For IPTOS / IPTOS_THROUGHPUT.
      13             : #ifdef HAVE_WIN32
      14             : #include <ws2tcpip.h>
      15             : #else
      16             : #include <netinet/ip.h>
      17             : #endif
      18             : 
      19             : #ifdef HAVE_NCURSES_H
      20             : #include <ncurses.h>
      21             : #elif HAVE_NCURSES_NCURSES_H
      22             : #include <ncurses/ncurses.h>
      23             : #endif
      24             : 
      25             : #include "protocol2/blist.h"
      26             : 
      27             : static void truncate_readbuf(struct asfd *asfd)
      28             : {
      29           0 :         asfd->readbuf[0]='\0';
      30           0 :         asfd->readbuflen=0;
      31             : }
      32             : 
      33             : static int asfd_alloc_buf(struct asfd *asfd, char **buf)
      34             : {
      35          18 :         if(!*buf && !(*buf=(char *)calloc_w(1, asfd->bufmaxsize, __func__)))
      36             :                 return -1;
      37             :         return 0;
      38             : }
      39             : 
      40           0 : static int extract_buf(struct asfd *asfd,
      41             :         size_t len, size_t offset)
      42             : {
      43           0 :         if(offset+len>=asfd->bufmaxsize)
      44             :         {
      45           0 :                 logp("%s: offset(%lu)+len(%lu)>=asfd->bufmaxsize(%lu) in %s!",
      46             :                         asfd->desc,
      47             :                         (unsigned long)offset,
      48             :                         (unsigned long)len,
      49             :                         (unsigned long)asfd->bufmaxsize,
      50             :                         __func__);
      51           0 :                 return -1;
      52             :         }
      53             : 
      54           0 :         if(!(asfd->rbuf->buf=(char *)malloc_w(len+1, __func__)))
      55             :                 return -1;
      56           0 :         if(!(memcpy(asfd->rbuf->buf, asfd->readbuf+offset, len)))
      57             :         {
      58           0 :                 logp("%s: memcpy failed in %s\n", asfd->desc, __func__);
      59           0 :                 return -1;
      60             :         }
      61           0 :         asfd->rbuf->buf[len]='\0';
      62           0 :         if(!(memmove(asfd->readbuf,
      63           0 :                 asfd->readbuf+len+offset, asfd->readbuflen-len-offset)))
      64             :         {
      65           0 :                 logp("%s: memmove failed in %s\n", asfd->desc, __func__);
      66           0 :                 return -1;
      67             :         }
      68           0 :         asfd->readbuflen-=len+offset;
      69           0 :         asfd->rbuf->len=len;
      70           0 :         return 0;
      71             : }
      72             : 
      73             : #ifdef HAVE_NCURSES
      74           0 : static int parse_readbuf_ncurses(struct asfd *asfd)
      75             : {
      76           0 :         if(!asfd->readbuflen) return 0;
      77             :         // This is reading ints, and will be cast back to an int when it comes
      78             :         // to be processed later.
      79           0 :         if(extract_buf(asfd, asfd->readbuflen, 0)) return -1;
      80           0 :         return 0;
      81             : }
      82             : #endif
      83             : 
      84           0 : static int parse_readbuf_line_buf(struct asfd *asfd)
      85             : {
      86             :         static char *cp=NULL;
      87             :         static char *dp=NULL;
      88             :         static size_t len=0;
      89           0 :         if(!cp)
      90             :         {
      91             :                 // Only start from the beginning if we previously got something
      92             :                 // to extract.
      93           0 :                 cp=asfd->readbuf;
      94           0 :                 len=0;
      95             :         }
      96           0 :         for(; len<asfd->readbuflen; cp++, len++)
      97             :         {
      98           0 :                 if(*cp!='\n') continue;
      99           0 :                 len++;
     100           0 :                 if(extract_buf(asfd, len, 0)) return -1;
     101             :                 // Strip trailing white space, like '\r\n'.
     102           0 :                 dp=asfd->rbuf->buf;
     103           0 :                 for(cp=&(dp[len-1]); cp>=dp && isspace(*cp); cp--, len--)
     104           0 :                         *cp='\0';
     105           0 :                 asfd->rbuf->len=len;
     106           0 :                 break;
     107             :         }
     108           0 :         cp=NULL;
     109           0 :         return 0;
     110             : }
     111             : 
     112           0 : static int parse_readbuf_standard(struct asfd *asfd)
     113             : {
     114           0 :         unsigned int s=0;
     115             :         char command;
     116           0 :         if(asfd->readbuflen<5) return 0;
     117           0 :         if((sscanf(asfd->readbuf, "%c%04X", &command, &s))!=2)
     118             :         {
     119           0 :                 logp("%s: sscanf of '%s' failed in %s\n",
     120             :                         asfd->desc, asfd->readbuf, __func__);
     121           0 :                 return -1;
     122             :         }
     123           0 :         if(s>=asfd->bufmaxsize)
     124             :         {
     125           0 :                 logp("%s: given buffer length '%d', which is too big!\n",
     126             :                         asfd->desc, s);
     127           0 :                 return -1;
     128             :         }
     129           0 :         if(asfd->readbuflen>=s+5)
     130             :         {
     131           0 :                 asfd->rbuf->cmd=(enum cmd)command;
     132           0 :                 if(extract_buf(asfd, (size_t)s, 5))
     133             :                         return -1;
     134             :         }
     135             :         return 0;
     136             : }
     137             : 
     138           0 : static int asfd_parse_readbuf(struct asfd *asfd)
     139             : {
     140           0 :         if(asfd->rbuf->buf) return 0;
     141             : 
     142           0 :         if(asfd->parse_readbuf_specific(asfd))
     143             :         {
     144           0 :                 truncate_readbuf(asfd);
     145           0 :                 return -1;
     146             :         }
     147             : 
     148             :         return 0;
     149             : }
     150             : 
     151             : #ifdef HAVE_NCURSES
     152           0 : static int asfd_do_read_ncurses(struct asfd *asfd)
     153             : {
     154             :         static int i;
     155           0 :         i=getch();
     156           0 :         asfd->readbuflen=sizeof(int);
     157           0 :         memcpy(asfd->readbuf, &i, asfd->readbuflen);
     158           0 :         return 0;
     159             : }
     160             : 
     161           0 : static int asfd_do_write_ncurses(__attribute__ ((unused)) struct asfd *asfd)
     162             : {
     163           0 :         logp("This function should not have been called: %s\n", __func__);
     164           0 :         return -1;
     165             : }
     166             : #endif
     167             : 
     168           0 : static int asfd_do_read(struct asfd *asfd)
     169             : {
     170             :         ssize_t r;
     171           0 :         r=read(asfd->fd,
     172           0 :           asfd->readbuf+asfd->readbuflen, asfd->bufmaxsize-asfd->readbuflen);
     173           0 :         if(r<0)
     174             :         {
     175           0 :                 if(errno==EAGAIN || errno==EINTR)
     176             :                         return 0;
     177           0 :                 logp("%s: read problem on fd %d: %s\n",
     178             :                         asfd->desc, asfd->fd, strerror(errno));
     179           0 :                 goto error;
     180             :         }
     181           0 :         else if(!r)
     182             :         {
     183             :                 // End of data.
     184           0 :                 logp("%s: end of data\n", asfd->desc);
     185           0 :                 goto error;
     186             :         }
     187           0 :         asfd->readbuflen+=r;
     188           0 :         asfd->rcvd+=r;
     189           0 :         return 0;
     190             : error:
     191           0 :         truncate_readbuf(asfd);
     192           0 :         return -1;
     193             : }
     194             : 
     195             : static void peer_msg(void)
     196             : {
     197           0 :         logp("This is probably caused by the peer exiting.\n");
     198           0 :         logp("Please check the peer's logs.\n");
     199             : }
     200             : 
     201           0 : static int asfd_do_read_ssl(struct asfd *asfd)
     202             : {
     203             :         int e;
     204             :         ssize_t r;
     205             : 
     206           0 :         asfd->read_blocked_on_write=0;
     207             : 
     208           0 :         ERR_clear_error();
     209           0 :         r=SSL_read(
     210             :                 asfd->ssl,
     211           0 :                 asfd->readbuf+asfd->readbuflen,
     212           0 :                 asfd->bufmaxsize-asfd->readbuflen
     213             :         );
     214             : 
     215           0 :         switch((e=SSL_get_error(asfd->ssl, r)))
     216             :         {
     217             :                 case SSL_ERROR_NONE:
     218           0 :                         asfd->readbuflen+=r;
     219           0 :                         asfd->rcvd+=r;
     220           0 :                         break;
     221             :                 case SSL_ERROR_ZERO_RETURN:
     222             :                         // End of data.
     223           0 :                         logp("%s: Peer closed SSL session\n", asfd->desc);
     224           0 :                         SSL_shutdown(asfd->ssl);
     225           0 :                         goto error;
     226             :                 case SSL_ERROR_WANT_READ:
     227             :                         break;
     228             :                 case SSL_ERROR_WANT_WRITE:
     229           0 :                         asfd->read_blocked_on_write=1;
     230           0 :                         break;
     231             :                 case SSL_ERROR_SYSCALL:
     232           0 :                         if(errno==EAGAIN || errno==EINTR)
     233             :                                 break;
     234           0 :                         logp("%s: Got network read error\n",
     235             :                                 asfd->desc);
     236             :                         // Fall through to read problem
     237             :                 default:
     238           0 :                         asfd->errors++;
     239           0 :                         logp_ssl_err(
     240             :                                 "%s: network read problem in %s: %d - %d=%s\n",
     241             :                                 asfd->desc, __func__,
     242           0 :                                 e, errno, strerror(errno));
     243             :                         peer_msg();
     244             :                         goto error;
     245             :         }
     246             :         return 0;
     247             : error:
     248           0 :         truncate_readbuf(asfd);
     249           0 :         return -1;
     250             : }
     251             : 
     252             : // Return 0 for OK to write, non-zero for not OK to write.
     253           0 : static int check_ratelimit(struct asfd *asfd)
     254             : {
     255             :         float f;
     256             :         time_t diff;
     257           0 :         if(!asfd->rlstart) asfd->rlstart=time(NULL);
     258           0 :         if((diff=asfd->as->now-asfd->rlstart)<0)
     259             :         {
     260             :                 // It is possible that the clock changed. Reset ourselves.
     261           0 :                 asfd->as->now=asfd->rlstart;
     262           0 :                 asfd->rlbytes=0;
     263           0 :                 logp("Looks like the clock went back in time since starting. "
     264             :                         "Resetting ratelimit\n");
     265           0 :                 return 0;
     266             :         }
     267           0 :         if(!diff) return 0; // Need to get started somehow.
     268           0 :         f=(asfd->rlbytes)/diff; // Bytes per second.
     269             : 
     270           0 :         if(f>=asfd->ratelimit)
     271             :         {
     272             : #ifdef HAVE_WIN32
     273             :                 // Windows Sleep is milliseconds, usleep is microseconds.
     274             :                 // Do some conversion.
     275             :                 Sleep(asfd->rlsleeptime/1000);
     276             : #else
     277           0 :                 usleep(asfd->rlsleeptime);
     278             : #endif
     279             :                 // If sleeping, increase the sleep time.
     280           0 :                 if((asfd->rlsleeptime*=2)>=500000) asfd->rlsleeptime=500000;
     281             :                 return 1;
     282             :         }
     283             :         // If not sleeping, decrease the sleep time.
     284           0 :         if((asfd->rlsleeptime/=2)<=9999) asfd->rlsleeptime=10000;
     285             :         return 0;
     286             : }
     287             : 
     288           0 : static int asfd_do_write(struct asfd *asfd)
     289             : {
     290             :         ssize_t w;
     291           0 :         if(asfd->ratelimit && check_ratelimit(asfd)) return 0;
     292             : 
     293           0 :         w=write(asfd->fd, asfd->writebuf, asfd->writebuflen);
     294           0 :         if(w<0)
     295             :         {
     296           0 :                 if(errno==EAGAIN || errno==EINTR)
     297             :                         return 0;
     298           0 :                 logp("%s: Got error in %s, (%d=%s)\n", __func__,
     299             :                         asfd->desc, errno, strerror(errno));
     300           0 :                 asfd->errors++;
     301           0 :                 return -1;
     302             :         }
     303           0 :         else if(!w)
     304             :         {
     305           0 :                 logp("%s: Wrote nothing in %s\n", asfd->desc, __func__);
     306           0 :                 asfd->errors++;
     307           0 :                 return -1;
     308             :         }
     309           0 :         if(asfd->ratelimit) asfd->rlbytes+=w;
     310           0 :         asfd->sent+=w;
     311             : /*
     312             : {
     313             : char buf[100000]="";
     314             : snprintf(buf, w+1, "%s", asfd->writebuf);
     315             : printf("wrote %d: %s\n", w, buf);
     316             : }
     317             : */
     318             : 
     319           0 :         memmove(asfd->writebuf, asfd->writebuf+w, asfd->writebuflen-w);
     320           0 :         asfd->writebuflen-=w;
     321           0 :         return 0;
     322             : }
     323             : 
     324           0 : static int asfd_do_write_ssl(struct asfd *asfd)
     325             : {
     326             :         int e;
     327             :         ssize_t w;
     328             : 
     329           0 :         asfd->write_blocked_on_read=0;
     330             : 
     331           0 :         if(asfd->ratelimit && check_ratelimit(asfd)) return 0;
     332           0 :         ERR_clear_error();
     333           0 :         w=SSL_write(asfd->ssl, asfd->writebuf, asfd->writebuflen);
     334             : 
     335           0 :         switch((e=SSL_get_error(asfd->ssl, w)))
     336             :         {
     337             :                 case SSL_ERROR_NONE:
     338             : /*
     339             : {
     340             : char buf[100000]="";
     341             : snprintf(buf, w+1, "%s", asfd->writebuf);
     342             : printf("wrote %d: %s\n", w, buf);
     343             : }
     344             : */
     345           0 :                         if(asfd->ratelimit) asfd->rlbytes+=w;
     346           0 :                         memmove(asfd->writebuf,
     347           0 :                                 asfd->writebuf+w, asfd->writebuflen-w);
     348           0 :                         asfd->writebuflen-=w;
     349           0 :                         asfd->sent+=w;
     350           0 :                         break;
     351             :                 case SSL_ERROR_WANT_WRITE:
     352             :                         break;
     353             :                 case SSL_ERROR_WANT_READ:
     354           0 :                         asfd->write_blocked_on_read=1;
     355           0 :                         break;
     356             :                 case SSL_ERROR_SYSCALL:
     357           0 :                         if(errno==EAGAIN || errno==EINTR)
     358             :                                 break;
     359           0 :                         logp("%s: Got network write error\n",
     360             :                                 asfd->desc);
     361             :                         // Fall through to write problem
     362             :                 default:
     363           0 :                         asfd->errors++;
     364           0 :                         logp_ssl_err(
     365             :                                 "%s: network write problem in %s: %d - %d=%s\n",
     366             :                                 asfd->desc, __func__,
     367           0 :                                 e, errno, strerror(errno));
     368             :                         peer_msg();
     369           0 :                         return -1;
     370             :         }
     371             :         return 0;
     372             : }
     373             : 
     374             : static int append_to_write_buffer(struct asfd *asfd,
     375             :         const char *buf, size_t len)
     376             : {
     377           0 :         memcpy(asfd->writebuf+asfd->writebuflen, buf, len);
     378           0 :         asfd->writebuflen+=len;
     379           0 :         asfd->writebuf[asfd->writebuflen]='\0';
     380             :         return 0;
     381             : }
     382             : 
     383           0 : static enum append_ret asfd_append_all_to_write_buffer(struct asfd *asfd,
     384             :         struct iobuf *wbuf)
     385             : {
     386           0 :         switch(asfd->streamtype)
     387             :         {
     388             :                 case ASFD_STREAM_STANDARD:
     389             :                 {
     390           0 :                         size_t sblen=0;
     391           0 :                         char sbuf[10]="";
     392           0 :                         if(asfd->writebuflen+6+(wbuf->len)>=asfd->bufmaxsize-1)
     393           0 :                                 return APPEND_BLOCKED;
     394             : 
     395           0 :                         snprintf(sbuf, sizeof(sbuf), "%c%04X",
     396           0 :                                 wbuf->cmd, (unsigned int)wbuf->len);
     397           0 :                         sblen=strlen(sbuf);
     398           0 :                         append_to_write_buffer(asfd, sbuf, sblen);
     399           0 :                         break;
     400             :                 }
     401             :                 case ASFD_STREAM_LINEBUF:
     402           0 :                         if(asfd->writebuflen+wbuf->len>=asfd->bufmaxsize-1)
     403             :                                 return APPEND_BLOCKED;
     404             :                         break;
     405             :                 case ASFD_STREAM_NCURSES_STDIN:
     406             :                 default:
     407           0 :                         logp("%s: unknown asfd stream type in %s: %d\n",
     408             :                                 asfd->desc, __func__, asfd->streamtype);
     409           0 :                         return APPEND_ERROR;
     410             :         }
     411           0 :         append_to_write_buffer(asfd, wbuf->buf, wbuf->len);
     412             : //printf("append %s\n", iobuf_to_printable(wbuf));
     413           0 :         wbuf->len=0;
     414           0 :         return APPEND_OK;
     415             : }
     416             : 
     417             : #ifdef IPTOS_THROUGHPUT
     418           0 : static int asfd_connection_af(struct asfd *asfd)
     419             : {
     420             :         struct sockaddr_storage s;
     421           0 :         socklen_t slen = sizeof(s);
     422             : 
     423           0 :         memset(&s, 0, sizeof(s));
     424           0 :         if(getsockname(asfd->fd, (struct sockaddr *)&s, &slen)<0)
     425             :                 return 0;
     426           0 :         return s.ss_family;
     427             : }
     428             : #endif
     429             : 
     430           0 : static int asfd_set_bulk_packets(struct asfd *asfd)
     431             : {
     432             : #ifdef IPTOS_THROUGHPUT
     433           0 :         int opt=IPTOS_THROUGHPUT;
     434           0 :         if(asfd->fd<0) return -1;
     435             : 
     436           0 :         switch(asfd_connection_af(asfd))
     437             :         {
     438             :                 case AF_INET:
     439           0 :                         if(setsockopt(asfd->fd, IPPROTO_IP, IP_TOS,
     440             :                                 (char *)&opt, sizeof(opt))>=0)
     441             :                                         break;
     442           0 :                         logp("%s: error: set IPTOS throughput: %s\n",
     443           0 :                                 asfd->desc, strerror(errno));
     444           0 :                         return -1;
     445             :                 case AF_INET6:
     446           0 :                         if(setsockopt(asfd->fd, IPPROTO_IPV6, IPV6_TCLASS,
     447             :                                 (char *)&opt, sizeof(opt))>=0)
     448             :                                         break;
     449           0 :                         logp("%s: error: set IPV6_TCLASS throughput: %s\n",
     450           0 :                                 asfd->desc, strerror(errno));
     451           0 :                         return -1;
     452             :         }
     453             : #endif
     454             :         return 0;
     455             : }
     456             : 
     457           0 : static int asfd_read(struct asfd *asfd)
     458             : {
     459           0 :         if(asfd->as->doing_estimate) return 0;
     460           0 :         while(!asfd->rbuf->buf)
     461             :         {
     462           0 :                 if(asfd->errors)
     463             :                         return -1;
     464           0 :                 if(asfd->as->read_write(asfd->as))
     465             :                         return -1;
     466             :         }
     467             :         return 0;
     468             : }
     469             : 
     470         100 : int asfd_read_expect(struct asfd *asfd, enum cmd cmd, const char *expect)
     471             : {
     472         100 :         int ret=0;
     473         100 :         if(asfd->read(asfd)) return -1;
     474          97 :         if(asfd->rbuf->cmd!=cmd || strcmp(asfd->rbuf->buf, expect))
     475             :         {
     476           5 :                 logp("%s: expected '%c:%s', got '%s'\n",
     477             :                         asfd->desc, cmd, expect,
     478             :                         iobuf_to_printable(asfd->rbuf));
     479           5 :                 ret=-1;
     480             :         }
     481          97 :         iobuf_free_content(asfd->rbuf);
     482          97 :         return ret;
     483             : }
     484             : 
     485           0 : static int asfd_write(struct asfd *asfd, struct iobuf *wbuf)
     486             : {
     487           0 :         if(asfd->as->doing_estimate) return 0;
     488           0 :         while(wbuf->len)
     489             :         {
     490           0 :                 if(asfd->errors)
     491             :                         return -1;
     492           0 :                 if(asfd->append_all_to_write_buffer(asfd, wbuf)==APPEND_ERROR)
     493             :                         return -1;
     494           0 :                 if(asfd->as->write(asfd->as)) return -1;
     495             :         }
     496             :         return 0;
     497             : }
     498             : 
     499           0 : static int asfd_write_str(struct asfd *asfd, enum cmd wcmd, const char *wsrc)
     500             : {
     501             :         struct iobuf wbuf;
     502           0 :         wbuf.cmd=wcmd;
     503           0 :         wbuf.buf=(char *)wsrc;
     504           0 :         wbuf.len=strlen(wsrc);
     505           0 :         return asfd->write(asfd, &wbuf);
     506             : }
     507             : 
     508             : #ifndef UTEST
     509             : static
     510             : #endif
     511          19 : int asfd_simple_loop(struct asfd *asfd,
     512             :         struct conf **confs, void *param, const char *caller,
     513             :   enum asl_ret callback(struct asfd *asfd, struct conf **confs, void *param))
     514             : {
     515          19 :         struct iobuf *rbuf=asfd->rbuf;
     516             :         while(1)
     517             :         {
     518         750 :                 iobuf_free_content(rbuf);
     519         750 :                 if(asfd->read(asfd)) goto error;
     520         749 :                 if(!rbuf->buf) continue;
     521          30 :                 if(rbuf->cmd!=CMD_GEN)
     522             :                 {
     523           0 :                         if(rbuf->cmd==CMD_WARNING
     524           0 :                           || rbuf->cmd==CMD_MESSAGE)
     525             :                         {
     526           0 :                                 struct cntr *cntr=NULL;
     527           0 :                                 if(confs) cntr=get_cntr(confs);
     528           0 :                                 log_recvd(rbuf, cntr, 0);
     529             :                         }
     530           0 :                         else if(rbuf->cmd==CMD_INTERRUPT)
     531             :                         {
     532             :                                 // Ignore - client wanted to interrupt a file.
     533             :                         }
     534             :                         else
     535             :                         {
     536           0 :                                 logp("%s: unexpected command in %s(), called from %s(): %s\n", asfd->desc, __func__, caller, iobuf_to_printable(rbuf));
     537           0 :                                 goto error;
     538             :                         }
     539           0 :                         continue;
     540             :                 }
     541          30 :                 switch(callback(asfd, confs, param))
     542             :                 {
     543             :                         case ASL_CONTINUE: break;
     544             :                         case ASL_END_OK:
     545          16 :                                 iobuf_free_content(rbuf);
     546          16 :                                 return 0;
     547             :                         case ASL_END_OK_RETURN_1:
     548           0 :                                 iobuf_free_content(rbuf);
     549           0 :                                 return 1;
     550             :                         case ASL_END_ERROR:
     551             :                         default:
     552             :                                 goto error;
     553             :                 }
     554             :         }
     555             : error:
     556           3 :         iobuf_free_content(rbuf);
     557           3 :         return -1;
     558             : }
     559             : 
     560           0 : static void asfd_set_timeout(struct asfd *asfd, int max_network_timeout)
     561             : {
     562           0 :         asfd->max_network_timeout=max_network_timeout;
     563           0 :         asfd->network_timeout=asfd->max_network_timeout;
     564           0 : }
     565             : 
     566           9 : static char *get_asfd_desc(const char *desc, int fd)
     567             : {
     568           9 :         char r[256]="";
     569           9 :         snprintf(r, sizeof(r), "%s %d", desc, fd);
     570           9 :         return strdup_w(r, __func__);
     571             : }
     572             : 
     573           9 : static int asfd_init(struct asfd *asfd, const char *desc,
     574             :         struct async *as, int afd, const char *listen,
     575             :         SSL *assl, enum asfd_streamtype streamtype)
     576             : {
     577           9 :         asfd->as=as;
     578           9 :         asfd->fd=afd;
     579           9 :         asfd->ssl=assl;
     580           9 :         asfd->streamtype=streamtype;
     581           9 :         asfd->rlsleeptime=10000;
     582           9 :         asfd->pid=-1;
     583           9 :         asfd->attempt_reads=1;
     584           9 :         asfd->bufmaxsize=(ASYNC_BUF_LEN*2)+32;
     585             : #ifdef HAVE_WIN32
     586             :         // Windows craps out if you try to read stdin into a buffer that is
     587             :         // too big!
     588             :         if(asfd->fd==fileno(stdin))
     589             :                 asfd->bufmaxsize=4096;
     590             : #endif
     591             : 
     592           9 :         asfd->parse_readbuf=asfd_parse_readbuf;
     593           9 :         asfd->append_all_to_write_buffer=asfd_append_all_to_write_buffer;
     594           9 :         asfd->set_bulk_packets=asfd_set_bulk_packets;
     595           9 :         asfd->set_timeout=asfd_set_timeout;
     596           9 :         if(asfd->ssl)
     597             :         {
     598           1 :                 asfd->do_read=asfd_do_read_ssl;
     599           1 :                 asfd->do_write=asfd_do_write_ssl;
     600             :         }
     601             :         else
     602             :         {
     603           8 :                 asfd->do_read=asfd_do_read;
     604           8 :                 asfd->do_write=asfd_do_write;
     605             : #ifdef HAVE_NCURSES
     606           8 :                 if(asfd->streamtype==ASFD_STREAM_NCURSES_STDIN)
     607             :                 {
     608           1 :                         asfd->do_read=asfd_do_read_ncurses;
     609           1 :                         asfd->do_write=asfd_do_write_ncurses;
     610             :                 }
     611             : #endif
     612             :         }
     613           9 :         asfd->read=asfd_read;
     614           9 :         asfd->simple_loop=asfd_simple_loop;
     615           9 :         asfd->write=asfd_write;
     616           9 :         asfd->write_str=asfd_write_str;
     617             : 
     618           9 :         switch(asfd->streamtype)
     619             :         {
     620             :                 case ASFD_STREAM_STANDARD:
     621           2 :                         asfd->parse_readbuf_specific=parse_readbuf_standard;
     622           2 :                         break;
     623             :                 case ASFD_STREAM_LINEBUF:
     624           6 :                         asfd->parse_readbuf_specific=parse_readbuf_line_buf;
     625           6 :                         break;
     626             : #ifdef HAVE_NCURSES
     627             :                 case ASFD_STREAM_NCURSES_STDIN:
     628           1 :                         asfd->parse_readbuf_specific=parse_readbuf_ncurses;
     629           1 :                         break;
     630             : #endif
     631             :                 default:
     632           0 :                         logp("%s: unknown asfd stream type in %s: %d\n",
     633             :                                 desc, __func__, asfd->streamtype);
     634           0 :                         return -1;
     635             :         }
     636             : 
     637           9 :         if(!(asfd->rbuf=iobuf_alloc())
     638          18 :           || asfd_alloc_buf(asfd, &asfd->readbuf)
     639          18 :           || asfd_alloc_buf(asfd, &asfd->writebuf)
     640           9 :           || !(asfd->desc=get_asfd_desc(desc, asfd->fd))
     641           9 :           || !(asfd->listen=strdup_w(listen, __func__)))
     642             :                 return -1;
     643             :         return 0;
     644             : }
     645             : 
     646         363 : struct asfd *asfd_alloc(void)
     647             : {
     648             :         struct asfd *asfd;
     649         372 :         asfd=(struct asfd *)calloc_w(1, sizeof(struct asfd), __func__);
     650         372 :         if(asfd)
     651         372 :                 asfd->fd=-1;
     652         363 :         return asfd;
     653             : }
     654             : 
     655         372 : void asfd_close(struct asfd *asfd)
     656             : {
     657         372 :         if(!asfd) return;
     658         372 :         if(asfd->ssl && asfd->fd>=0)
     659             :         {
     660           1 :                 set_blocking(asfd->fd);
     661             :                 // I do not think this SSL_shutdown stuff works right.
     662             :                 // Ignore it for now.
     663             : #ifndef HAVE_WIN32
     664           1 :                 signal(SIGPIPE, SIG_IGN);
     665             : #endif
     666           1 :                 if(!SSL_shutdown(asfd->ssl))
     667             :                 {
     668           0 :                         shutdown(asfd->fd, 1);
     669           0 :                         SSL_shutdown(asfd->ssl);
     670             :                 }
     671             :         }
     672         372 :         if(asfd->ssl)
     673             :         {
     674           1 :                 SSL_free(asfd->ssl);
     675           1 :                 asfd->ssl=NULL;
     676             :         }
     677         372 :         close_fd(&asfd->fd);
     678             : }
     679             : 
     680         372 : static void asfd_free_content(struct asfd *asfd)
     681             : {
     682         372 :         asfd_close(asfd);
     683         372 :         iobuf_free(&asfd->rbuf);
     684         372 :         free_w(&asfd->readbuf);
     685         372 :         free_w(&asfd->writebuf);
     686         372 :         free_w(&asfd->desc);
     687         372 :         free_w(&asfd->client);
     688         372 :         free_w(&asfd->listen);
     689         372 :         incoming_free(&asfd->in);
     690         372 :         blist_free(&asfd->blist);
     691         372 : }
     692             : 
     693         374 : void asfd_free(struct asfd **asfd)
     694             : {
     695         374 :         if(!asfd || !*asfd) return;
     696         372 :         asfd_free_content(*asfd);
     697         372 :         free_v((void **)asfd);
     698             : }
     699             : 
     700          10 : static struct asfd *do_setup_asfd(struct async *as,
     701             :         const char *desc, int *fd, const char *listen,
     702             :         SSL *ssl, enum asfd_streamtype streamtype)
     703             : {
     704          10 :         struct asfd *asfd=NULL;
     705             : 
     706          10 :         if(!fd || *fd<0)
     707             :         {
     708           1 :                 logp("Given invalid descriptor in %s\n", __func__);
     709           1 :                 goto error;
     710             :         }
     711             : 
     712           9 :         set_non_blocking(*fd);
     713           9 :         if(!(asfd=asfd_alloc())
     714           9 :           || asfd_init(asfd, desc, as, *fd, listen, ssl, streamtype))
     715             :                 goto error;
     716           9 :         *fd=-1;
     717           9 :         as->asfd_add(as, asfd);
     718           9 :         return asfd;
     719             : error:
     720           1 :         asfd_free(&asfd);
     721           1 :         return NULL;
     722             : }
     723             : 
     724           1 : struct asfd *setup_asfd_ssl(struct async *as,
     725             :         const char *desc, int *fd, SSL *ssl)
     726             : {
     727           1 :         return do_setup_asfd(as, desc, fd, /*listen*/"",
     728             :                 ssl, ASFD_STREAM_STANDARD);
     729             : }
     730             : 
     731           2 : struct asfd *setup_asfd(struct async *as,
     732             :         const char *desc, int *fd, const char *listen)
     733             : {
     734           2 :         return do_setup_asfd(as, desc, fd, listen,
     735             :                 /*ssl*/NULL, ASFD_STREAM_STANDARD);
     736             : }
     737             : 
     738             : static struct asfd *setup_asfd_linebuf(struct async *as,
     739             :         const char *desc, int *fd)
     740             : {
     741           6 :         return do_setup_asfd(as, desc, fd, /*listen*/"",
     742             :                 /*ssl*/NULL, ASFD_STREAM_LINEBUF);
     743             : }
     744             : 
     745           1 : struct asfd *setup_asfd_linebuf_read(struct async *as,
     746             :         const char *desc, int *fd)
     747             : {
     748           3 :         return setup_asfd_linebuf(as, desc, fd);
     749             : }
     750             : 
     751           1 : struct asfd *setup_asfd_linebuf_write(struct async *as,
     752             :         const char *desc, int *fd)
     753             : {
     754             :         struct asfd *asfd;
     755           3 :         if((asfd=setup_asfd_linebuf(as, desc, fd)))
     756           3 :                 asfd->attempt_reads=0;
     757           1 :         return asfd;
     758             : }
     759             : 
     760           0 : static struct asfd *fileno_error(const char *func)
     761             : {
     762           0 :         logp("fileno error in %s: %s\n", func, strerror(errno));
     763           0 :         return NULL;
     764             : }
     765             : 
     766           2 : struct asfd *setup_asfd_stdin(struct async *as)
     767             : {
     768           2 :         int fd=fileno(stdin);
     769           2 :         if(fd<0)
     770           0 :                 return fileno_error(__func__);
     771           2 :         return setup_asfd_linebuf_read(as, "stdin", &fd);
     772             : }
     773             : 
     774           2 : struct asfd *setup_asfd_stdout(struct async *as)
     775             : {
     776           2 :         int fd=fileno(stdout);
     777           2 :         if(fd<0)
     778           0 :                 return fileno_error(__func__);
     779             :         return setup_asfd_linebuf_write(as, "stdout", &fd);
     780             : }
     781             : 
     782           1 : struct asfd *setup_asfd_ncurses_stdin(struct async *as)
     783             : {
     784           1 :         int fd=fileno(stdin);
     785           1 :         if(fd<0)
     786           0 :                 return fileno_error(__func__);
     787           1 :         return do_setup_asfd(as, "stdin", &fd, /*listen*/"",
     788             :                 /*ssl=*/NULL, ASFD_STREAM_NCURSES_STDIN);
     789             : }
     790             : 
     791             : // Want to make sure that we are listening for reads too - this will let us
     792             : // exit promptly if the client was killed.
     793           0 : static int read_and_write(struct asfd *asfd)
     794             : {
     795             :         // Protect against getting stuck in loops where we are trying to
     796             :         // flush buffers, but keep getting the same error.
     797           0 :         if(asfd->as->read_write(asfd->as))
     798             :                 return -1;
     799           0 :         if(!asfd->rbuf->buf) return 0;
     800           0 :         iobuf_log_unexpected(asfd->rbuf, __func__);
     801             :         return -1;
     802             : }
     803             : 
     804           0 : int asfd_flush_asio(struct asfd *asfd)
     805             : {
     806           0 :         while(asfd && asfd->writebuflen>0)
     807             :         {
     808           0 :                 if(asfd->errors)
     809             :                         return -1;
     810           0 :                 if(read_and_write(asfd))
     811             :                         return -1;
     812             :         }
     813             :         return 0;
     814             : }
     815             : 
     816          84 : int asfd_write_wrapper(struct asfd *asfd, struct iobuf *wbuf)
     817             : {
     818             :         while(1)
     819             :         {
     820          84 :                 if(asfd->errors)
     821             :                         return -1;
     822          84 :                 switch(asfd->append_all_to_write_buffer(asfd, wbuf))
     823             :                 {
     824             :                         case APPEND_OK: return 0;
     825             :                         case APPEND_BLOCKED: break;
     826           3 :                         default: return -1;
     827             :                 }
     828           0 :                 if(read_and_write(asfd)) return -1;
     829             :         }
     830             :         return 0;
     831             : }
     832             : 
     833          84 : int asfd_write_wrapper_str(struct asfd *asfd, enum cmd wcmd, const char *wsrc)
     834             : {
     835             :         static struct iobuf wbuf;
     836          84 :         iobuf_from_str(&wbuf, wcmd, (char *)wsrc);
     837          84 :         return asfd_write_wrapper(asfd, &wbuf);
     838             : }
     839             : 

Generated by: LCOV version 1.13