LCOV - code coverage report
Current view: top level - src - asfd.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 18 315 5.7 %
Date: 2015-10-31 Functions: 3 28 10.7 %

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

Generated by: LCOV version 1.10