Home | History | Annotate | Download | only in dropbear

Lines Matching refs:Channel

34 #include "channel.h"
40 static void send_msg_channel_open_confirmation(struct Channel* channel,
43 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf);
44 static void send_msg_channel_window_adjust(struct Channel *channel,
46 static void send_msg_channel_data(struct Channel *channel, int isextended);
47 static void send_msg_channel_eof(struct Channel *channel);
48 static void send_msg_channel_close(struct Channel *channel);
49 static void remove_channel(struct Channel *channel);
50 static void delete_channel(struct Channel *channel);
51 static void check_in_progress(struct Channel *channel);
52 static unsigned int write_pending(struct Channel * channel);
53 static void check_close(struct Channel *channel);
54 static void close_chan_fd(struct Channel *channel, int fd, int how);
59 #define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
60 #define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
65 /* may as well create space for a single channel */
66 ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
87 TRACE(("channel %d closing", i))
95 /* Create a new channel entry, send a reply confirm or failure */
99 struct Channel* newchannel(unsigned int remotechan,
103 struct Channel * newchan;
123 ses.channels = (struct Channel**)m_realloc(ses.channels,
124 (ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
135 newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
167 /* Returns the channel structure corresponding to the channel in the current
169 * A valid channel is always returns, it will fail fatally with an unknown
170 * channel */
171 static struct Channel* getchannel_msg(const char* kind) {
178 dropbear_exit("%s for unknown channel %d", kind, chan);
180 dropbear_exit("Unknown channel %d", chan);
186 struct Channel* getchannel() {
193 struct Channel *channel;
196 /* foreach channel */
199 channel = ses.channels[i];
200 if (channel == NULL) {
206 if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
208 send_msg_channel_data(channel, 0);
212 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
213 && FD_ISSET(channel->errfd, readfds)) {
215 send_msg_channel_data(channel, 1);
219 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
220 if (channel->initconn) {
222 check_in_progress(channel);
223 continue; /* Important not to use the channel after
226 writechannel(channel, channel->writefd, channel->writebuf);
230 if (ERRFD_IS_WRITE(channel)
231 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
232 writechannel(channel, channel->errfd, channel->extrabuf);
235 /* handle any channel closing etc */
236 check_close(channel);
248 * stderr of a channel's endpoint. */
249 static unsigned int write_pending(struct Channel * channel) {
251 if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
253 } else if (channel->errfd >= 0 && channel->extrabuf &&
254 cbuf_getused(channel->extrabuf) > 0) {
262 static void check_close(struct Channel *channel) {
265 channel->writefd, channel->readfd,
266 channel->errfd, channel->sent_close, channel->recv_close))
268 cbuf_getused(channel->writebuf),
269 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
271 if (!channel->flushing && channel->type->check_close
272 && channel->type->check_close(channel))
274 channel->flushing = 1;
277 if (channel->recv_close && !write_pending(channel)) {
278 if (!channel->sent_close) {
280 send_msg_channel_close(channel);
282 remove_channel(channel);
286 if (channel->recv_eof && !write_pending(channel)) {
287 close_chan_fd(channel, channel->writefd, SHUT_WR);
292 and if there isn't data available, the channel will get closed. */
293 if (channel->flushing) {
295 if (channel->readfd >= 0 && channel->transwindow > 0) {
297 send_msg_channel_data(channel, 0);
299 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
300 && channel->transwindow > 0) {
302 send_msg_channel_data(channel, 1);
307 if (!channel->sent_eof
308 && channel->readfd == FD_CLOSED
309 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
310 send_msg_channel_eof(channel);
314 if (!channel->sent_close
315 && channel->readfd == FD_CLOSED
316 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
317 && !write_pending(channel)) {
319 send_msg_channel_close(channel);
324 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
325 * it is important that the channel reference isn't used after a call to this
327 static void check_in_progress(struct Channel *channel) {
334 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
336 send_msg_channel_open_failure(channel->remotechan,
338 close(channel->writefd);
339 delete_channel(channel);
342 send_msg_channel_open_confirmation(channel, channel->recvwindow,
343 channel->recvmaxpacket);
344 channel->readfd = channel->writefd;
345 channel->initconn = 0;
351 /* Send the close message and set the channel as closed */
352 static void send_msg_channel_close(struct Channel *channel) {
355 if (channel->type->closehandler) {
356 channel->type->closehandler(channel);
362 buf_putint(ses.writepayload, channel->remotechan);
366 channel->sent_eof = 1;
367 channel->sent_close = 1;
368 close_chan_fd(channel, channel->readfd, SHUT_RD);
369 close_chan_fd(channel, channel->errfd, SHUT_RDWR);
370 close_chan_fd(channel, channel->writefd, SHUT_WR);
375 static void send_msg_channel_eof(struct Channel *channel) {
381 buf_putint(ses.writepayload, channel->remotechan);
385 channel->sent_eof = 1;
390 /* Called to write data out to the local side of the channel.
391 * Only called when we know we can write to a channel, writes as much as
393 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
406 close_chan_fd(channel, fd, SHUT_WR);
414 channel->recvdonelen += len;
417 if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
419 send_msg_channel_window_adjust(channel, channel->recvdonelen);
420 channel->recvwindow += channel->recvdonelen;
421 channel->recvdonelen = 0;
424 dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
425 dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
426 dropbear_assert(channel->extrabuf == NULL ||
427 channel->recvwindow <= cbuf_getavail(channel->extrabuf));
437 struct Channel * channel;
441 channel = ses.channels[i];
442 if (channel == NULL) {
447 if (channel->transwindow > 0) {
449 if (channel->readfd >= 0) {
450 FD_SET(channel->readfd, readfds);
453 if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
454 FD_SET(channel->errfd, readfds);
459 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
460 || channel->initconn) {
461 FD_SET(channel->writefd, writefds);
464 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
465 && cbuf_getused(channel->extrabuf) > 0 ) {
466 FD_SET(channel->errfd, writefds);
469 } /* foreach channel */
477 /* handle the channel EOF event, by closing the channel filedescriptor. The
478 * channel isn't closed yet, it is left until the incoming (from the program
482 struct Channel * channel;
486 channel = getchannel_msg("EOF");
488 channel->recv_eof = 1;
490 check_close(channel);
495 /* Handle channel closure(), respond in kind and close the channels */
498 struct Channel * channel;
502 channel = getchannel_msg("Close");
504 channel->recv_eof = 1;
505 channel->recv_close = 1;
507 check_close(channel);
511 /* Remove a channel entry, this is only executed after both sides have sent
512 * channel close */
513 static void remove_channel(struct Channel * channel) {
516 TRACE(("channel index is %d", channel->index))
518 cbuf_free(channel->writebuf);
519 channel->writebuf = NULL;
521 if (channel->extrabuf) {
522 cbuf_free(channel->extrabuf);
523 channel->extrabuf = NULL;
529 TRACE(("CLOSE writefd %d", channel->writefd))
530 close(channel->writefd);
531 TRACE(("CLOSE readfd %d", channel->readfd))
532 close(channel->readfd);
533 TRACE(("CLOSE errfd %d", channel->errfd))
534 close(channel->errfd);
536 channel->typedata = NULL;
538 delete_channel(channel);
543 /* Remove a channel entry */
544 static void delete_channel(struct Channel *channel) {
546 ses.channels[channel->index] = NULL;
547 m_free(channel);
553 /* Handle channel specific requests, passing off to corresponding handlers
557 struct Channel *channel;
561 channel = getchannel();
563 if (channel->type->reqhandler) {
564 channel->type->reqhandler(channel);
566 send_msg_channel_failure(channel);
575 * chan is the remote channel, isextended is 0 if it is normal data, 1
578 static void send_msg_channel_data(struct Channel *channel, int isextended) {
587 channel->sent_close);
590 fd = channel->errfd;
592 fd = channel->readfd;
597 maxlen = MIN(channel->transwindow, channel->transmaxpacket);
598 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and
610 buf_putint(ses.writepayload, channel->remotechan);
625 close_chan_fd(channel, fd, SHUT_RD);
637 channel->transwindow -= len;
643 if (channel->flushing && len < (ssize_t)maxlen)
645 TRACE(("closing from channel, flushing out."))
646 close_chan_fd(channel, fd, SHUT_RD);
651 /* We receive channel data */
654 struct Channel *channel;
656 channel = getchannel();
658 common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
663 void common_recv_msg_channel_data(struct Channel *channel, int fd,
673 if (channel->recv_eof) {
711 dropbear_assert(channel->recvwindow >= datalen);
712 channel->recvwindow -= datalen;
713 dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
718 /* Increment the outgoing data window for a channel - the remote end limits
723 struct Channel * channel;
726 channel = getchannel();
732 channel->transwindow += incr;
733 channel->transwindow = MIN(channel->transwindow, MAX_TRANS_WINDOW);
737 /* Increment the incoming data window for a channel, and let the remote
739 static void send_msg_channel_window_adjust(struct Channel* channel,
746 buf_putint(ses.writepayload, channel->remotechan);
752 /* Handle a new channel request, performing any channel-type-specific setup */
758 struct Channel *channel;
781 /* Get the channel type. Client and server style invokation will set up a
799 /* create the channel */
800 channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
802 if (channel == NULL) {
807 if (channel->type->inithandler) {
808 ret = channel->type->inithandler(channel);
815 delete_channel(channel);
822 send_msg_channel_open_confirmation(channel, channel->recvwindow,
823 channel->recvmaxpacket);
837 void send_msg_channel_failure(struct Channel *channel) {
843 buf_putint(ses.writepayload, channel->remotechan);
850 void send_msg_channel_success(struct Channel *channel) {
856 buf_putint(ses.writepayload, channel->remotechan);
862 /* Send a channel open failure message, with a corresponding reason
880 /* Confirm a channel open, and let the remote end know what number we've
882 static void send_msg_channel_open_confirmation(struct Channel* channel,
890 buf_putint(ses.writepayload, channel->remotechan);
891 buf_putint(ses.writepayload, channel->index);
900 static void close_chan_fd(struct Channel *channel, int fd, int how) {
904 if (channel->type->sepfds) {
918 if (closeout && (fd == channel->readfd)) {
919 channel->readfd = FD_CLOSED;
921 if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
922 channel->errfd = FD_CLOSED;
925 if (closein && fd == channel->writefd) {
926 channel->writefd = FD_CLOSED;
928 if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
929 channel->errfd = FD_CLOSED;
934 if (channel->type->sepfds && channel->readfd == FD_CLOSED
935 && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
943 /* Create a new channel, and start the open request. This is intended
944 * for X11, agent, tcp forwarding, and should be filled with channel-specific
950 struct Channel* chan;
967 /* now open the channel connection */
980 /* Confirmation that our channel open request (for forwardings) was
984 struct Channel * channel;
989 channel = getchannel();
991 if (!channel->await_open) {
992 dropbear_exit("unexpected channel reply");
994 channel->await_open = 0;
996 channel->remotechan = buf_getint(ses.payload);
997 channel->transwindow = buf_getint(ses.payload);
998 channel->transmaxpacket = buf_getint(ses.payload);
1001 channel->remotechan, channel->index))
1004 if (channel->type->inithandler) {
1005 ret = channel->type->inithandler(channel);
1007 remove_channel(channel);
1016 /* Notification that our channel open request failed */
1019 struct Channel * channel;
1021 channel = getchannel();
1023 if (!channel->await_open) {
1024 dropbear_exit("unexpected channel reply");
1026 channel->await_open = 0;
1028 remove_channel(channel);