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