LCOV - code coverage report
Current view: top level - src - asfd.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 47 303 15.5 %
Date: 2016-01-03 Functions: 8 31 25.8 %

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

Generated by: LCOV version 1.10