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

Generated by: LCOV version 1.10