1 /* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
4 * Redistribution and use in source and binary forms,
5 * with or without modification, are permitted provided
6 * that the following conditions are met:
8 * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * Neither the name of the copyright holder nor the names
18 * of any other contributors may be used to endorse or
19 * promote products derived from this software without
20 * specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
38 #include "libssh2_priv.h"
43 #ifdef HAVE_INTTYPES_H
48 /* {{{ libssh2_channel_nextid
49 * Determine the next channel ID we can use at our end
52 libssh2_channel_nextid(LIBSSH2_SESSION
* session
)
54 unsigned long id
= session
->next_channel
;
55 LIBSSH2_CHANNEL
*channel
;
57 channel
= session
->channels
.head
;
60 if (channel
->local
.id
> id
) {
61 id
= channel
->local
.id
;
63 channel
= channel
->next
;
66 /* This is a shortcut to avoid waiting for close packets on channels we've forgotten about,
67 * This *could* be a problem if we request and close 4 billion or so channels in too rapid succession
68 * for the remote end to respond, but the worst case scenario is that some data meant for another channel
69 * Gets picked up by the new one.... Pretty unlikely all told...
71 session
->next_channel
= id
+ 1;
72 _libssh2_debug(session
, LIBSSH2_DBG_CONN
, "Allocated new channel ID#%lu",
79 /* {{{ libssh2_channel_locate
80 * Locate a channel pointer by number
83 libssh2_channel_locate(LIBSSH2_SESSION
* session
, unsigned long channel_id
)
85 LIBSSH2_CHANNEL
*channel
= session
->channels
.head
;
87 if (channel
->local
.id
== channel_id
) {
90 channel
= channel
->next
;
98 #define libssh2_channel_add(session, channel) \
100 if ((session)->channels.tail) { \
101 (session)->channels.tail->next = (channel); \
102 (channel)->prev = (session)->channels.tail; \
104 (session)->channels.head = (channel); \
105 (channel)->prev = NULL; \
107 (channel)->next = NULL; \
108 (session)->channels.tail = (channel); \
109 (channel)->session = (session); \
112 /* {{{ libssh2_channel_open_ex
113 * Establish a generic session channel
115 LIBSSH2_API LIBSSH2_CHANNEL
*
116 libssh2_channel_open_ex(LIBSSH2_SESSION
* session
, const char *channel_type
,
117 unsigned int channel_type_len
,
118 unsigned int window_size
, unsigned int packet_size
,
119 const char *message
, unsigned int message_len
)
121 static const unsigned char reply_codes
[3] = {
122 SSH_MSG_CHANNEL_OPEN_CONFIRMATION
,
123 SSH_MSG_CHANNEL_OPEN_FAILURE
,
129 if (session
->open_state
== libssh2_NB_state_idle
) {
130 session
->open_channel
= NULL
;
131 session
->open_packet
= NULL
;
132 session
->open_data
= NULL
;
133 /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) + window_size(4) + packet_size(4) */
134 session
->open_packet_len
= channel_type_len
+ message_len
+ 17;
135 session
->open_local_channel
= libssh2_channel_nextid(session
);
137 /* Zero the whole thing out */
138 memset(&session
->open_packet_requirev_state
, 0,
139 sizeof(session
->open_packet_requirev_state
));
141 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
142 "Opening Channel - win %d pack %d", window_size
,
144 session
->open_channel
=
145 LIBSSH2_ALLOC(session
, sizeof(LIBSSH2_CHANNEL
));
146 if (!session
->open_channel
) {
147 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
148 "Unable to allocate space for channel data", 0);
151 memset(session
->open_channel
, 0, sizeof(LIBSSH2_CHANNEL
));
153 session
->open_channel
->channel_type_len
= channel_type_len
;
154 session
->open_channel
->channel_type
=
155 LIBSSH2_ALLOC(session
, channel_type_len
);
156 if (!session
->open_channel
->channel_type
) {
157 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
158 "Failed allocating memory for channel type name", 0);
159 LIBSSH2_FREE(session
, session
->open_channel
);
160 session
->open_channel
= NULL
;
163 memcpy(session
->open_channel
->channel_type
, channel_type
,
166 /* REMEMBER: local as in locally sourced */
167 session
->open_channel
->local
.id
= session
->open_local_channel
;
168 session
->open_channel
->remote
.window_size
= window_size
;
169 session
->open_channel
->remote
.window_size_initial
= window_size
;
170 session
->open_channel
->remote
.packet_size
= packet_size
;
172 libssh2_channel_add(session
, session
->open_channel
);
174 s
= session
->open_packet
=
175 LIBSSH2_ALLOC(session
, session
->open_packet_len
);
176 if (!session
->open_packet
) {
177 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
178 "Unable to allocate temporary space for packet", 0);
181 *(s
++) = SSH_MSG_CHANNEL_OPEN
;
182 libssh2_htonu32(s
, channel_type_len
);
185 memcpy(s
, channel_type
, channel_type_len
);
186 s
+= channel_type_len
;
188 libssh2_htonu32(s
, session
->open_local_channel
);
191 libssh2_htonu32(s
, window_size
);
194 libssh2_htonu32(s
, packet_size
);
197 if (message
&& message_len
) {
198 memcpy(s
, message
, message_len
);
202 session
->open_state
= libssh2_NB_state_created
;
205 if (session
->open_state
== libssh2_NB_state_created
) {
206 rc
= libssh2_packet_write(session
, session
->open_packet
,
207 session
->open_packet_len
);
208 if (rc
== PACKET_EAGAIN
) {
209 libssh2_error(session
, LIBSSH2_ERROR_EAGAIN
,
210 "Would block sending channel-open request", 0);
213 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
214 "Unable to send channel-open request", 0);
218 session
->open_state
= libssh2_NB_state_sent
;
221 if (session
->open_state
== libssh2_NB_state_sent
) {
222 rc
= libssh2_packet_requirev_ex(session
, reply_codes
,
224 &session
->open_data_len
, 1,
225 session
->open_packet
+ 5 +
227 &session
->open_packet_requirev_state
);
228 if (rc
== PACKET_EAGAIN
) {
229 libssh2_error(session
, LIBSSH2_ERROR_EAGAIN
, "Would block", 0);
235 if (session
->open_data
[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION
) {
236 session
->open_channel
->remote
.id
=
237 libssh2_ntohu32(session
->open_data
+ 5);
238 session
->open_channel
->local
.window_size
=
239 libssh2_ntohu32(session
->open_data
+ 9);
240 session
->open_channel
->local
.window_size_initial
=
241 libssh2_ntohu32(session
->open_data
+ 9);
242 session
->open_channel
->local
.packet_size
=
243 libssh2_ntohu32(session
->open_data
+ 13);
244 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
245 "Connection Established - ID: %lu/%lu win: %lu/%lu pack: %lu/%lu",
246 session
->open_channel
->local
.id
,
247 session
->open_channel
->remote
.id
,
248 session
->open_channel
->local
.window_size
,
249 session
->open_channel
->remote
.window_size
,
250 session
->open_channel
->local
.packet_size
,
251 session
->open_channel
->remote
.packet_size
);
252 LIBSSH2_FREE(session
, session
->open_packet
);
253 session
->open_packet
= NULL
;
254 LIBSSH2_FREE(session
, session
->open_data
);
255 session
->open_data
= NULL
;
257 session
->open_state
= libssh2_NB_state_idle
;
258 return session
->open_channel
;
261 if (session
->open_data
[0] == SSH_MSG_CHANNEL_OPEN_FAILURE
) {
262 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_FAILURE
,
263 "Channel open failure", 0);
269 if (session
->open_data
) {
270 LIBSSH2_FREE(session
, session
->open_data
);
271 session
->open_data
= NULL
;
273 if (session
->open_packet
) {
274 LIBSSH2_FREE(session
, session
->open_packet
);
275 session
->open_packet
= NULL
;
277 if (session
->open_channel
) {
278 unsigned char channel_id
[4];
279 LIBSSH2_FREE(session
, session
->open_channel
->channel_type
);
281 if (session
->open_channel
->next
) {
282 session
->open_channel
->next
->prev
= session
->open_channel
->prev
;
284 if (session
->open_channel
->prev
) {
285 session
->open_channel
->prev
->next
= session
->open_channel
->next
;
287 if (session
->channels
.head
== session
->open_channel
) {
288 session
->channels
.head
= session
->open_channel
->next
;
290 if (session
->channels
.tail
== session
->open_channel
) {
291 session
->channels
.tail
= session
->open_channel
->prev
;
294 /* Clear out packets meant for this channel */
295 libssh2_htonu32(channel_id
, session
->open_channel
->local
.id
);
296 while ((libssh2_packet_ask_ex
297 (session
, SSH_MSG_CHANNEL_DATA
, &session
->open_data
,
298 &session
->open_data_len
, 1, channel_id
, 4, 0) >= 0)
300 (libssh2_packet_ask_ex
301 (session
, SSH_MSG_CHANNEL_EXTENDED_DATA
, &session
->open_data
,
302 &session
->open_data_len
, 1, channel_id
, 4, 0) >= 0)) {
303 LIBSSH2_FREE(session
, session
->open_data
);
304 session
->open_data
= NULL
;
307 /* Free any state variables still holding data */
308 if (session
->open_channel
->write_packet
) {
309 LIBSSH2_FREE(session
, session
->open_channel
->write_packet
);
310 session
->open_channel
->write_packet
= NULL
;
313 LIBSSH2_FREE(session
, session
->open_channel
);
314 session
->open_channel
= NULL
;
317 session
->open_state
= libssh2_NB_state_idle
;
323 /* {{{ libssh2_channel_direct_tcpip_ex
324 * Tunnel TCP/IP connect through the SSH session to direct host/port
326 LIBSSH2_API LIBSSH2_CHANNEL
*
327 libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION
* session
, const char *host
,
328 int port
, const char *shost
, int sport
)
330 LIBSSH2_CHANNEL
*channel
;
333 if (session
->direct_state
== libssh2_NB_state_idle
) {
334 session
->direct_host_len
= strlen(host
);
335 session
->direct_shost_len
= strlen(shost
);
336 /* host_len(4) + port(4) + shost_len(4) + sport(4) */
337 session
->direct_message_len
=
338 session
->direct_host_len
+ session
->direct_shost_len
+ 16;
340 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
341 "Requesting direct-tcpip session to from %s:%d to %s:%d",
342 shost
, sport
, host
, port
);
344 s
= session
->direct_message
=
345 LIBSSH2_ALLOC(session
, session
->direct_message_len
);
346 if (!session
->direct_message
) {
347 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
348 "Unable to allocate memory for direct-tcpip connection",
352 libssh2_htonu32(s
, session
->direct_host_len
);
354 memcpy(s
, host
, session
->direct_host_len
);
355 s
+= session
->direct_host_len
;
356 libssh2_htonu32(s
, port
);
359 libssh2_htonu32(s
, session
->direct_shost_len
);
361 memcpy(s
, shost
, session
->direct_shost_len
);
362 s
+= session
->direct_shost_len
;
363 libssh2_htonu32(s
, sport
);
366 session
->direct_state
= libssh2_NB_state_created
;
370 libssh2_channel_open_ex(session
, "direct-tcpip",
371 sizeof("direct-tcpip") - 1,
372 LIBSSH2_CHANNEL_WINDOW_DEFAULT
,
373 LIBSSH2_CHANNEL_PACKET_DEFAULT
,
374 (char *) session
->direct_message
,
375 session
->direct_message_len
);
377 if (libssh2_session_last_errno(session
) == LIBSSH2_ERROR_EAGAIN
) {
378 /* The error code is still set to LIBSSH2_ERROR_EAGAIN */
381 LIBSSH2_FREE(session
, session
->direct_message
);
382 session
->direct_message
= NULL
;
387 LIBSSH2_FREE(session
, session
->direct_message
);
388 session
->direct_message
= NULL
;
395 /* {{{ libssh2_channel_forward_listen_ex
396 * Bind a port on the remote host and listen for connections
398 LIBSSH2_API LIBSSH2_LISTENER
*
399 libssh2_channel_forward_listen_ex(LIBSSH2_SESSION
* session
, const char *host
,
400 int port
, int *bound_port
, int queue_maxsize
)
402 unsigned char *s
, *data
;
403 static const unsigned char reply_codes
[3] =
404 { SSH_MSG_REQUEST_SUCCESS
, SSH_MSG_REQUEST_FAILURE
, 0 };
405 unsigned long data_len
;
408 if (session
->fwdLstn_state
== libssh2_NB_state_idle
) {
409 session
->fwdLstn_host_len
=
410 (host ?
strlen(host
) : (sizeof("0.0.0.0") - 1));
411 /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */
412 session
->fwdLstn_packet_len
=
413 session
->fwdLstn_host_len
+ (sizeof("tcpip-forward") - 1) + 14;
415 /* Zero the whole thing out */
416 memset(&session
->fwdLstn_packet_requirev_state
, 0,
417 sizeof(session
->fwdLstn_packet_requirev_state
));
419 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
420 "Requesting tcpip-forward session for %s:%d", host
,
423 s
= session
->fwdLstn_packet
=
424 LIBSSH2_ALLOC(session
, session
->fwdLstn_packet_len
);
425 if (!session
->fwdLstn_packet
) {
426 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
427 "Unable to allocate memeory for setenv packet", 0);
431 *(s
++) = SSH_MSG_GLOBAL_REQUEST
;
432 libssh2_htonu32(s
, sizeof("tcpip-forward") - 1);
434 memcpy(s
, "tcpip-forward", sizeof("tcpip-forward") - 1);
435 s
+= sizeof("tcpip-forward") - 1;
436 *(s
++) = 0x01; /* want_reply */
438 libssh2_htonu32(s
, session
->fwdLstn_host_len
);
440 memcpy(s
, host ? host
: "0.0.0.0", session
->fwdLstn_host_len
);
441 s
+= session
->fwdLstn_host_len
;
442 libssh2_htonu32(s
, port
);
445 session
->fwdLstn_state
= libssh2_NB_state_created
;
448 if (session
->fwdLstn_state
== libssh2_NB_state_created
) {
449 rc
= libssh2_packet_write(session
, session
->fwdLstn_packet
,
450 session
->fwdLstn_packet_len
);
451 if (rc
== PACKET_EAGAIN
) {
452 libssh2_error(session
, LIBSSH2_ERROR_EAGAIN
,
453 "Would block sending global-request packet for forward listen request",
457 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
458 "Unable to send global-request packet for forward listen request",
460 LIBSSH2_FREE(session
, session
->fwdLstn_packet
);
461 session
->fwdLstn_packet
= NULL
;
462 session
->fwdLstn_state
= libssh2_NB_state_idle
;
465 LIBSSH2_FREE(session
, session
->fwdLstn_packet
);
466 session
->fwdLstn_packet
= NULL
;
468 session
->fwdLstn_state
= libssh2_NB_state_sent
;
471 if (session
->fwdLstn_state
== libssh2_NB_state_sent
) {
472 rc
= libssh2_packet_requirev_ex(session
, reply_codes
, &data
, &data_len
,
475 fwdLstn_packet_requirev_state
);
476 if (rc
== PACKET_EAGAIN
) {
477 libssh2_error(session
, LIBSSH2_ERROR_EAGAIN
, "Would block", 0);
480 libssh2_error(session
, LIBSSH2_ERROR_PROTO
, "Unknown", 0);
481 session
->fwdLstn_state
= libssh2_NB_state_idle
;
485 if (data
[0] == SSH_MSG_REQUEST_SUCCESS
) {
486 LIBSSH2_LISTENER
*listener
;
488 listener
= LIBSSH2_ALLOC(session
, sizeof(LIBSSH2_LISTENER
));
490 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
491 "Unable to allocate memory for listener queue",
493 LIBSSH2_FREE(session
, data
);
494 session
->fwdLstn_state
= libssh2_NB_state_idle
;
497 memset(listener
, 0, sizeof(LIBSSH2_LISTENER
));
498 listener
->session
= session
;
500 LIBSSH2_ALLOC(session
, session
->fwdLstn_host_len
+ 1);
501 if (!listener
->host
) {
502 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
503 "Unable to allocate memory for listener queue",
505 LIBSSH2_FREE(session
, listener
);
506 LIBSSH2_FREE(session
, data
);
507 session
->fwdLstn_state
= libssh2_NB_state_idle
;
510 memcpy(listener
->host
, host ? host
: "0.0.0.0",
511 session
->fwdLstn_host_len
);
512 listener
->host
[session
->fwdLstn_host_len
] = 0;
513 if (data_len
>= 5 && !port
) {
514 listener
->port
= libssh2_ntohu32(data
+ 1);
515 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
516 "Dynamic tcpip-forward port allocated: %d",
519 listener
->port
= port
;
522 listener
->queue_size
= 0;
523 listener
->queue_maxsize
= queue_maxsize
;
525 listener
->next
= session
->listeners
;
526 listener
->prev
= NULL
;
527 if (session
->listeners
) {
528 session
->listeners
->prev
= listener
;
530 session
->listeners
= listener
;
533 *bound_port
= listener
->port
;
536 LIBSSH2_FREE(session
, data
);
537 session
->fwdLstn_state
= libssh2_NB_state_idle
;
541 if (data
[0] == SSH_MSG_REQUEST_FAILURE
) {
542 LIBSSH2_FREE(session
, data
);
543 libssh2_error(session
, LIBSSH2_ERROR_REQUEST_DENIED
,
544 "Unable to complete request for forward-listen", 0);
545 session
->fwdLstn_state
= libssh2_NB_state_idle
;
550 session
->fwdLstn_state
= libssh2_NB_state_idle
;
557 /* {{{ libssh2_channel_forward_cancel
558 * Stop listening on a remote port and free the listener
559 * Toss out any pending (un-accept()ed) connections
561 * Return 0 on success, PACKET_EAGAIN if would block, -1 on error
564 libssh2_channel_forward_cancel(LIBSSH2_LISTENER
* listener
)
566 LIBSSH2_SESSION
*session
= listener
->session
;
567 LIBSSH2_CHANNEL
*queued
= listener
->queue
;
568 unsigned char *packet
, *s
;
569 unsigned long host_len
= strlen(listener
->host
);
570 /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */
571 unsigned long packet_len
=
572 host_len
+ 14 + sizeof("cancel-tcpip-forward") - 1;
575 if (listener
->chanFwdCncl_state
== libssh2_NB_state_idle
) {
576 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
577 "Cancelling tcpip-forward session for %s:%d",
578 listener
->host
, listener
->port
);
580 s
= packet
= LIBSSH2_ALLOC(session
, packet_len
);
582 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
583 "Unable to allocate memeory for setenv packet", 0);
587 *(s
++) = SSH_MSG_GLOBAL_REQUEST
;
588 libssh2_htonu32(s
, sizeof("cancel-tcpip-forward") - 1);
590 memcpy(s
, "cancel-tcpip-forward", sizeof("cancel-tcpip-forward") - 1);
591 s
+= sizeof("cancel-tcpip-forward") - 1;
592 *(s
++) = 0x00; /* want_reply */
594 libssh2_htonu32(s
, host_len
);
596 memcpy(s
, listener
->host
, host_len
);
598 libssh2_htonu32(s
, listener
->port
);
601 listener
->chanFwdCncl_state
= libssh2_NB_state_created
;
603 packet
= listener
->chanFwdCncl_data
;
606 if (listener
->chanFwdCncl_state
== libssh2_NB_state_created
) {
607 rc
= libssh2_packet_write(session
, packet
, packet_len
);
608 if (rc
== PACKET_EAGAIN
) {
609 listener
->chanFwdCncl_data
= packet
;
611 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
612 "Unable to send global-request packet for forward listen request",
614 LIBSSH2_FREE(session
, packet
);
615 listener
->chanFwdCncl_state
= libssh2_NB_state_idle
;
618 LIBSSH2_FREE(session
, packet
);
620 listener
->chanFwdCncl_state
= libssh2_NB_state_sent
;
624 LIBSSH2_CHANNEL
*next
= queued
->next
;
626 rc
= libssh2_channel_free(queued
);
627 if (rc
== PACKET_EAGAIN
) {
628 return PACKET_EAGAIN
;
632 LIBSSH2_FREE(session
, listener
->host
);
634 if (listener
->next
) {
635 listener
->next
->prev
= listener
->prev
;
637 if (listener
->prev
) {
638 listener
->prev
->next
= listener
->next
;
640 session
->listeners
= listener
->next
;
643 LIBSSH2_FREE(session
, listener
);
645 listener
->chanFwdCncl_state
= libssh2_NB_state_idle
;
652 /* {{{ libssh2_channel_forward_accept
653 * Accept a connection
655 LIBSSH2_API LIBSSH2_CHANNEL
*
656 libssh2_channel_forward_accept(LIBSSH2_LISTENER
* listener
)
661 rc
= libssh2_packet_read(listener
->session
);
662 if (rc
== PACKET_EAGAIN
) {
663 libssh2_error(listener
->session
, LIBSSH2_ERROR_EAGAIN
,
664 "Would block waiting for packet", 0);
669 if (listener
->queue
) {
670 LIBSSH2_SESSION
*session
= listener
->session
;
671 LIBSSH2_CHANNEL
*channel
;
673 channel
= listener
->queue
;
675 listener
->queue
= listener
->queue
->next
;
676 if (listener
->queue
) {
677 listener
->queue
->prev
= NULL
;
680 channel
->prev
= NULL
;
681 channel
->next
= session
->channels
.head
;
682 session
->channels
.head
= channel
;
685 channel
->next
->prev
= channel
;
687 session
->channels
.tail
= channel
;
689 listener
->queue_size
--;
699 /* {{{ libssh2_channel_setenv_ex
700 * Set an environment variable prior to requesting a shell/program/subsystem
703 libssh2_channel_setenv_ex(LIBSSH2_CHANNEL
* channel
, const char *varname
,
704 unsigned int varname_len
, const char *value
,
705 unsigned int value_len
)
707 LIBSSH2_SESSION
*session
= channel
->session
;
708 unsigned char *s
, *data
;
709 static const unsigned char reply_codes
[3] =
710 { SSH_MSG_CHANNEL_SUCCESS
, SSH_MSG_CHANNEL_FAILURE
, 0 };
711 unsigned long data_len
;
714 if (channel
->setenv_state
== libssh2_NB_state_idle
) {
715 /* 21 = packet_type(1) + channel_id(4) + request_len(4) +
716 * request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */
717 channel
->setenv_packet_len
= varname_len
+ value_len
+ 21;
719 /* Zero the whole thing out */
720 memset(&channel
->setenv_packet_requirev_state
, 0,
721 sizeof(channel
->setenv_packet_requirev_state
));
723 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
724 "Setting remote environment variable: %s=%s on channel %lu/%lu",
725 varname
, value
, channel
->local
.id
, channel
->remote
.id
);
727 s
= channel
->setenv_packet
=
728 LIBSSH2_ALLOC(session
, channel
->setenv_packet_len
);
729 if (!channel
->setenv_packet
) {
730 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
731 "Unable to allocate memeory for setenv packet", 0);
735 *(s
++) = SSH_MSG_CHANNEL_REQUEST
;
736 libssh2_htonu32(s
, channel
->remote
.id
);
738 libssh2_htonu32(s
, sizeof("env") - 1);
740 memcpy(s
, "env", sizeof("env") - 1);
741 s
+= sizeof("env") - 1;
745 libssh2_htonu32(s
, varname_len
);
747 memcpy(s
, varname
, varname_len
);
750 libssh2_htonu32(s
, value_len
);
752 memcpy(s
, value
, value_len
);
755 channel
->setenv_state
= libssh2_NB_state_created
;
758 if (channel
->setenv_state
== libssh2_NB_state_created
) {
759 rc
= libssh2_packet_write(session
, channel
->setenv_packet
,
760 channel
->setenv_packet_len
);
761 if (rc
== PACKET_EAGAIN
) {
762 return PACKET_EAGAIN
;
764 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
765 "Unable to send channel-request packet for setenv request",
767 LIBSSH2_FREE(session
, channel
->setenv_packet
);
768 channel
->setenv_packet
= NULL
;
769 channel
->setenv_state
= libssh2_NB_state_idle
;
772 LIBSSH2_FREE(session
, channel
->setenv_packet
);
773 channel
->setenv_packet
= NULL
;
775 libssh2_htonu32(channel
->setenv_local_channel
, channel
->local
.id
);
777 channel
->setenv_state
= libssh2_NB_state_sent
;
780 if (channel
->setenv_state
== libssh2_NB_state_sent
) {
781 rc
= libssh2_packet_requirev_ex(session
, reply_codes
, &data
, &data_len
,
782 1, channel
->setenv_local_channel
, 4,
784 setenv_packet_requirev_state
);
785 if (rc
== PACKET_EAGAIN
) {
786 return PACKET_EAGAIN
;
789 channel
->setenv_state
= libssh2_NB_state_idle
;
793 if (data
[0] == SSH_MSG_CHANNEL_SUCCESS
) {
794 LIBSSH2_FREE(session
, data
);
795 channel
->setenv_state
= libssh2_NB_state_idle
;
799 LIBSSH2_FREE(session
, data
);
802 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED
,
803 "Unable to complete request for channel-setenv", 0);
804 channel
->setenv_state
= libssh2_NB_state_idle
;
810 /* {{{ libssh2_channel_request_pty_ex
811 * Duh... Request a PTY
814 libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL
* channel
, const char *term
,
815 unsigned int term_len
, const char *modes
,
816 unsigned int modes_len
, int width
, int height
,
817 int width_px
, int height_px
)
819 LIBSSH2_SESSION
*session
= channel
->session
;
820 unsigned char *s
, *data
;
821 static const unsigned char reply_codes
[3] =
822 { SSH_MSG_CHANNEL_SUCCESS
, SSH_MSG_CHANNEL_FAILURE
, 0 };
823 unsigned long data_len
;
826 if (channel
->reqPTY_state
== libssh2_NB_state_idle
) {
827 /* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) +
828 * want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) +
829 * height_px(4) + modes_len(4) */
830 channel
->reqPTY_packet_len
= term_len
+ modes_len
+ 41;
832 /* Zero the whole thing out */
833 memset(&channel
->reqPTY_packet_requirev_state
, 0,
834 sizeof(channel
->reqPTY_packet_requirev_state
));
836 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
837 "Allocating tty on channel %lu/%lu", channel
->local
.id
,
840 s
= channel
->reqPTY_packet
=
841 LIBSSH2_ALLOC(session
, channel
->reqPTY_packet_len
);
842 if (!channel
->reqPTY_packet
) {
843 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
844 "Unable to allocate memory for pty-request", 0);
848 *(s
++) = SSH_MSG_CHANNEL_REQUEST
;
849 libssh2_htonu32(s
, channel
->remote
.id
);
851 libssh2_htonu32(s
, sizeof("pty-req") - 1);
853 memcpy(s
, "pty-req", sizeof("pty-req") - 1);
854 s
+= sizeof("pty-req") - 1;
858 libssh2_htonu32(s
, term_len
);
861 memcpy(s
, term
, term_len
);
865 libssh2_htonu32(s
, width
);
867 libssh2_htonu32(s
, height
);
869 libssh2_htonu32(s
, width_px
);
871 libssh2_htonu32(s
, height_px
);
874 libssh2_htonu32(s
, modes_len
);
877 memcpy(s
, modes
, modes_len
);
881 channel
->reqPTY_state
= libssh2_NB_state_created
;
884 if (channel
->reqPTY_state
== libssh2_NB_state_created
) {
885 rc
= libssh2_packet_write(session
, channel
->reqPTY_packet
,
886 channel
->reqPTY_packet_len
);
887 if (rc
== PACKET_EAGAIN
) {
888 return PACKET_EAGAIN
;
890 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
891 "Unable to send pty-request packet", 0);
892 LIBSSH2_FREE(session
, channel
->reqPTY_packet
);
893 channel
->reqPTY_packet
= NULL
;
894 channel
->reqPTY_state
= libssh2_NB_state_idle
;
897 LIBSSH2_FREE(session
, channel
->reqPTY_packet
);
898 channel
->reqPTY_packet
= NULL
;
900 libssh2_htonu32(channel
->reqPTY_local_channel
, channel
->local
.id
);
902 channel
->reqPTY_state
= libssh2_NB_state_sent
;
905 if (channel
->reqPTY_state
== libssh2_NB_state_sent
) {
906 rc
= libssh2_packet_requirev_ex(session
, reply_codes
, &data
, &data_len
,
907 1, channel
->reqPTY_local_channel
, 4,
909 reqPTY_packet_requirev_state
);
910 if (rc
== PACKET_EAGAIN
) {
911 return PACKET_EAGAIN
;
913 channel
->reqPTY_state
= libssh2_NB_state_idle
;
917 if (data
[0] == SSH_MSG_CHANNEL_SUCCESS
) {
918 LIBSSH2_FREE(session
, data
);
919 channel
->reqPTY_state
= libssh2_NB_state_idle
;
924 LIBSSH2_FREE(session
, data
);
925 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED
,
926 "Unable to complete request for channel request-pty", 0);
927 channel
->reqPTY_state
= libssh2_NB_state_idle
;
933 /* Keep this an even number */
934 #define LIBSSH2_X11_RANDOM_COOKIE_LEN 32
936 /* {{{ libssh2_channel_x11_req_ex
937 * Request X11 forwarding
940 libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL
* channel
, int single_connection
,
941 const char *auth_proto
, const char *auth_cookie
,
944 LIBSSH2_SESSION
*session
= channel
->session
;
945 unsigned char *s
, *data
;
946 static const unsigned char reply_codes
[3] =
947 { SSH_MSG_CHANNEL_SUCCESS
, SSH_MSG_CHANNEL_FAILURE
, 0 };
948 unsigned long data_len
;
949 unsigned long proto_len
=
950 auth_proto ?
strlen(auth_proto
) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
951 unsigned long cookie_len
=
952 auth_cookie ?
strlen(auth_cookie
) : LIBSSH2_X11_RANDOM_COOKIE_LEN
;
955 if (channel
->reqX11_state
== libssh2_NB_state_idle
) {
956 /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) +
957 * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) +
959 channel
->reqX11_packet_len
= proto_len
+ cookie_len
+ 30;
961 /* Zero the whole thing out */
962 memset(&channel
->reqX11_packet_requirev_state
, 0,
963 sizeof(channel
->reqX11_packet_requirev_state
));
965 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
966 "Requesting x11-req for channel %lu/%lu: single=%d proto=%s cookie=%s screen=%d",
967 channel
->local
.id
, channel
->remote
.id
,
969 auth_proto ? auth_proto
: "MIT-MAGIC-COOKIE-1",
970 auth_cookie ? auth_cookie
: "<random>", screen_number
);
972 s
= channel
->reqX11_packet
=
973 LIBSSH2_ALLOC(session
, channel
->reqX11_packet_len
);
974 if (!channel
->reqX11_packet
) {
975 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
976 "Unable to allocate memory for pty-request", 0);
980 *(s
++) = SSH_MSG_CHANNEL_REQUEST
;
981 libssh2_htonu32(s
, channel
->remote
.id
);
983 libssh2_htonu32(s
, sizeof("x11-req") - 1);
985 memcpy(s
, "x11-req", sizeof("x11-req") - 1);
986 s
+= sizeof("x11-req") - 1;
988 *(s
++) = 0x01; /* want_reply */
989 *(s
++) = single_connection ?
0x01 : 0x00;
991 libssh2_htonu32(s
, proto_len
);
993 memcpy(s
, auth_proto ? auth_proto
: "MIT-MAGIC-COOKIE-1", proto_len
);
996 libssh2_htonu32(s
, cookie_len
);
999 memcpy(s
, auth_cookie
, cookie_len
);
1002 unsigned char buffer
[LIBSSH2_X11_RANDOM_COOKIE_LEN
/ 2];
1004 libssh2_random(buffer
, LIBSSH2_X11_RANDOM_COOKIE_LEN
/ 2);
1005 for(i
= 0; i
< (LIBSSH2_X11_RANDOM_COOKIE_LEN
/ 2); i
++) {
1006 snprintf((char *) s
+ (i
* 2), 2, "%02X", buffer
[i
]);
1011 libssh2_htonu32(s
, screen_number
);
1014 channel
->reqX11_state
= libssh2_NB_state_created
;
1017 if (channel
->reqX11_state
== libssh2_NB_state_created
) {
1018 rc
= libssh2_packet_write(session
, channel
->reqX11_packet
,
1019 channel
->reqX11_packet_len
);
1020 if (rc
== PACKET_EAGAIN
) {
1021 return PACKET_EAGAIN
;
1024 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1025 "Unable to send x11-req packet", 0);
1026 LIBSSH2_FREE(session
, channel
->reqX11_packet
);
1027 channel
->reqX11_packet
= NULL
;
1028 channel
->reqX11_state
= libssh2_NB_state_idle
;
1031 LIBSSH2_FREE(session
, channel
->reqX11_packet
);
1032 channel
->reqX11_packet
= NULL
;
1034 libssh2_htonu32(channel
->reqX11_local_channel
, channel
->local
.id
);
1036 channel
->reqX11_state
= libssh2_NB_state_sent
;
1039 if (channel
->reqX11_state
== libssh2_NB_state_sent
) {
1040 rc
= libssh2_packet_requirev_ex(session
, reply_codes
, &data
, &data_len
,
1041 1, channel
->reqX11_local_channel
, 4,
1043 reqX11_packet_requirev_state
);
1044 if (rc
== PACKET_EAGAIN
) {
1045 return PACKET_EAGAIN
;
1047 channel
->reqX11_state
= libssh2_NB_state_idle
;
1051 if (data
[0] == SSH_MSG_CHANNEL_SUCCESS
) {
1052 LIBSSH2_FREE(session
, data
);
1053 channel
->reqX11_state
= libssh2_NB_state_idle
;
1058 LIBSSH2_FREE(session
, data
);
1059 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED
,
1060 "Unable to complete request for channel x11-req", 0);
1066 /* {{{ libssh2_channel_process_startup
1067 * Primitive for libssh2_channel_(shell|exec|subsystem)
1070 libssh2_channel_process_startup(LIBSSH2_CHANNEL
* channel
, const char *request
,
1071 unsigned int request_len
, const char *message
,
1072 unsigned int message_len
)
1074 LIBSSH2_SESSION
*session
= channel
->session
;
1075 unsigned char *s
, *data
;
1076 static const unsigned char reply_codes
[3] =
1077 { SSH_MSG_CHANNEL_SUCCESS
, SSH_MSG_CHANNEL_FAILURE
, 0 };
1078 unsigned long data_len
;
1081 if (channel
->process_state
== libssh2_NB_state_idle
) {
1082 /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
1083 channel
->process_packet_len
= request_len
+ 10;
1085 /* Zero the whole thing out */
1086 memset(&channel
->process_packet_requirev_state
, 0,
1087 sizeof(channel
->process_packet_requirev_state
));
1090 channel
->process_packet_len
+= message_len
+ 4;
1093 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1094 "starting request(%s) on channel %lu/%lu, message=%s",
1095 request
, channel
->local
.id
, channel
->remote
.id
,
1097 s
= channel
->process_packet
=
1098 LIBSSH2_ALLOC(session
, channel
->process_packet_len
);
1099 if (!channel
->process_packet
) {
1100 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1101 "Unable to allocate memory for channel-process request",
1106 *(s
++) = SSH_MSG_CHANNEL_REQUEST
;
1107 libssh2_htonu32(s
, channel
->remote
.id
);
1109 libssh2_htonu32(s
, request_len
);
1111 memcpy(s
, request
, request_len
);
1117 libssh2_htonu32(s
, message_len
);
1119 memcpy(s
, message
, message_len
);
1123 channel
->process_state
= libssh2_NB_state_created
;
1126 if (channel
->process_state
== libssh2_NB_state_created
) {
1127 rc
= libssh2_packet_write(session
, channel
->process_packet
,
1128 channel
->process_packet_len
);
1129 if (rc
== PACKET_EAGAIN
) {
1130 return PACKET_EAGAIN
;
1132 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1133 "Unable to send channel request", 0);
1134 LIBSSH2_FREE(session
, channel
->process_packet
);
1135 channel
->process_packet
= NULL
;
1136 channel
->process_state
= libssh2_NB_state_idle
;
1139 LIBSSH2_FREE(session
, channel
->process_packet
);
1140 channel
->process_packet
= NULL
;
1142 libssh2_htonu32(channel
->process_local_channel
, channel
->local
.id
);
1144 channel
->process_state
= libssh2_NB_state_sent
;
1147 if (channel
->process_state
== libssh2_NB_state_sent
) {
1148 rc
= libssh2_packet_requirev_ex(session
, reply_codes
, &data
, &data_len
,
1149 1, channel
->process_local_channel
, 4,
1151 process_packet_requirev_state
);
1152 if (rc
== PACKET_EAGAIN
) {
1153 return PACKET_EAGAIN
;
1155 channel
->process_state
= libssh2_NB_state_idle
;
1159 if (data
[0] == SSH_MSG_CHANNEL_SUCCESS
) {
1160 LIBSSH2_FREE(session
, data
);
1161 channel
->process_state
= libssh2_NB_state_idle
;
1166 LIBSSH2_FREE(session
, data
);
1167 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED
,
1168 "Unable to complete request for channel-process-startup", 0);
1169 channel
->process_state
= libssh2_NB_state_idle
;
1175 /* {{{ libssh2_channel_set_blocking
1176 * Set a channel's blocking mode on or off, similar to a socket's
1177 * fcntl(fd, F_SETFL, O_NONBLOCK); type command
1180 libssh2_channel_set_blocking(LIBSSH2_CHANNEL
* channel
, int blocking
)
1182 (void) _libssh2_session_set_blocking(channel
->session
, blocking
);
1187 /* {{{ libssh2_channel_flush_ex
1188 * Flush data from one (or all) stream
1189 * Returns number of bytes flushed, or -1 on failure
1192 libssh2_channel_flush_ex(LIBSSH2_CHANNEL
* channel
, int streamid
)
1194 LIBSSH2_PACKET
*packet
= channel
->session
->packets
.head
;
1196 if (channel
->flush_state
== libssh2_NB_state_idle
) {
1197 channel
->flush_refund_bytes
= 0;
1198 channel
->flush_flush_bytes
= 0;
1201 LIBSSH2_PACKET
*next
= packet
->next
;
1202 unsigned char packet_type
= packet
->data
[0];
1204 if (((packet_type
== SSH_MSG_CHANNEL_DATA
)
1205 || (packet_type
== SSH_MSG_CHANNEL_EXTENDED_DATA
))
1206 && (libssh2_ntohu32(packet
->data
+ 1) == channel
->local
.id
)) {
1207 /* It's our channel at least */
1208 long packet_stream_id
=
1210 SSH_MSG_CHANNEL_DATA
) ?
0 : libssh2_ntohu32(packet
->data
+
1212 if ((streamid
== LIBSSH2_CHANNEL_FLUSH_ALL
)
1213 || ((packet_type
== SSH_MSG_CHANNEL_EXTENDED_DATA
)
1214 && ((streamid
== LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA
)
1215 || (streamid
== packet_stream_id
)))
1216 || ((packet_type
== SSH_MSG_CHANNEL_DATA
)
1217 && (streamid
== 0))) {
1218 int bytes_to_flush
= packet
->data_len
- packet
->data_head
;
1220 _libssh2_debug(channel
->session
, LIBSSH2_DBG_CONN
,
1221 "Flushing %d bytes of data from stream %lu on channel %lu/%lu",
1222 bytes_to_flush
, packet_stream_id
,
1223 channel
->local
.id
, channel
->remote
.id
);
1225 /* It's one of the streams we wanted to flush */
1226 channel
->flush_refund_bytes
+= packet
->data_len
- 13;
1227 channel
->flush_flush_bytes
+= bytes_to_flush
;
1229 LIBSSH2_FREE(channel
->session
, packet
->data
);
1231 packet
->prev
->next
= packet
->next
;
1233 channel
->session
->packets
.head
= packet
->next
;
1236 packet
->next
->prev
= packet
->prev
;
1238 channel
->session
->packets
.tail
= packet
->prev
;
1240 LIBSSH2_FREE(channel
->session
, packet
);
1246 channel
->flush_state
= libssh2_NB_state_created
;
1249 if (channel
->flush_refund_bytes
) {
1252 rc
= libssh2_channel_receive_window_adjust(channel
,
1253 channel
->flush_refund_bytes
,
1255 if (rc
== PACKET_EAGAIN
) {
1256 return PACKET_EAGAIN
;
1260 channel
->flush_state
= libssh2_NB_state_idle
;
1262 return channel
->flush_flush_bytes
;
1267 /* {{{ libssh2_channel_get_exit_status
1268 * Return the channel's program exit status
1271 libssh2_channel_get_exit_status(LIBSSH2_CHANNEL
* channel
)
1273 return channel
->exit_status
;
1278 /* {{{ libssh2_channel_receive_window_adjust
1279 * Adjust the receive window for a channel by adjustment bytes
1280 * If the amount to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and
1281 * force is 0 the adjustment amount will be queued for a later packet
1283 * Returns the new size of the receive window (as understood by remote end)
1285 LIBSSH2_API
unsigned long
1286 libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL
* channel
,
1287 unsigned long adjustment
,
1288 unsigned char force
)
1292 if (channel
->adjust_state
== libssh2_NB_state_idle
) {
1294 && (adjustment
+ channel
->adjust_queue
<
1295 LIBSSH2_CHANNEL_MINADJUST
)) {
1296 _libssh2_debug(channel
->session
, LIBSSH2_DBG_CONN
,
1297 "Queueing %lu bytes for receive window adjustment for channel %lu/%lu",
1298 adjustment
, channel
->local
.id
, channel
->remote
.id
);
1299 channel
->adjust_queue
+= adjustment
;
1300 return channel
->remote
.window_size
;
1303 if (!adjustment
&& !channel
->adjust_queue
) {
1304 return channel
->remote
.window_size
;
1307 adjustment
+= channel
->adjust_queue
;
1308 channel
->adjust_queue
= 0;
1311 /* Adjust the window based on the block we just freed */
1312 channel
->adjust_adjust
[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST
;
1313 libssh2_htonu32(channel
->adjust_adjust
+ 1, channel
->remote
.id
);
1314 libssh2_htonu32(channel
->adjust_adjust
+ 5, adjustment
);
1315 _libssh2_debug(channel
->session
, LIBSSH2_DBG_CONN
,
1316 "Adjusting window %lu bytes for data flushed from channel %lu/%lu",
1317 adjustment
, channel
->local
.id
, channel
->remote
.id
);
1319 channel
->adjust_state
= libssh2_NB_state_created
;
1322 rc
= libssh2_packet_write(channel
->session
, channel
->adjust_adjust
, 9);
1323 if (rc
== PACKET_EAGAIN
) {
1324 return PACKET_EAGAIN
;
1326 libssh2_error(channel
->session
, LIBSSH2_ERROR_SOCKET_SEND
,
1327 "Unable to send transfer-window adjustment packet, deferring",
1329 channel
->adjust_queue
= adjustment
;
1330 channel
->adjust_state
= libssh2_NB_state_idle
;
1332 channel
->adjust_state
= libssh2_NB_state_idle
;
1333 channel
->remote
.window_size
+= adjustment
;
1336 return channel
->remote
.window_size
;
1341 /* {{{ libssh2_channel_handle_extended_data
1342 * How should extended data look to the calling app?
1343 * Keep it in separate channels[_read() _read_stdder()]? (NORMAL)
1344 * Merge the extended data to the standard data? [everything via _read()]? (MERGE)
1345 * Ignore it entirely [toss out packets as they come in]? (IGNORE)
1348 libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL
* channel
,
1351 while (libssh2_channel_handle_extended_data2(channel
, ignore_mode
) ==
1356 libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL
* channel
,
1359 if (channel
->extData2_state
== libssh2_NB_state_idle
) {
1360 _libssh2_debug(channel
->session
, LIBSSH2_DBG_CONN
,
1361 "Setting channel %lu/%lu handle_extended_data mode to %d",
1362 channel
->local
.id
, channel
->remote
.id
, ignore_mode
);
1363 channel
->remote
.extended_data_ignore_mode
= ignore_mode
;
1365 channel
->extData2_state
= libssh2_NB_state_created
;
1368 if (channel
->extData2_state
== libssh2_NB_state_idle
) {
1369 if (ignore_mode
== LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE
) {
1370 if (libssh2_channel_flush_ex
1372 LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA
) == PACKET_EAGAIN
) {
1373 return PACKET_EAGAIN
;
1378 channel
->extData2_state
= libssh2_NB_state_idle
;
1385 * {{{ libssh2_channel_read_ex
1386 * Read data from a channel blocking or non-blocking depending on set state
1388 * When this is done non-blocking, it is important to not return 0 until the
1389 * currently read channel is complete. If we read stuff from the wire but it
1390 * was no payload data to fill in the buffer with, we MUST make sure to return
1394 libssh2_channel_read_ex(LIBSSH2_CHANNEL
* channel
, int stream_id
, char *buf
,
1397 LIBSSH2_SESSION
*session
= channel
->session
;
1398 libssh2pack_t rc
= 0;
1400 if (channel
->read_state
== libssh2_NB_state_idle
) {
1401 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1402 "Attempting to read %d bytes from channel %lu/%lu stream #%d",
1403 (int) buflen
, channel
->local
.id
, channel
->remote
.id
,
1406 /* process all incoming packets */
1408 if (libssh2_waitsocket(session
, 0) > 0) {
1409 rc
= libssh2_packet_read(session
);
1411 /* Set for PACKET_EAGAIN so we continue */
1416 if ((rc
< 0) && (rc
!= PACKET_EAGAIN
)) {
1417 fprintf(stderr
, "return rc = %d\n", rc
);
1420 channel
->read_bytes_read
= 0;
1421 channel
->read_block
= 0;
1423 channel
->read_packet
= session
->packets
.head
;
1425 channel
->read_state
= libssh2_NB_state_created
;
1429 * =============================== NOTE ===============================
1430 * I know this is very ugly and not a really good use of "goto", but
1431 * this case statement would be even uglier to do it any other way
1433 if (channel
->read_state
== libssh2_NB_state_jump1
) {
1434 goto channel_read_ex_point1
;
1440 if (channel
->read_block
) {
1441 /* in the second lap and onwards, do this */
1442 rc
= libssh2_packet_read(session
);
1443 channel
->read_packet
= session
->packets
.head
;
1447 if (rc
!= PACKET_EAGAIN
) {
1448 channel
->read_state
= libssh2_NB_state_idle
;
1450 /* no packets available */
1454 while (channel
->read_packet
1455 && (channel
->read_bytes_read
< (int) buflen
)) {
1456 /* In case packet gets destroyed during this iteration */
1457 channel
->read_next
= channel
->read_packet
->next
;
1459 channel
->read_local_id
=
1460 libssh2_ntohu32(channel
->read_packet
->data
+ 1);
1463 * Either we asked for a specific extended data stream
1464 * (and data was available),
1465 * or the standard stream (and data was available),
1466 * or the standard stream with extended_data_merge
1467 * enabled and data was available
1470 && (channel
->read_packet
->data
[0] ==
1471 SSH_MSG_CHANNEL_EXTENDED_DATA
)
1472 && (channel
->local
.id
== channel
->read_local_id
)
1474 (int) libssh2_ntohu32(channel
->read_packet
->data
+ 5)))
1476 && (channel
->read_packet
->data
[0] == SSH_MSG_CHANNEL_DATA
)
1477 && (channel
->local
.id
== channel
->read_local_id
))
1479 && (channel
->read_packet
->data
[0] ==
1480 SSH_MSG_CHANNEL_EXTENDED_DATA
)
1481 && (channel
->local
.id
== channel
->read_local_id
)
1482 && (channel
->remote
.extended_data_ignore_mode
==
1483 LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE
))) {
1485 channel
->read_want
= buflen
- channel
->read_bytes_read
;
1486 channel
->read_unlink_packet
= 0;
1488 if (channel
->read_want
>=
1489 (int) (channel
->read_packet
->data_len
-
1490 channel
->read_packet
->data_head
)) {
1491 channel
->read_want
=
1492 channel
->read_packet
->data_len
-
1493 channel
->read_packet
->data_head
;
1494 channel
->read_unlink_packet
= 1;
1497 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1498 "Reading %d of buffered data from %lu/%lu/%d",
1499 channel
->read_want
, channel
->local
.id
,
1500 channel
->remote
.id
, stream_id
);
1501 memcpy(buf
+ channel
->read_bytes_read
,
1502 channel
->read_packet
->data
+
1503 channel
->read_packet
->data_head
, channel
->read_want
);
1504 channel
->read_packet
->data_head
+= channel
->read_want
;
1505 channel
->read_bytes_read
+= channel
->read_want
;
1507 if (channel
->read_unlink_packet
) {
1508 if (channel
->read_packet
->prev
) {
1509 channel
->read_packet
->prev
->next
=
1510 channel
->read_packet
->next
;
1512 session
->packets
.head
= channel
->read_packet
->next
;
1514 if (channel
->read_packet
->next
) {
1515 channel
->read_packet
->next
->prev
=
1516 channel
->read_packet
->prev
;
1518 session
->packets
.tail
= channel
->read_packet
->prev
;
1520 LIBSSH2_FREE(session
, channel
->read_packet
->data
);
1523 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1524 "Unlinking empty packet buffer from channel %lu/%lu",
1525 channel
->local
.id
, channel
->remote
.id
);
1526 channel_read_ex_point1
:
1527 channel
->read_state
= libssh2_NB_state_jump1
;
1528 rc
= libssh2_channel_receive_window_adjust(channel
,
1534 if (rc
== PACKET_EAGAIN
) {
1535 return PACKET_EAGAIN
;
1537 channel
->read_state
= libssh2_NB_state_created
;
1538 LIBSSH2_FREE(session
, channel
->read_packet
);
1539 channel
->read_packet
= NULL
;
1542 channel
->read_packet
= channel
->read_next
;
1544 channel
->read_block
= 1;
1545 } while ((channel
->read_bytes_read
== 0) && !channel
->remote
.close
);
1547 channel
->read_state
= libssh2_NB_state_idle
;
1548 if (channel
->read_bytes_read
== 0) {
1549 if (channel
->session
->socket_block
) {
1550 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_CLOSED
,
1551 "Remote end has closed this channel", 0);
1554 * when non-blocking, we must return PACKET_EAGAIN if we haven't
1555 * completed reading the channel
1557 if (!libssh2_channel_eof(channel
)) {
1558 return PACKET_EAGAIN
;
1563 channel
->read_state
= libssh2_NB_state_idle
;
1564 return channel
->read_bytes_read
;
1570 * {{{ libssh2_channel_packet_data_len
1571 * Return the size of the data block of the current packet, or 0 if there
1575 libssh2_channel_packet_data_len(LIBSSH2_CHANNEL
* channel
, int stream_id
)
1577 LIBSSH2_SESSION
*session
= channel
->session
;
1578 LIBSSH2_PACKET
*read_packet
;
1579 uint32_t read_local_id
;
1581 if ((read_packet
= session
->packets
.head
) == NULL
) {
1585 while (read_packet
) {
1586 read_local_id
= libssh2_ntohu32(read_packet
->data
+ 1);
1589 * Either we asked for a specific extended data stream
1590 * (and data was available),
1591 * or the standard stream (and data was available),
1592 * or the standard stream with extended_data_merge
1593 * enabled and data was available
1596 && (read_packet
->data
[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
)
1597 && (channel
->local
.id
== read_local_id
)
1598 && (stream_id
== (int) libssh2_ntohu32(read_packet
->data
+ 5)))
1599 || (!stream_id
&& (read_packet
->data
[0] == SSH_MSG_CHANNEL_DATA
)
1600 && (channel
->local
.id
== read_local_id
)) || (!stream_id
1603 SSH_MSG_CHANNEL_EXTENDED_DATA
)
1609 extended_data_ignore_mode
1611 LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE
)))
1614 return (read_packet
->data_len
- read_packet
->data_head
);
1616 read_packet
= read_packet
->next
;
1624 /* {{{ libssh2_channel_write_ex
1625 * Send data to a channel
1628 libssh2_channel_write_ex(LIBSSH2_CHANNEL
* channel
, int stream_id
,
1629 const char *buf
, size_t buflen
)
1631 LIBSSH2_SESSION
*session
= channel
->session
;
1634 if (channel
->write_state
== libssh2_NB_state_idle
) {
1635 channel
->write_bufwrote
= 0;
1637 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1638 "Writing %d bytes on channel %lu/%lu, stream #%d",
1639 (int) buflen
, channel
->local
.id
, channel
->remote
.id
,
1642 if (channel
->local
.close
) {
1643 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_CLOSED
,
1644 "We've already closed this channel", 0);
1648 if (channel
->local
.eof
) {
1649 libssh2_error(session
, LIBSSH2_ERROR_CHANNEL_EOF_SENT
,
1650 "EOF has already been sight, data might be ignored",
1656 The following chunk of code is #ifdef'ed out, since I wanted it to
1657 remain here with the given explanation why having the code in here
1658 is not a good idea. The text is taken from the email Gavrie
1659 Philipson wrote to libssh2-devel on Nov 8 2007.
1661 The logic behind this is that in nonblocking mode, if the local
1662 window size has shrunk to zero, there's no point in trying to send
1663 anything more. However, exiting the function at that point does not
1664 allow any adjusts from the remote side to be received, since
1665 libssh2_packet_read (that is called further on in this function) is
1666 never called in this case.
1668 Removing this bit of code fixes the problem. This should not cause
1669 busy waiting, since after the libssh2_packet_read, the function
1670 correctly returns PACKET_EAGAIN if the window size was not adjusted.
1672 if (!channel
->session
->socket_block
&&
1673 (channel
->local
.window_size
<= 0)) {
1674 /* Can't write anything */
1679 /* [13] 9 = packet_type(1) + channelno(4) [ + streamid(4) ] + buflen(4) */
1680 channel
->write_packet_len
= buflen
+ (stream_id ?
13 : 9);
1681 channel
->write_packet
=
1682 LIBSSH2_ALLOC(session
, channel
->write_packet_len
);
1683 if (!channel
->write_packet
) {
1684 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1685 "Unable to allocte space for data transmission packet",
1690 channel
->write_state
= libssh2_NB_state_allocated
;
1693 while (buflen
> 0) {
1694 if (channel
->write_state
== libssh2_NB_state_allocated
) {
1695 channel
->write_bufwrite
= buflen
;
1696 channel
->write_s
= channel
->write_packet
;
1698 *(channel
->write_s
++) =
1699 stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA
:
1700 SSH_MSG_CHANNEL_DATA
;
1701 libssh2_htonu32(channel
->write_s
, channel
->remote
.id
);
1702 channel
->write_s
+= 4;
1704 libssh2_htonu32(channel
->write_s
, stream_id
);
1705 channel
->write_s
+= 4;
1708 /* twiddle our thumbs until there's window space available */
1709 while (channel
->local
.window_size
<= 0) {
1710 /* Don't worry -- This is never hit unless it's a
1711 blocking channel anyway */
1712 rc
= libssh2_packet_read(session
);
1715 /* Error or EAGAIN occurred, disconnect? */
1716 if (rc
!= PACKET_EAGAIN
) {
1717 channel
->write_state
= libssh2_NB_state_idle
;
1722 if ((rc
== 0) && (session
->socket_block
== 0)) {
1724 * if rc == 0 and in non-blocking, then fake EAGAIN
1725 * to prevent busyloops until data arriaves on the network
1726 * which seemed like a very bad idea
1728 return PACKET_EAGAIN
;
1732 /* Don't exceed the remote end's limits */
1733 /* REMEMBER local means local as the SOURCE of the data */
1734 if (channel
->write_bufwrite
> channel
->local
.window_size
) {
1735 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1736 "Splitting write block due to %lu byte window_size on %lu/%lu/%d",
1737 channel
->local
.window_size
, channel
->local
.id
,
1738 channel
->remote
.id
, stream_id
);
1739 channel
->write_bufwrite
= channel
->local
.window_size
;
1741 if (channel
->write_bufwrite
> channel
->local
.packet_size
) {
1742 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1743 "Splitting write block due to %lu byte packet_size on %lu/%lu/%d",
1744 channel
->local
.packet_size
, channel
->local
.id
,
1745 channel
->remote
.id
, stream_id
);
1746 channel
->write_bufwrite
= channel
->local
.packet_size
;
1748 libssh2_htonu32(channel
->write_s
, channel
->write_bufwrite
);
1749 channel
->write_s
+= 4;
1750 memcpy(channel
->write_s
, buf
, channel
->write_bufwrite
);
1751 channel
->write_s
+= channel
->write_bufwrite
;
1753 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1754 "Sending %d bytes on channel %lu/%lu, stream_id=%d",
1755 (int) channel
->write_bufwrite
, channel
->local
.id
,
1756 channel
->remote
.id
, stream_id
);
1758 channel
->write_state
= libssh2_NB_state_created
;
1761 if (channel
->write_state
== libssh2_NB_state_created
) {
1762 rc
= libssh2_packet_write(session
, channel
->write_packet
,
1764 channel
->write_packet
);
1765 if (rc
== PACKET_EAGAIN
) {
1766 return PACKET_EAGAIN
;
1768 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1769 "Unable to send channel data", 0);
1770 LIBSSH2_FREE(session
, channel
->write_packet
);
1771 channel
->write_packet
= NULL
;
1772 channel
->write_state
= libssh2_NB_state_idle
;
1775 /* Shrink local window size */
1776 channel
->local
.window_size
-= channel
->write_bufwrite
;
1778 /* Adjust buf for next iteration */
1779 buflen
-= channel
->write_bufwrite
;
1780 buf
+= channel
->write_bufwrite
;
1781 channel
->write_bufwrote
+= channel
->write_bufwrite
;
1783 channel
->write_state
= libssh2_NB_state_allocated
;
1786 * Not sure this is still wanted
1787 if (!channel->session->socket_block) {
1794 LIBSSH2_FREE(session
, channel
->write_packet
);
1795 channel
->write_packet
= NULL
;
1797 channel
->write_state
= libssh2_NB_state_idle
;
1799 return channel
->write_bufwrote
;
1804 /* {{{ libssh2_channel_send_eof
1805 * Send EOF on channel
1808 libssh2_channel_send_eof(LIBSSH2_CHANNEL
* channel
)
1810 LIBSSH2_SESSION
*session
= channel
->session
;
1811 unsigned char packet
[5]; /* packet_type(1) + channelno(4) */
1814 _libssh2_debug(session
, LIBSSH2_DBG_CONN
, "Sending EOF on channel %lu/%lu",
1815 channel
->local
.id
, channel
->remote
.id
);
1816 packet
[0] = SSH_MSG_CHANNEL_EOF
;
1817 libssh2_htonu32(packet
+ 1, channel
->remote
.id
);
1818 rc
= libssh2_packet_write(session
, packet
, 5);
1819 if (rc
== PACKET_EAGAIN
) {
1820 return PACKET_EAGAIN
;
1822 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1823 "Unable to send EOF on channel", 0);
1826 channel
->local
.eof
= 1;
1833 /* {{{ libssh2_channel_eof
1834 * Read channel's eof status
1837 libssh2_channel_eof(LIBSSH2_CHANNEL
* channel
)
1839 LIBSSH2_SESSION
*session
= channel
->session
;
1840 LIBSSH2_PACKET
*packet
= session
->packets
.head
;
1843 if (((packet
->data
[0] == SSH_MSG_CHANNEL_DATA
)
1844 || (packet
->data
[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
))
1845 && (channel
->local
.id
== libssh2_ntohu32(packet
->data
+ 1))) {
1846 /* There's data waiting to be read yet, mask the EOF status */
1849 packet
= packet
->next
;
1852 return channel
->remote
.eof
;
1857 /* {{{ libssh2_channel_wait_closed
1858 * Awaiting channel EOF
1861 libssh2_channel_wait_eof(LIBSSH2_CHANNEL
* channel
)
1863 LIBSSH2_SESSION
*session
= channel
->session
;
1866 if (channel
->wait_eof_state
== libssh2_NB_state_idle
) {
1867 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1868 "Awaiting close of channel %lu/%lu", channel
->local
.id
,
1869 channel
->remote
.id
);
1871 channel
->wait_eof_state
= libssh2_NB_state_created
;
1875 * While channel is not eof, read more packets from the network.
1876 * Either the EOF will be set or network timeout will occur.
1879 if (channel
->remote
.eof
) {
1882 rc
= libssh2_packet_read(session
);
1883 if (rc
== PACKET_EAGAIN
) {
1884 return PACKET_EAGAIN
;
1885 } else if (rc
< 0) {
1886 channel
->wait_eof_state
= libssh2_NB_state_idle
;
1891 channel
->wait_eof_state
= libssh2_NB_state_idle
;
1899 /* {{{ libssh2_channel_close
1903 libssh2_channel_close(LIBSSH2_CHANNEL
* channel
)
1905 LIBSSH2_SESSION
*session
= channel
->session
;
1909 if (channel
->local
.close
) {
1910 /* Already closed, act like we sent another close,
1911 * even though we didn't... shhhhhh */
1912 channel
->close_state
= libssh2_NB_state_idle
;
1916 if (channel
->close_state
== libssh2_NB_state_idle
) {
1917 _libssh2_debug(session
, LIBSSH2_DBG_CONN
, "Closing channel %lu/%lu",
1918 channel
->local
.id
, channel
->remote
.id
);
1920 if (channel
->close_cb
) {
1921 LIBSSH2_CHANNEL_CLOSE(session
, channel
);
1923 channel
->local
.close
= 1;
1925 channel
->close_packet
[0] = SSH_MSG_CHANNEL_CLOSE
;
1926 libssh2_htonu32(channel
->close_packet
+ 1, channel
->remote
.id
);
1928 channel
->close_state
= libssh2_NB_state_created
;
1931 if (channel
->close_state
== libssh2_NB_state_created
) {
1932 retcode
= libssh2_packet_write(session
, channel
->close_packet
, 5);
1933 if (retcode
== PACKET_EAGAIN
) {
1934 return PACKET_EAGAIN
;
1935 } else if (retcode
) {
1936 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1937 "Unable to send close-channel request", 0);
1938 channel
->close_state
= libssh2_NB_state_idle
;
1942 channel
->close_state
= libssh2_NB_state_sent
;
1945 if (channel
->close_state
== libssh2_NB_state_sent
) {
1946 /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
1947 if (!channel
->remote
.close
) {
1951 ret
= libssh2_packet_read(session
);
1952 if (ret
== PACKET_EAGAIN
) {
1953 return PACKET_EAGAIN
;
1954 } else if (ret
< 0) {
1957 } while ((ret
!= SSH_MSG_CHANNEL_CLOSE
) && (rc
== 0));
1961 channel
->close_state
= libssh2_NB_state_idle
;
1968 /* {{{ libssh2_channel_wait_closed
1969 * Awaiting channel close after EOF
1972 libssh2_channel_wait_closed(LIBSSH2_CHANNEL
* channel
)
1974 LIBSSH2_SESSION
*session
= channel
->session
;
1977 if (!libssh2_channel_eof(channel
)) {
1978 libssh2_error(session
, LIBSSH2_ERROR_INVAL
,
1979 "libssh2_channel_wait_closed() invoked when channel is not in EOF state",
1984 if (channel
->wait_closed_state
== libssh2_NB_state_idle
) {
1985 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
1986 "Awaiting close of channel %lu/%lu", channel
->local
.id
,
1987 channel
->remote
.id
);
1989 channel
->wait_closed_state
= libssh2_NB_state_created
;
1993 * While channel is not closed, read more packets from the network.
1994 * Either the channel will be closed or network timeout will occur.
1997 if (!channel
->remote
.close
) {
2000 rc
= libssh2_packet_read(session
);
2001 if (rc
== PACKET_EAGAIN
) {
2002 return PACKET_EAGAIN
;
2003 } else if (rc
<= 0) {
2008 channel
->wait_closed_state
= libssh2_NB_state_idle
;
2016 /* {{{ libssh2_channel_free
2017 * Make sure a channel is closed, then remove the channel from the session
2018 * and free its resource(s)
2020 * Returns 0 on success, -1 on failure
2023 libssh2_channel_free(LIBSSH2_CHANNEL
* channel
)
2025 LIBSSH2_SESSION
*session
= channel
->session
;
2026 unsigned char channel_id
[4];
2027 unsigned char *data
;
2028 unsigned long data_len
;
2031 if (channel
->free_state
== libssh2_NB_state_idle
) {
2032 _libssh2_debug(session
, LIBSSH2_DBG_CONN
,
2033 "Freeing channel %lu/%lu resources", channel
->local
.id
,
2034 channel
->remote
.id
);
2036 channel
->free_state
= libssh2_NB_state_created
;
2039 /* Allow channel freeing even when the socket has lost its connection */
2040 if (!channel
->local
.close
2041 && (session
->socket_state
== LIBSSH2_SOCKET_CONNECTED
)) {
2042 while ((rc
= libssh2_channel_close(channel
)) == PACKET_EAGAIN
);
2044 channel
->free_state
= libssh2_NB_state_idle
;
2049 channel
->free_state
= libssh2_NB_state_idle
;
2052 * channel->remote.close *might* not be set yet, Well...
2053 * We've sent the close packet, what more do you want?
2054 * Just let packet_add ignore it when it finally arrives
2057 /* Clear out packets meant for this channel */
2058 libssh2_htonu32(channel_id
, channel
->local
.id
);
2059 while ((libssh2_packet_ask_ex
2060 (session
, SSH_MSG_CHANNEL_DATA
, &data
, &data_len
, 1, channel_id
, 4,
2063 (libssh2_packet_ask_ex
2064 (session
, SSH_MSG_CHANNEL_EXTENDED_DATA
, &data
, &data_len
, 1,
2065 channel_id
, 4, 0) >= 0)) {
2066 LIBSSH2_FREE(session
, data
);
2069 /* free "channel_type" */
2070 if (channel
->channel_type
) {
2071 LIBSSH2_FREE(session
, channel
->channel_type
);
2074 /* Unlink from channel brigade */
2075 if (channel
->prev
) {
2076 channel
->prev
->next
= channel
->next
;
2078 session
->channels
.head
= channel
->next
;
2080 if (channel
->next
) {
2081 channel
->next
->prev
= channel
->prev
;
2083 session
->channels
.tail
= channel
->prev
;
2087 * Make sure all memory used in the state variables are free
2089 if (channel
->setenv_packet
) {
2090 LIBSSH2_FREE(session
, channel
->setenv_packet
);
2092 if (channel
->reqPTY_packet
) {
2093 LIBSSH2_FREE(session
, channel
->reqPTY_packet
);
2095 if (channel
->reqX11_packet
) {
2096 LIBSSH2_FREE(session
, channel
->reqX11_packet
);
2098 if (channel
->process_packet
) {
2099 LIBSSH2_FREE(session
, channel
->process_packet
);
2101 if (channel
->write_packet
) {
2102 LIBSSH2_FREE(session
, channel
->write_packet
);
2105 LIBSSH2_FREE(session
, channel
);
2112 /* {{{ libssh2_channel_window_read_ex
2113 * Check the status of the read window
2114 * Returns the number of bytes which the remote end may send without overflowing the window limit
2115 * read_avail (if passed) will be populated with the number of bytes actually available to be read
2116 * window_size_initial (if passed) will be populated with the window_size_initial as defined by the channel_open request
2118 LIBSSH2_API
unsigned long
2119 libssh2_channel_window_read_ex(LIBSSH2_CHANNEL
* channel
,
2120 unsigned long *read_avail
,
2121 unsigned long *window_size_initial
)
2123 if (window_size_initial
) {
2124 *window_size_initial
= channel
->remote
.window_size_initial
;
2128 unsigned long bytes_queued
= 0;
2129 LIBSSH2_PACKET
*packet
= channel
->session
->packets
.head
;
2132 unsigned char packet_type
= packet
->data
[0];
2134 if (((packet_type
== SSH_MSG_CHANNEL_DATA
)
2135 || (packet_type
== SSH_MSG_CHANNEL_EXTENDED_DATA
))
2136 && (libssh2_ntohu32(packet
->data
+ 1) == channel
->local
.id
)) {
2137 bytes_queued
+= packet
->data_len
- packet
->data_head
;
2140 packet
= packet
->next
;
2143 *read_avail
= bytes_queued
;
2146 return channel
->remote
.window_size
;
2151 /* {{{ libssh2_channel_window_write_ex
2152 * Check the status of the write window
2153 * Returns the number of bytes which may be safely writen on the channel without blocking
2154 * window_size_initial (if passed) will be populated with the size of the initial window as defined by the channel_open request
2156 LIBSSH2_API
unsigned long
2157 libssh2_channel_window_write_ex(LIBSSH2_CHANNEL
* channel
,
2158 unsigned long *window_size_initial
)
2160 if (window_size_initial
) {
2161 /* For locally initiated channels this is very often 0, so it's not *that* useful as information goes */
2162 *window_size_initial
= channel
->local
.window_size_initial
;
2165 return channel
->local
.window_size
;