Mercurial > dropbear
comparison common-channel.c @ 1079:acf444bcb115
Fix no-writev fallback
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 02 May 2015 22:47:25 +0800 |
parents | cc6116cc0b5c |
children | c45d65392c1a |
comparison
equal
deleted
inserted
replaced
1078:b3b772646974 | 1079:acf444bcb115 |
---|---|
432 channel->sent_eof = 1; | 432 channel->sent_eof = 1; |
433 | 433 |
434 TRACE(("leave send_msg_channel_eof")) | 434 TRACE(("leave send_msg_channel_eof")) |
435 } | 435 } |
436 | 436 |
437 /* Called to write data out to the local side of the channel. | 437 #ifndef HAVE_WRITEV |
438 Writes the circular buffer contents and also the "moredata" buffer | 438 static void writechannel_fallback(struct Channel* channel, int fd, circbuffer *cbuf, |
439 if not null. Will ignore EAGAIN */ | 439 const unsigned char *UNUSED(moredata), unsigned int *morelen) { |
440 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf, | 440 |
441 unsigned char *circ_p1, *circ_p2; | |
442 unsigned int circ_len1, circ_len2; | |
443 ssize_t written; | |
444 | |
445 if (morelen) { | |
446 /* fallback doesn't consume moredata */ | |
447 *morelen = 0; | |
448 } | |
449 | |
450 /* Write the first portion of the circular buffer */ | |
451 cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2); | |
452 written = write(fd, circ_p1, circ_len1); | |
453 if (written < 0) { | |
454 if (errno != EINTR && errno != EAGAIN) { | |
455 TRACE(("channel IO write error fd %d %s", fd, strerror(errno))) | |
456 close_chan_fd(channel, fd, SHUT_WR); | |
457 } | |
458 } else { | |
459 cbuf_incrread(cbuf, written); | |
460 channel->recvdonelen += written; | |
461 } | |
462 } | |
463 #endif /* !HAVE_WRITEV */ | |
464 | |
465 #ifdef HAVE_WRITEV | |
466 static void writechannel_writev(struct Channel* channel, int fd, circbuffer *cbuf, | |
441 const unsigned char *moredata, unsigned int *morelen) { | 467 const unsigned char *moredata, unsigned int *morelen) { |
442 | 468 |
443 struct iovec iov[3]; | 469 struct iovec iov[3]; |
444 unsigned char *circ_p1, *circ_p2; | 470 unsigned char *circ_p1, *circ_p2; |
445 unsigned int circ_len1, circ_len2; | 471 unsigned int circ_len1, circ_len2; |
446 int io_count = 0; | 472 int io_count = 0; |
447 | 473 |
448 int written; | 474 ssize_t written; |
449 | |
450 TRACE(("enter writechannel fd %d", fd)) | |
451 | 475 |
452 cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2); | 476 cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2); |
453 | 477 |
454 if (circ_len1 > 0) { | 478 if (circ_len1 > 0) { |
455 TRACE(("circ1 %d", circ_len1)) | 479 TRACE(("circ1 %d", circ_len1)) |
500 *morelen = written - cbuf_written; | 524 *morelen = written - cbuf_written; |
501 } | 525 } |
502 channel->recvdonelen += written; | 526 channel->recvdonelen += written; |
503 } | 527 } |
504 | 528 |
505 #if 0 | 529 } |
506 | 530 #endif /* HAVE_WRITEV */ |
507 maxlen = cbuf_readlen(cbuf); | 531 |
508 | 532 /* Called to write data out to the local side of the channel. |
509 /* Write the data out */ | 533 Writes the circular buffer contents and also the "moredata" buffer |
510 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen); | 534 if not null. Will ignore EAGAIN */ |
511 if (len <= 0) { | 535 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf, |
512 TRACE(("errno %d len %d", errno, len)) | 536 const unsigned char *moredata, unsigned int *morelen) { |
513 if (len < 0 && errno != EINTR) { | 537 TRACE(("enter writechannel fd %d", fd)) |
514 close_chan_fd(channel, fd, SHUT_WR); | 538 #ifdef HAVE_WRITEV |
515 } | 539 writechannel_writev(channel, fd, cbuf, moredata, morelen); |
516 TRACE(("leave writechannel: len <= 0")) | 540 #else |
517 return; | 541 writechannel_fallback(channel, fd, cbuf, moredata, morelen); |
518 } | |
519 TRACE(("writechannel wrote %d", len)) | |
520 | |
521 cbuf_incrread(cbuf, len); | |
522 channel->recvdonelen += len; | |
523 #endif | 542 #endif |
524 | 543 |
525 /* Window adjust handling */ | 544 /* Window adjust handling */ |
526 if (channel->recvdonelen >= RECV_WINDOWEXTEND) { | 545 if (channel->recvdonelen >= RECV_WINDOWEXTEND) { |
527 send_msg_channel_window_adjust(channel, channel->recvdonelen); | 546 send_msg_channel_window_adjust(channel, channel->recvdonelen); |
534 dropbear_assert(channel->extrabuf == NULL || | 553 dropbear_assert(channel->extrabuf == NULL || |
535 channel->recvwindow <= cbuf_getavail(channel->extrabuf)); | 554 channel->recvwindow <= cbuf_getavail(channel->extrabuf)); |
536 | 555 |
537 TRACE(("leave writechannel")) | 556 TRACE(("leave writechannel")) |
538 } | 557 } |
558 | |
539 | 559 |
540 /* Set the file descriptors for the main select in session.c | 560 /* Set the file descriptors for the main select in session.c |
541 * This avoid channels which don't have any window available, are closed, etc*/ | 561 * This avoid channels which don't have any window available, are closed, etc*/ |
542 void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) { | 562 void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) { |
543 | 563 |