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