libssh2

Форк
0
/
session.c 
1952 строки · 59.3 Кб
1
/* Copyright (C) Sara Golemon <sarag@libssh2.org>
2
 * Copyright (C) Daniel Stenberg
3
 * Copyright (C) Simon Josefsson <simon@josefsson.org>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms,
7
 * with or without modification, are permitted provided
8
 * that the following conditions are met:
9
 *
10
 *   Redistributions of source code must retain the above
11
 *   copyright notice, this list of conditions and the
12
 *   following disclaimer.
13
 *
14
 *   Redistributions in binary form must reproduce the above
15
 *   copyright notice, this list of conditions and the following
16
 *   disclaimer in the documentation and/or other materials
17
 *   provided with the distribution.
18
 *
19
 *   Neither the name of the copyright holder nor the names
20
 *   of any other contributors may be used to endorse or
21
 *   promote products derived from this software without
22
 *   specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37
 * OF SUCH DAMAGE.
38
 *
39
 * SPDX-License-Identifier: BSD-3-Clause
40
 */
41

42
#include "libssh2_priv.h"
43

44
#ifdef _WIN32
45
#include <ws2tcpip.h>  /* for socklen_t */
46
#endif
47
#ifdef HAVE_UNISTD_H
48
#include <unistd.h>
49
#endif
50
#ifdef HAVE_ALLOCA_H
51
#include <alloca.h>
52
#endif
53

54
#include <errno.h>
55
#include <stdlib.h>
56
#include <fcntl.h>
57

58
#include "transport.h"
59
#include "session.h"
60
#include "channel.h"
61
#include "mac.h"
62

63
#if defined(_WIN32)
64
#define libssh2_usec_t long
65
#elif defined(__APPLE__)
66
#define libssh2_usec_t suseconds_t
67
#else
68
#undef libssh2_usec_t
69
#endif
70

71
/* libssh2_default_alloc
72
 */
73
static
74
LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
75
{
76
    (void)abstract;
77
    return malloc(count);
78
}
79

80
/* libssh2_default_free
81
 */
82
static
83
LIBSSH2_FREE_FUNC(libssh2_default_free)
84
{
85
    (void)abstract;
86
    free(ptr);
87
}
88

89
/* libssh2_default_realloc
90
 */
91
static
92
LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
93
{
94
    (void)abstract;
95
    return realloc(ptr, count);
96
}
97

98
/*
99
 * banner_receive
100
 *
101
 * Wait for a hello from the remote host
102
 * Allocate a buffer and store the banner in session->remote.banner
103
 * Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative
104
 * on failure
105
 */
106
static int
107
banner_receive(LIBSSH2_SESSION * session)
108
{
109
    ssize_t ret;
110
    size_t banner_len;
111

112
    if(session->banner_TxRx_state == libssh2_NB_state_idle) {
113
        banner_len = 0;
114

115
        session->banner_TxRx_state = libssh2_NB_state_created;
116
    }
117
    else {
118
        banner_len = session->banner_TxRx_total_send;
119
    }
120

121
    while((banner_len < sizeof(session->banner_TxRx_banner)) &&
122
          ((banner_len == 0)
123
           || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
124
        char c = '\0';
125

126
        /* no incoming block yet! */
127
        session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
128

129
        ret = LIBSSH2_RECV(session, &c, 1,
130
                           LIBSSH2_SOCKET_RECV_FLAGS(session));
131
        if(ret < 0) {
132
            if(session->api_block_mode || (ret != -EAGAIN))
133
                /* ignore EAGAIN when non-blocking */
134
                _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
135
                               "Error recving %d bytes: %ld", 1, (long)-ret));
136
        }
137
        else
138
            _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
139
                           "Recved %ld bytes banner", (long)ret));
140

141
        if(ret < 0) {
142
            if(ret == -EAGAIN) {
143
                session->socket_block_directions =
144
                    LIBSSH2_SESSION_BLOCK_INBOUND;
145
                session->banner_TxRx_total_send = banner_len;
146
                return LIBSSH2_ERROR_EAGAIN;
147
            }
148

149
            /* Some kinda error */
150
            session->banner_TxRx_state = libssh2_NB_state_idle;
151
            session->banner_TxRx_total_send = 0;
152
            return LIBSSH2_ERROR_SOCKET_RECV;
153
        }
154

155
        if(ret == 0) {
156
            session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
157
            return LIBSSH2_ERROR_SOCKET_DISCONNECT;
158
        }
159

160
        if((c == '\r' || c == '\n') && banner_len == 0) {
161
            continue;
162
        }
163

164
        if(c == '\0') {
165
            /* NULLs are not allowed in SSH banners */
166
            session->banner_TxRx_state = libssh2_NB_state_idle;
167
            session->banner_TxRx_total_send = 0;
168
            return LIBSSH2_ERROR_BANNER_RECV;
169
        }
170

171
        session->banner_TxRx_banner[banner_len++] = c;
172
    }
173

174
    while(banner_len &&
175
          ((session->banner_TxRx_banner[banner_len - 1] == '\n') ||
176
           (session->banner_TxRx_banner[banner_len - 1] == '\r'))) {
177
        banner_len--;
178
    }
179

180
    /* From this point on, we are done here */
181
    session->banner_TxRx_state = libssh2_NB_state_idle;
182
    session->banner_TxRx_total_send = 0;
183

184
    if(!banner_len)
185
        return LIBSSH2_ERROR_BANNER_RECV;
186

187
    if(session->remote.banner)
188
        LIBSSH2_FREE(session, session->remote.banner);
189

190
    session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
191
    if(!session->remote.banner) {
192
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
193
                              "Error allocating space for remote banner");
194
    }
195
    memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
196
    session->remote.banner[banner_len] = '\0';
197
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
198
                   session->remote.banner));
199
    return LIBSSH2_ERROR_NONE;
200
}
201

202
/*
203
 * banner_send
204
 *
205
 * Send the default banner, or the one set via libssh2_setopt_string
206
 *
207
 * Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you
208
 * should call this function again as soon as it is likely that more data can
209
 * be sent, and this function should then be called with the same argument set
210
 * (same data pointer and same data_len) until zero or failure is returned.
211
 */
212
static int
213
banner_send(LIBSSH2_SESSION * session)
214
{
215
    char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF;
216
    size_t banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1;
217
    ssize_t ret;
218

219
    if(session->banner_TxRx_state == libssh2_NB_state_idle) {
220
        if(session->local.banner) {
221
            /* setopt_string will have given us our \r\n characters */
222
            banner_len = strlen((char *) session->local.banner);
223
            banner = (char *) session->local.banner;
224
        }
225
#ifdef LIBSSH2DEBUG
226
        {
227
            char banner_dup[256];
228

229
            /* Hack and slash to avoid sending CRLF in debug output */
230
            if(banner_len < 256) {
231
                memcpy(banner_dup, banner, banner_len - 2);
232
                banner_dup[banner_len - 2] = '\0';
233
            }
234
            else {
235
                memcpy(banner_dup, banner, 255);
236
                banner_dup[255] = '\0';
237
            }
238

239
            _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
240
                           "Sending Banner: %s", banner_dup));
241
        }
242
#endif
243

244
        session->banner_TxRx_state = libssh2_NB_state_created;
245
    }
246

247
    /* no outgoing block yet! */
248
    session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
249

250
    ret = LIBSSH2_SEND(session,
251
                       banner + session->banner_TxRx_total_send,
252
                       banner_len - session->banner_TxRx_total_send,
253
                       LIBSSH2_SOCKET_SEND_FLAGS(session));
254
    if(ret < 0)
255
        _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
256
                       "Error sending %ld bytes: %ld",
257
                       (long)(banner_len - session->banner_TxRx_total_send),
258
                       (long)-ret));
259
    else
260
        _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
261
                       "Sent %ld/%ld bytes at %p+%ld", (long)ret,
262
                       (long)(banner_len - session->banner_TxRx_total_send),
263
                       (void *)banner, (long)session->banner_TxRx_total_send));
264

265
    if(ret != (ssize_t)(banner_len - session->banner_TxRx_total_send)) {
266
        if(ret >= 0 || ret == -EAGAIN) {
267
            /* the whole packet could not be sent, save the what was */
268
            session->socket_block_directions =
269
                LIBSSH2_SESSION_BLOCK_OUTBOUND;
270
            if(ret > 0)
271
                session->banner_TxRx_total_send += ret;
272
            return LIBSSH2_ERROR_EAGAIN;
273
        }
274
        session->banner_TxRx_state = libssh2_NB_state_idle;
275
        session->banner_TxRx_total_send = 0;
276
        return LIBSSH2_ERROR_SOCKET_RECV;
277
    }
278

279
    /* Set the state back to idle */
280
    session->banner_TxRx_state = libssh2_NB_state_idle;
281
    session->banner_TxRx_total_send = 0;
282

283
    return 0;
284
}
285

286
/*
287
 * session_nonblock() sets the given socket to either blocking or
288
 * non-blocking mode based on the 'nonblock' boolean argument. This function
289
 * is copied from the libcurl sources with permission.
290
 */
291
static int
292
session_nonblock(libssh2_socket_t sockfd,   /* operate on this */
293
                 int nonblock /* TRUE or FALSE */ )
294
{
295
#ifdef HAVE_O_NONBLOCK
296
    /* most recent unix versions */
297
    int flags;
298

299
    flags = fcntl(sockfd, F_GETFL, 0);
300
    if(nonblock)
301
        return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
302
    else
303
        return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
304
#elif defined(HAVE_FIONBIO)
305
    /* older unix versions and VMS */
306
    int flags;
307

308
    flags = nonblock;
309
    return ioctl(sockfd, FIONBIO, &flags);
310
#elif defined(HAVE_IOCTLSOCKET_CASE)
311
    /* presumably for Amiga */
312
    return IoctlSocket(sockfd, FIONBIO, (long) nonblock);
313
#elif defined(HAVE_SO_NONBLOCK)
314
    /* BeOS */
315
    long b = nonblock ? 1 : 0;
316
    return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
317
#elif defined(_WIN32)
318
    unsigned long flags;
319

320
    flags = nonblock;
321
    return ioctlsocket(sockfd, FIONBIO, &flags);
322
#else
323
    (void)sockfd;
324
    (void)nonblock;
325
    return 0;                   /* returns success */
326
#endif
327
}
328

329
/*
330
 * get_socket_nonblocking
331
 *
332
 * gets the given blocking or non-blocking state of the socket.
333
 */
334
static int
335
get_socket_nonblocking(libssh2_socket_t sockfd)
336
{                               /* operate on this */
337
#ifdef HAVE_O_NONBLOCK
338
    /* most recent unix versions */
339
    int flags = fcntl(sockfd, F_GETFL, 0);
340

341
    if(flags == -1) {
342
        /* Assume blocking on error */
343
        return 1;
344
    }
345
    return (flags & O_NONBLOCK);
346
#elif defined(HAVE_SO_NONBLOCK)
347
    /* BeOS */
348
    long b;
349
    if(getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) {
350
        /* Assume blocking on error */
351
        return 1;
352
    }
353
    return (int) b;
354
#elif defined(SO_STATE) && defined(__VMS)
355
    /* VMS TCP/IP Services */
356

357
    size_t sockstat = 0;
358
    int    callstat = 0;
359
    size_t size = sizeof(int);
360

361
    callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE,
362
                          (char *)&sockstat, &size);
363
    if(callstat == -1) {
364
        return 0;
365
    }
366
    if((sockstat&SS_NBIO) != 0) {
367
        return 1;
368
    }
369
    return 0;
370
#elif defined(_WIN32)
371
    unsigned int option_value;
372
    socklen_t option_len = sizeof(option_value);
373

374
    if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
375
                  (void *) &option_value, &option_len)) {
376
        /* Assume blocking on error */
377
        return 1;
378
    }
379
    return (int) option_value;
380
#else
381
    (void)sockfd;
382
    return 1;                   /* returns blocking */
383
#endif
384
}
385

386
/* libssh2_session_banner_set
387
 * Set the local banner to use in the server handshake.
388
 */
389
LIBSSH2_API int
390
libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner)
391
{
392
    size_t banner_len = banner ? strlen(banner) : 0;
393

394
    if(session->local.banner) {
395
        LIBSSH2_FREE(session, session->local.banner);
396
        session->local.banner = NULL;
397
    }
398

399
    if(!banner_len)
400
        return 0;
401

402
    session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
403
    if(!session->local.banner) {
404
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
405
                              "Unable to allocate memory for local banner");
406
    }
407

408
    memcpy(session->local.banner, banner, banner_len);
409

410
    /* first zero terminate like this so that the debug output is nice */
411
    session->local.banner[banner_len] = '\0';
412
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s",
413
                   session->local.banner));
414
    session->local.banner[banner_len++] = '\r';
415
    session->local.banner[banner_len++] = '\n';
416
    session->local.banner[banner_len] = '\0';
417

418
    return 0;
419
}
420

421
#ifndef LIBSSH2_NO_DEPRECATED
422
/* libssh2_banner_set
423
 * Set the local banner. DEPRECATED VERSION
424
 */
425
LIBSSH2_API int
426
libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
427
{
428
    return libssh2_session_banner_set(session, banner);
429
}
430
#endif
431

432
/*
433
 * libssh2_session_init_ex
434
 *
435
 * Allocate and initialize a libssh2 session structure. Allows for malloc
436
 * callbacks in case the calling program has its own memory manager It's
437
 * allowable (but unadvisable) to define some but not all of the malloc
438
 * callbacks An additional pointer value may be optionally passed to be sent
439
 * to the callbacks (so they know who's asking)
440
 */
441
LIBSSH2_API LIBSSH2_SESSION *
442
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
443
                        LIBSSH2_FREE_FUNC((*my_free)),
444
                        LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract)
445
{
446
    LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc;
447
    LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free;
448
    LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc;
449
    LIBSSH2_SESSION *session;
450

451
    if(my_alloc) {
452
        local_alloc = my_alloc;
453
    }
454
    if(my_free) {
455
        local_free = my_free;
456
    }
457
    if(my_realloc) {
458
        local_realloc = my_realloc;
459
    }
460

461
    session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract);
462
    if(session) {
463
        memset(session, 0, sizeof(LIBSSH2_SESSION));
464
        session->alloc = local_alloc;
465
        session->free = local_free;
466
        session->realloc = local_realloc;
467
        session->send = _libssh2_send;
468
        session->recv = _libssh2_recv;
469
        session->abstract = abstract;
470
        session->api_timeout = 0; /* timeout-free API by default */
471
        session->api_block_mode = 1; /* blocking API by default */
472
        session->state = LIBSSH2_STATE_INITIAL_KEX;
473
        session->fullpacket_required_type = 0;
474
        session->packet_read_timeout = LIBSSH2_DEFAULT_READ_TIMEOUT;
475
        session->flag.quote_paths = 1; /* default behavior is to quote paths
476
                                          for the scp subsystem */
477
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
478
                       "New session resource allocated"));
479
        _libssh2_init_if_needed();
480
    }
481
    return session;
482
}
483

484
/*
485
 * libssh2_session_callback_set2
486
 *
487
 * Set (or reset) a callback function
488
 * Returns the prior address
489
 */
490
LIBSSH2_API libssh2_cb_generic *
491
libssh2_session_callback_set2(LIBSSH2_SESSION *session, int cbtype,
492
                              libssh2_cb_generic *callback)
493
{
494
    libssh2_cb_generic *oldcb;
495

496
    switch(cbtype) {
497
    case LIBSSH2_CALLBACK_IGNORE:
498
        oldcb = (libssh2_cb_generic *)session->ssh_msg_ignore;
499
        session->ssh_msg_ignore = (LIBSSH2_IGNORE_FUNC((*)))callback;
500
        return oldcb;
501

502
    case LIBSSH2_CALLBACK_DEBUG:
503
        oldcb = (libssh2_cb_generic *)session->ssh_msg_debug;
504
        session->ssh_msg_debug = (LIBSSH2_DEBUG_FUNC((*)))callback;
505
        return oldcb;
506

507
    case LIBSSH2_CALLBACK_DISCONNECT:
508
        oldcb = (libssh2_cb_generic *)session->ssh_msg_disconnect;
509
        session->ssh_msg_disconnect = (LIBSSH2_DISCONNECT_FUNC((*)))callback;
510
        return oldcb;
511

512
    case LIBSSH2_CALLBACK_MACERROR:
513
        oldcb = (libssh2_cb_generic *)session->macerror;
514
        session->macerror = (LIBSSH2_MACERROR_FUNC((*)))callback;
515
        return oldcb;
516

517
    case LIBSSH2_CALLBACK_X11:
518
        oldcb = (libssh2_cb_generic *)session->x11;
519
        session->x11 = (LIBSSH2_X11_OPEN_FUNC((*)))callback;
520
        return oldcb;
521

522
    case LIBSSH2_CALLBACK_SEND:
523
        oldcb = (libssh2_cb_generic *)session->send;
524
        session->send = (LIBSSH2_SEND_FUNC((*)))callback;
525
        return oldcb;
526

527
    case LIBSSH2_CALLBACK_RECV:
528
        oldcb = (libssh2_cb_generic *)session->recv;
529
        session->recv = (LIBSSH2_RECV_FUNC((*)))callback;
530
        return oldcb;
531

532
    case LIBSSH2_CALLBACK_AUTHAGENT:
533
        oldcb = (libssh2_cb_generic *)session->authagent;
534
        session->authagent = (LIBSSH2_AUTHAGENT_FUNC((*)))callback;
535
        return oldcb;
536

537
    case LIBSSH2_CALLBACK_AUTHAGENT_IDENTITIES:
538
        oldcb = (libssh2_cb_generic *)session->addLocalIdentities;
539
        session->addLocalIdentities =
540
            (LIBSSH2_ADD_IDENTITIES_FUNC((*)))callback;
541
        return oldcb;
542

543
    case LIBSSH2_CALLBACK_AUTHAGENT_SIGN:
544
        oldcb = (libssh2_cb_generic *)session->agentSignCallback;
545
        session->agentSignCallback =
546
            (LIBSSH2_AUTHAGENT_SIGN_FUNC((*)))callback;
547
        return oldcb;
548
    }
549
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Setting Callback %d",
550
                   cbtype));
551

552
    return NULL;
553
}
554

555
/*
556
 * libssh2_session_callback_set (DEPRECATED, DO NOT USE!)
557
 *
558
 * Set (or reset) a callback function
559
 * Returns the prior address
560
 *
561
 * ALERT: this function relies on that we can typecast function pointers
562
 * to void pointers, which isn't allowed in ISO C!
563
 */
564
#ifdef _MSC_VER
565
#pragma warning(push)
566
/* 'type cast': from data pointer to function pointer */
567
#pragma warning(disable:4054)
568
/* 'type cast': from function pointer to data pointer */
569
#pragma warning(disable:4055)
570
#else
571
#pragma GCC diagnostic push
572
#pragma GCC diagnostic ignored "-Wpedantic"
573
#endif
574
LIBSSH2_API void *
575
libssh2_session_callback_set(LIBSSH2_SESSION * session,
576
                             int cbtype, void *callback)
577
{
578
    return (void *)libssh2_session_callback_set2(session, cbtype,
579
                                               (libssh2_cb_generic *)callback);
580
}
581
#ifdef _MSC_VER
582
#pragma warning(pop)
583
#else
584
#pragma GCC diagnostic pop
585
#endif
586

587
/*
588
 * _libssh2_wait_socket
589
 *
590
 * Utility function that waits for action on the socket. Returns 0 when ready
591
 * to run again or error on timeout.
592
 */
593
int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
594
{
595
    int rc;
596
    int seconds_to_next;
597
    int dir;
598
    int has_timeout;
599
    long ms_to_next = 0;
600
    long elapsed_ms;
601

602
    /* since libssh2 often sets EAGAIN internally before this function is
603
       called, we can decrease some amount of confusion in user programs by
604
       resetting the error code in this function to reduce the risk of EAGAIN
605
       being stored as error when a blocking function has returned */
606
    session->err_code = LIBSSH2_ERROR_NONE;
607

608
    rc = libssh2_keepalive_send(session, &seconds_to_next);
609
    if(rc)
610
        return rc;
611

612
    ms_to_next = seconds_to_next * 1000;
613

614
    /* figure out what to wait for */
615
    dir = libssh2_session_block_directions(session);
616

617
    if(!dir) {
618
        _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
619
                       "Nothing to wait for in wait_socket"));
620
        /* To avoid that we hang below just because there's nothing set to
621
           wait for, we timeout on 1 second to also avoid busy-looping
622
           during this condition */
623
        ms_to_next = 1000;
624
    }
625

626
    if(session->api_timeout > 0 &&
627
        (seconds_to_next == 0 ||
628
         ms_to_next > session->api_timeout)) {
629
        time_t now = time(NULL);
630
        elapsed_ms = (long)(1000*difftime(now, start_time));
631
        if(elapsed_ms > session->api_timeout) {
632
            return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
633
                                  "API timeout expired");
634
        }
635
        ms_to_next = (session->api_timeout - elapsed_ms);
636
        has_timeout = 1;
637
    }
638
    else if(ms_to_next > 0) {
639
        has_timeout = 1;
640
    }
641
    else
642
        has_timeout = 0;
643

644
#ifdef HAVE_POLL
645
    {
646
        struct pollfd sockets[1];
647

648
        sockets[0].fd = session->socket_fd;
649
        sockets[0].events = 0;
650
        sockets[0].revents = 0;
651

652
        if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
653
            sockets[0].events |= POLLIN;
654

655
        if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
656
            sockets[0].events |= POLLOUT;
657

658
        rc = poll(sockets, 1, has_timeout ? (int)ms_to_next : -1);
659
    }
660
#else
661
    {
662
        fd_set rfd;
663
        fd_set wfd;
664
        fd_set *writefd = NULL;
665
        fd_set *readfd = NULL;
666
        struct timeval tv;
667

668
        tv.tv_sec = ms_to_next / 1000;
669
#ifdef libssh2_usec_t
670
        tv.tv_usec = (libssh2_usec_t)((ms_to_next - tv.tv_sec*1000) * 1000);
671
#else
672
        tv.tv_usec = (ms_to_next - tv.tv_sec*1000) * 1000;
673
#endif
674

675
        if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) {
676
            FD_ZERO(&rfd);
677
#if defined(__GNUC__)
678
#pragma GCC diagnostic push
679
#pragma GCC diagnostic ignored "-Wsign-conversion"
680
#endif
681
            FD_SET(session->socket_fd, &rfd);
682
#if defined(__GNUC__)
683
#pragma GCC diagnostic pop
684
#endif
685
            readfd = &rfd;
686
        }
687

688
        if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) {
689
            FD_ZERO(&wfd);
690
#if defined(__GNUC__)
691
#pragma GCC diagnostic push
692
#pragma GCC diagnostic ignored "-Wsign-conversion"
693
#endif
694
            FD_SET(session->socket_fd, &wfd);
695
#if defined(__GNUC__)
696
#pragma GCC diagnostic pop
697
#endif
698
            writefd = &wfd;
699
        }
700

701
        rc = select((int)(session->socket_fd + 1), readfd, writefd, NULL,
702
                    has_timeout ? &tv : NULL);
703
    }
704
#endif
705
    if(rc == 0) {
706
        return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
707
                              "Timed out waiting on socket");
708
    }
709
    if(rc < 0) {
710
        int err;
711
#ifdef _WIN32
712
        err = _libssh2_wsa2errno();
713
#else
714
        err = errno;
715
#endif
716
        /* Profiling tools that use SIGPROF can cause EINTR responses.
717
           poll() / select() do not set any descriptor states on EINTR,
718
           but some fds may be ready, so the caller should try again */
719
        if(err == EINTR)
720
            return 0;
721

722
        return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
723
                              "Error waiting on socket");
724
    }
725

726
    return 0; /* ready to try again */
727
}
728

729
static int
730
session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
731
{
732
    int rc;
733

734
    if(session->startup_state == libssh2_NB_state_idle) {
735
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
736
                       "session_startup for socket %ld", (long)sock));
737
        if(LIBSSH2_INVALID_SOCKET == sock) {
738
            /* Did we forget something? */
739
            return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET,
740
                                  "Bad socket provided");
741
        }
742
        session->socket_fd = sock;
743

744
        session->socket_prev_blockstate =
745
            !get_socket_nonblocking(session->socket_fd);
746

747
        if(session->socket_prev_blockstate) {
748
            /* If in blocking state change to non-blocking */
749
            rc = session_nonblock(session->socket_fd, 1);
750
            if(rc) {
751
                return _libssh2_error(session, rc,
752
                                      "Failed changing socket's "
753
                                      "blocking state to non-blocking");
754
            }
755
        }
756

757
        session->startup_state = libssh2_NB_state_created;
758
    }
759

760
    if(session->startup_state == libssh2_NB_state_created) {
761
        rc = banner_send(session);
762
        if(rc == LIBSSH2_ERROR_EAGAIN)
763
            return rc;
764
        else if(rc) {
765
            return _libssh2_error(session, rc,
766
                                  "Failed sending banner");
767
        }
768
        session->startup_state = libssh2_NB_state_sent;
769
        session->banner_TxRx_state = libssh2_NB_state_idle;
770
    }
771

772
    if(session->startup_state == libssh2_NB_state_sent) {
773
        do {
774
            rc = banner_receive(session);
775
            if(rc == LIBSSH2_ERROR_EAGAIN)
776
                return rc;
777
            else if(rc)
778
                return _libssh2_error(session, rc,
779
                                      "Failed getting banner");
780
        } while(strncmp("SSH-", (const char *)session->remote.banner, 4));
781

782
        session->startup_state = libssh2_NB_state_sent1;
783
    }
784

785
    if(session->startup_state == libssh2_NB_state_sent1) {
786
        rc = _libssh2_kex_exchange(session, 0, &session->startup_key_state);
787
        if(rc == LIBSSH2_ERROR_EAGAIN)
788
            return rc;
789
        else if(rc)
790
            return _libssh2_error(session, rc,
791
                                  "Unable to exchange encryption keys");
792

793
        session->startup_state = libssh2_NB_state_sent2;
794
    }
795

796
    if(session->startup_state == libssh2_NB_state_sent2) {
797
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
798
                       "Requesting userauth service"));
799

800
        /* Request the userauth service */
801
        session->startup_service[0] = SSH_MSG_SERVICE_REQUEST;
802
        _libssh2_htonu32(session->startup_service + 1,
803
                         sizeof("ssh-userauth") - 1);
804
        memcpy(session->startup_service + 5, "ssh-userauth",
805
               sizeof("ssh-userauth") - 1);
806

807
        session->startup_state = libssh2_NB_state_sent3;
808
    }
809

810
    if(session->startup_state == libssh2_NB_state_sent3) {
811
        rc = _libssh2_transport_send(session, session->startup_service,
812
                                     sizeof("ssh-userauth") + 5 - 1,
813
                                     NULL, 0);
814
        if(rc == LIBSSH2_ERROR_EAGAIN)
815
            return rc;
816
        else if(rc) {
817
            return _libssh2_error(session, rc,
818
                                  "Unable to ask for ssh-userauth service");
819
        }
820

821
        session->startup_state = libssh2_NB_state_sent4;
822
    }
823

824
    if(session->startup_state == libssh2_NB_state_sent4) {
825
        rc = _libssh2_packet_require(session, SSH_MSG_SERVICE_ACCEPT,
826
                                     &session->startup_data,
827
                                     &session->startup_data_len, 0, NULL, 0,
828
                                     &session->startup_req_state);
829
        if(rc)
830
            return _libssh2_error(session, rc,
831
                                  "Failed to get response to "
832
                                  "ssh-userauth request");
833

834
        if(session->startup_data_len < 5) {
835
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
836
                                  "Unexpected packet length");
837
        }
838

839
        session->startup_service_length =
840
            _libssh2_ntohu32(session->startup_data + 1);
841

842

843
        if((session->startup_service_length != (sizeof("ssh-userauth") - 1))
844
            || strncmp("ssh-userauth",
845
                       (const char *) session->startup_data + 5,
846
                       session->startup_service_length)) {
847
            LIBSSH2_FREE(session, session->startup_data);
848
            session->startup_data = NULL;
849
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
850
                                  "Invalid response received from server");
851
        }
852
        LIBSSH2_FREE(session, session->startup_data);
853
        session->startup_data = NULL;
854

855
        session->startup_state = libssh2_NB_state_idle;
856

857
        return 0;
858
    }
859

860
    /* just for safety return some error */
861
    return LIBSSH2_ERROR_INVAL;
862
}
863

864
/*
865
 * libssh2_session_handshake
866
 *
867
 * session: LIBSSH2_SESSION struct allocated and owned by the calling program
868
 * sock:    *must* be populated with an opened and connected socket.
869
 *
870
 * Returns: 0 on success, or non-zero on failure
871
 */
872
LIBSSH2_API int
873
libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock)
874
{
875
    int rc;
876

877
    BLOCK_ADJUST(rc, session, session_startup(session, sock));
878

879
    return rc;
880
}
881

882
#ifndef LIBSSH2_NO_DEPRECATED
883
/*
884
 * libssh2_session_startup
885
 *
886
 * DEPRECATED. Use libssh2_session_handshake() instead! This function is not
887
 * portable enough.
888
 *
889
 * session: LIBSSH2_SESSION struct allocated and owned by the calling program
890
 * sock:    *must* be populated with an opened and connected socket.
891
 *
892
 * Returns: 0 on success, or non-zero on failure
893
 */
894
LIBSSH2_API int
895
libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
896
{
897
    return libssh2_session_handshake(session, (libssh2_socket_t) sock);
898
}
899
#endif
900

901
/*
902
 * session_free
903
 *
904
 * Frees the memory allocated to the session
905
 * Also closes and frees any channels attached to this session
906
 */
907
static int
908
session_free(LIBSSH2_SESSION *session)
909
{
910
    int rc;
911
    LIBSSH2_PACKET *pkg;
912
    LIBSSH2_CHANNEL *ch;
913
    LIBSSH2_LISTENER *l;
914
    int packets_left = 0;
915

916
    if(session->free_state == libssh2_NB_state_idle) {
917
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
918
                       "Freeing session resource %p",
919
                       (void *)session->remote.banner));
920

921
        session->free_state = libssh2_NB_state_created;
922
    }
923

924
    if(session->free_state == libssh2_NB_state_created) {
925
        /* !checksrc! disable EQUALSNULL 1 */
926
        while((ch = _libssh2_list_first(&session->channels)) != NULL) {
927
            rc = _libssh2_channel_free(ch);
928
            if(rc == LIBSSH2_ERROR_EAGAIN)
929
                return rc;
930
        }
931

932
        session->free_state = libssh2_NB_state_sent;
933
    }
934

935
    if(session->free_state == libssh2_NB_state_sent) {
936
        /* !checksrc! disable EQUALSNULL 1 */
937
        while((l = _libssh2_list_first(&session->listeners)) != NULL) {
938
            rc = _libssh2_channel_forward_cancel(l);
939
            if(rc == LIBSSH2_ERROR_EAGAIN)
940
                return rc;
941
        }
942

943
        session->free_state = libssh2_NB_state_sent1;
944
    }
945

946
    if(session->state & LIBSSH2_STATE_NEWKEYS) {
947
        /* hostkey */
948
        if(session->hostkey && session->hostkey->dtor) {
949
            session->hostkey->dtor(session, &session->server_hostkey_abstract);
950
        }
951

952
        /* Client to Server */
953
        /* crypt */
954
        if(session->local.crypt && session->local.crypt->dtor) {
955
            session->local.crypt->dtor(session,
956
                                       &session->local.crypt_abstract);
957
        }
958
        /* comp */
959
        if(session->local.comp && session->local.comp->dtor) {
960
            session->local.comp->dtor(session, 1,
961
                                      &session->local.comp_abstract);
962
        }
963
        /* mac */
964
        if(session->local.mac && session->local.mac->dtor) {
965
            session->local.mac->dtor(session, &session->local.mac_abstract);
966
        }
967

968
        /* Server to Client */
969
        /* crypt */
970
        if(session->remote.crypt && session->remote.crypt->dtor) {
971
            session->remote.crypt->dtor(session,
972
                                        &session->remote.crypt_abstract);
973
        }
974
        /* comp */
975
        if(session->remote.comp && session->remote.comp->dtor) {
976
            session->remote.comp->dtor(session, 0,
977
                                       &session->remote.comp_abstract);
978
        }
979
        /* mac */
980
        if(session->remote.mac && session->remote.mac->dtor) {
981
            session->remote.mac->dtor(session, &session->remote.mac_abstract);
982
        }
983

984
        /* session_id */
985
        if(session->session_id) {
986
            LIBSSH2_FREE(session, session->session_id);
987
        }
988
    }
989

990
    /* Free banner(s) */
991
    if(session->remote.banner) {
992
        LIBSSH2_FREE(session, session->remote.banner);
993
    }
994
    if(session->local.banner) {
995
        LIBSSH2_FREE(session, session->local.banner);
996
    }
997

998
    /* Free preference(s) */
999
    if(session->kex_prefs) {
1000
        LIBSSH2_FREE(session, session->kex_prefs);
1001
    }
1002
    if(session->hostkey_prefs) {
1003
        LIBSSH2_FREE(session, session->hostkey_prefs);
1004
    }
1005

1006
    if(session->local.kexinit) {
1007
        LIBSSH2_FREE(session, session->local.kexinit);
1008
    }
1009
    if(session->local.crypt_prefs) {
1010
        LIBSSH2_FREE(session, session->local.crypt_prefs);
1011
    }
1012
    if(session->local.mac_prefs) {
1013
        LIBSSH2_FREE(session, session->local.mac_prefs);
1014
    }
1015
    if(session->local.comp_prefs) {
1016
        LIBSSH2_FREE(session, session->local.comp_prefs);
1017
    }
1018
    if(session->local.lang_prefs) {
1019
        LIBSSH2_FREE(session, session->local.lang_prefs);
1020
    }
1021

1022
    if(session->remote.kexinit) {
1023
        LIBSSH2_FREE(session, session->remote.kexinit);
1024
    }
1025
    if(session->remote.crypt_prefs) {
1026
        LIBSSH2_FREE(session, session->remote.crypt_prefs);
1027
    }
1028
    if(session->remote.mac_prefs) {
1029
        LIBSSH2_FREE(session, session->remote.mac_prefs);
1030
    }
1031
    if(session->remote.comp_prefs) {
1032
        LIBSSH2_FREE(session, session->remote.comp_prefs);
1033
    }
1034
    if(session->remote.lang_prefs) {
1035
        LIBSSH2_FREE(session, session->remote.lang_prefs);
1036
    }
1037
    if(session->server_sign_algorithms) {
1038
        LIBSSH2_FREE(session, session->server_sign_algorithms);
1039
    }
1040
    if(session->sign_algo_prefs) {
1041
        LIBSSH2_FREE(session, session->sign_algo_prefs);
1042
    }
1043

1044
    /*
1045
     * Make sure all memory used in the state variables are free
1046
     */
1047
    if(session->kexinit_data) {
1048
        LIBSSH2_FREE(session, session->kexinit_data);
1049
    }
1050
    if(session->startup_data) {
1051
        LIBSSH2_FREE(session, session->startup_data);
1052
    }
1053
    if(session->userauth_list_data) {
1054
        LIBSSH2_FREE(session, session->userauth_list_data);
1055
    }
1056
    if(session->userauth_banner) {
1057
        LIBSSH2_FREE(session, session->userauth_banner);
1058
    }
1059
    if(session->userauth_pswd_data) {
1060
        LIBSSH2_FREE(session, session->userauth_pswd_data);
1061
    }
1062
    if(session->userauth_pswd_newpw) {
1063
        LIBSSH2_FREE(session, session->userauth_pswd_newpw);
1064
    }
1065
    if(session->userauth_host_packet) {
1066
        LIBSSH2_FREE(session, session->userauth_host_packet);
1067
    }
1068
    if(session->userauth_host_method) {
1069
        LIBSSH2_FREE(session, session->userauth_host_method);
1070
    }
1071
    if(session->userauth_host_data) {
1072
        LIBSSH2_FREE(session, session->userauth_host_data);
1073
    }
1074
    if(session->userauth_pblc_data) {
1075
        LIBSSH2_FREE(session, session->userauth_pblc_data);
1076
    }
1077
    if(session->userauth_pblc_packet) {
1078
        LIBSSH2_FREE(session, session->userauth_pblc_packet);
1079
    }
1080
    if(session->userauth_pblc_method) {
1081
        LIBSSH2_FREE(session, session->userauth_pblc_method);
1082
    }
1083
    if(session->userauth_kybd_data) {
1084
        LIBSSH2_FREE(session, session->userauth_kybd_data);
1085
    }
1086
    if(session->userauth_kybd_packet) {
1087
        LIBSSH2_FREE(session, session->userauth_kybd_packet);
1088
    }
1089
    if(session->userauth_kybd_auth_instruction) {
1090
        LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
1091
    }
1092
    if(session->open_packet) {
1093
        LIBSSH2_FREE(session, session->open_packet);
1094
    }
1095
    if(session->open_data) {
1096
        LIBSSH2_FREE(session, session->open_data);
1097
    }
1098
    if(session->direct_message) {
1099
        LIBSSH2_FREE(session, session->direct_message);
1100
    }
1101
    if(session->fwdLstn_packet) {
1102
        LIBSSH2_FREE(session, session->fwdLstn_packet);
1103
    }
1104
    if(session->pkeyInit_data) {
1105
        LIBSSH2_FREE(session, session->pkeyInit_data);
1106
    }
1107
    if(session->scpRecv_command) {
1108
        LIBSSH2_FREE(session, session->scpRecv_command);
1109
    }
1110
    if(session->scpSend_command) {
1111
        LIBSSH2_FREE(session, session->scpSend_command);
1112
    }
1113
    if(session->sftpInit_sftp) {
1114
        LIBSSH2_FREE(session, session->sftpInit_sftp);
1115
    }
1116

1117
    /* Free payload buffer */
1118
    if(session->packet.total_num) {
1119
        LIBSSH2_FREE(session, session->packet.payload);
1120
    }
1121

1122
    /* Cleanup all remaining packets */
1123
    /* !checksrc! disable EQUALSNULL 1 */
1124
    while((pkg = _libssh2_list_first(&session->packets)) != NULL) {
1125
        packets_left++;
1126
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1127
                       "packet left with id %d", pkg->data[0]));
1128
        /* unlink the node */
1129
        _libssh2_list_remove(&pkg->node);
1130

1131
        /* free */
1132
        LIBSSH2_FREE(session, pkg->data);
1133
        LIBSSH2_FREE(session, pkg);
1134
    }
1135
    (void)packets_left;
1136
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1137
                   "Extra packets left %d", packets_left));
1138

1139
    if(session->socket_prev_blockstate) {
1140
        /* if the socket was previously blocking, put it back so */
1141
        rc = session_nonblock(session->socket_fd, 0);
1142
        if(rc) {
1143
            _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1144
                           "unable to reset socket's blocking state"));
1145
        }
1146
    }
1147

1148
    if(session->server_hostkey) {
1149
        LIBSSH2_FREE(session, session->server_hostkey);
1150
    }
1151

1152
    /* error string */
1153
    if(session->err_msg &&
1154
       ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
1155
        LIBSSH2_FREE(session, (char *)session->err_msg);
1156
    }
1157

1158
    LIBSSH2_FREE(session, session);
1159

1160
    return 0;
1161
}
1162

1163
/*
1164
 * libssh2_session_free
1165
 *
1166
 * Frees the memory allocated to the session
1167
 * Also closes and frees any channels attached to this session
1168
 */
1169
LIBSSH2_API int
1170
libssh2_session_free(LIBSSH2_SESSION * session)
1171
{
1172
    int rc;
1173

1174
    BLOCK_ADJUST(rc, session, session_free(session));
1175

1176
    return rc;
1177
}
1178

1179
/*
1180
 * session_disconnect
1181
 */
1182
static int
1183
session_disconnect(LIBSSH2_SESSION *session, int reason,
1184
                   const char *description,
1185
                   const char *lang)
1186
{
1187
    unsigned char *s;
1188
    size_t descr_len = 0, lang_len = 0;
1189
    int rc;
1190

1191
    if(session->disconnect_state == libssh2_NB_state_idle) {
1192
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1193
                       "Disconnecting: reason=%d, desc=%s, lang=%s", reason,
1194
                       description, lang));
1195
        if(description)
1196
            descr_len = strlen(description);
1197

1198
        if(lang)
1199
            lang_len = strlen(lang);
1200

1201
        if(descr_len > 256)
1202
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1203
                                  "too long description");
1204

1205
        if(lang_len > 256)
1206
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1207
                                  "too long language string");
1208

1209
        /* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
1210
        session->disconnect_data_len = descr_len + lang_len + 13;
1211

1212
        s = session->disconnect_data;
1213

1214
        *(s++) = SSH_MSG_DISCONNECT;
1215
        _libssh2_store_u32(&s, reason);
1216
        _libssh2_store_str(&s, description, descr_len);
1217
        /* store length only, lang is sent separately */
1218
        _libssh2_store_u32(&s, (uint32_t)lang_len);
1219

1220
        session->disconnect_state = libssh2_NB_state_created;
1221
    }
1222

1223
    rc = _libssh2_transport_send(session, session->disconnect_data,
1224
                                 session->disconnect_data_len,
1225
                                 (const unsigned char *)lang, lang_len);
1226
    if(rc == LIBSSH2_ERROR_EAGAIN)
1227
        return rc;
1228

1229
    session->disconnect_state = libssh2_NB_state_idle;
1230

1231
    return 0;
1232
}
1233

1234
/*
1235
 * libssh2_session_disconnect_ex
1236
 */
1237
LIBSSH2_API int
1238
libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
1239
                              const char *desc, const char *lang)
1240
{
1241
    int rc;
1242
    session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
1243
    session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
1244
    BLOCK_ADJUST(rc, session,
1245
                 session_disconnect(session, reason, desc, lang));
1246

1247
    return rc;
1248
}
1249

1250
/* libssh2_session_methods
1251
 *
1252
 * Return the currently active methods for method_type
1253
 *
1254
 * NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string
1255
 * regardless of actual negotiation Strings should NOT be freed
1256
 */
1257
LIBSSH2_API const char *
1258
libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
1259
{
1260
    /* All methods have char *name as their first element */
1261
    const LIBSSH2_KEX_METHOD *method = NULL;
1262

1263
    switch(method_type) {
1264
    case LIBSSH2_METHOD_KEX:
1265
        method = session->kex;
1266
        break;
1267

1268
    case LIBSSH2_METHOD_HOSTKEY:
1269
        method = (LIBSSH2_KEX_METHOD *) session->hostkey;
1270
        break;
1271

1272
    case LIBSSH2_METHOD_CRYPT_CS:
1273
        method = (LIBSSH2_KEX_METHOD *) session->local.crypt;
1274
        break;
1275

1276
    case LIBSSH2_METHOD_CRYPT_SC:
1277
        method = (LIBSSH2_KEX_METHOD *) session->remote.crypt;
1278
        break;
1279

1280
    case LIBSSH2_METHOD_MAC_CS:
1281
        method = (LIBSSH2_KEX_METHOD *) session->local.mac;
1282
        break;
1283

1284
    case LIBSSH2_METHOD_MAC_SC:
1285
        method = (LIBSSH2_KEX_METHOD *) session->remote.mac;
1286
        break;
1287

1288
    case LIBSSH2_METHOD_COMP_CS:
1289
        method = (LIBSSH2_KEX_METHOD *) session->local.comp;
1290
        break;
1291

1292
    case LIBSSH2_METHOD_COMP_SC:
1293
        method = (LIBSSH2_KEX_METHOD *) session->remote.comp;
1294
        break;
1295

1296
    case LIBSSH2_METHOD_LANG_CS:
1297
        return "";
1298

1299
    case LIBSSH2_METHOD_LANG_SC:
1300
        return "";
1301

1302
    default:
1303
        _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1304
                       "Invalid parameter specified for method_type");
1305
        return NULL;
1306
    }
1307

1308
    if(!method) {
1309
        _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
1310
                       "No method negotiated");
1311
        return NULL;
1312
    }
1313

1314
    return method->name;
1315
}
1316

1317
/* libssh2_session_abstract
1318
 * Retrieve a pointer to the abstract property
1319
 */
1320
LIBSSH2_API void **
1321
libssh2_session_abstract(LIBSSH2_SESSION * session)
1322
{
1323
    return &session->abstract;
1324
}
1325

1326
/* libssh2_session_last_error
1327
 *
1328
 * Returns error code and populates an error string into errmsg If want_buf is
1329
 * non-zero then the string placed into errmsg must be freed by the calling
1330
 * program. Otherwise it is assumed to be owned by libssh2
1331
 */
1332
LIBSSH2_API int
1333
libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
1334
                           int *errmsg_len, int want_buf)
1335
{
1336
    size_t msglen = 0;
1337

1338
    /* No error to report */
1339
    if(!session->err_code) {
1340
        if(errmsg) {
1341
            if(want_buf) {
1342
                *errmsg = LIBSSH2_ALLOC(session, 1);
1343
                if(*errmsg) {
1344
                    **errmsg = 0;
1345
                }
1346
            }
1347
            else {
1348
                *errmsg = (char *) "";
1349
            }
1350
        }
1351
        if(errmsg_len) {
1352
            *errmsg_len = 0;
1353
        }
1354
        return 0;
1355
    }
1356

1357
    if(errmsg) {
1358
        const char *error = session->err_msg ? session->err_msg : "";
1359

1360
        msglen = strlen(error);
1361

1362
        if(want_buf) {
1363
            /* Make a copy so the calling program can own it */
1364
            *errmsg = LIBSSH2_ALLOC(session, msglen + 1);
1365
            if(*errmsg) {
1366
                memcpy(*errmsg, error, msglen);
1367
                (*errmsg)[msglen] = 0;
1368
            }
1369
        }
1370
        else
1371
            *errmsg = (char *)error;
1372
    }
1373

1374
    if(errmsg_len) {
1375
        *errmsg_len = (int)msglen;
1376
    }
1377

1378
    return session->err_code;
1379
}
1380

1381
/* libssh2_session_last_errno
1382
 *
1383
 * Returns error code
1384
 */
1385
LIBSSH2_API int
1386
libssh2_session_last_errno(LIBSSH2_SESSION * session)
1387
{
1388
    return session->err_code;
1389
}
1390

1391
/* libssh2_session_set_last_error
1392
 *
1393
 * Sets the internal error code for the session.
1394
 *
1395
 * This function is available specifically to be used by high level
1396
 * language wrappers (i.e. Python or Perl) that may extend the library
1397
 * features while still relying on its error reporting mechanism.
1398
 */
1399
LIBSSH2_API int
1400
libssh2_session_set_last_error(LIBSSH2_SESSION* session,
1401
                               int errcode,
1402
                               const char *errmsg)
1403
{
1404
    return _libssh2_error_flags(session, errcode, errmsg,
1405
                                LIBSSH2_ERR_FLAG_DUP);
1406
}
1407

1408
/* libssh2_session_flag
1409
 *
1410
 * Set/Get session flags
1411
 *
1412
 * Return error code.
1413
 */
1414
LIBSSH2_API int
1415
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
1416
{
1417
    switch(flag) {
1418
    case LIBSSH2_FLAG_SIGPIPE:
1419
        session->flag.sigpipe = value;
1420
        break;
1421
    case LIBSSH2_FLAG_COMPRESS:
1422
        session->flag.compress = value;
1423
        break;
1424
    case LIBSSH2_FLAG_QUOTE_PATHS:
1425
        session->flag.quote_paths = value;
1426
        break;
1427
    default:
1428
        /* unknown flag */
1429
        return LIBSSH2_ERROR_INVAL;
1430
    }
1431

1432
    return LIBSSH2_ERROR_NONE;
1433
}
1434

1435
/* _libssh2_session_set_blocking
1436
 *
1437
 * Set a session's blocking mode on or off, return the previous status when
1438
 * this function is called. Note this function does not alter the state of the
1439
 * actual socket involved.
1440
 */
1441
int
1442
_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
1443
{
1444
    int bl = session->api_block_mode;
1445
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1446
                   "Setting blocking mode %s", blocking ? "ON" : "OFF"));
1447
    session->api_block_mode = blocking;
1448

1449
    return bl;
1450
}
1451

1452
/* libssh2_session_set_blocking
1453
 *
1454
 * Set a channel's blocking mode on or off, similar to a socket's
1455
 * fcntl(fd, F_SETFL, O_NONBLOCK); type command
1456
 */
1457
LIBSSH2_API void
1458
libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
1459
{
1460
    (void)_libssh2_session_set_blocking(session, blocking);
1461
}
1462

1463
/* libssh2_session_get_blocking
1464
 *
1465
 * Returns a session's blocking mode on or off
1466
 */
1467
LIBSSH2_API int
1468
libssh2_session_get_blocking(LIBSSH2_SESSION * session)
1469
{
1470
    return session->api_block_mode;
1471
}
1472

1473

1474
/* libssh2_session_set_timeout
1475
 *
1476
 * Set a session's timeout (in msec) for blocking mode,
1477
 * or 0 to disable timeouts.
1478
 */
1479
LIBSSH2_API void
1480
libssh2_session_set_timeout(LIBSSH2_SESSION * session, long timeout)
1481
{
1482
    session->api_timeout = timeout;
1483
}
1484

1485
/* libssh2_session_get_timeout
1486
 *
1487
 * Returns a session's timeout, or 0 if disabled
1488
 */
1489
LIBSSH2_API long
1490
libssh2_session_get_timeout(LIBSSH2_SESSION * session)
1491
{
1492
    return session->api_timeout;
1493
}
1494

1495
/* libssh2_session_set_read_timeout
1496
 *
1497
 * Set a session's timeout (in sec) when reading packets,
1498
 * or 0 to use default of 60 seconds.
1499
 */
1500
LIBSSH2_API void
1501
libssh2_session_set_read_timeout(LIBSSH2_SESSION * session, long timeout)
1502
{
1503
    if(timeout <= 0) {
1504
        timeout = LIBSSH2_DEFAULT_READ_TIMEOUT;
1505
    }
1506
    session->packet_read_timeout = timeout;
1507
}
1508

1509
/* libssh2_session_get_read_timeout
1510
 *
1511
 * Returns a session's timeout. Default is 60 seconds.
1512
 */
1513
LIBSSH2_API long
1514
libssh2_session_get_read_timeout(LIBSSH2_SESSION * session)
1515
{
1516
    return session->packet_read_timeout;
1517
}
1518

1519
/*
1520
 * libssh2_poll_channel_read
1521
 *
1522
 * Returns 0 if no data is waiting on channel,
1523
 * non-0 if data is available
1524
 */
1525
LIBSSH2_API int
1526
libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended)
1527
{
1528
    LIBSSH2_SESSION *session;
1529
    LIBSSH2_PACKET *packet;
1530

1531
    if(!channel)
1532
        return LIBSSH2_ERROR_BAD_USE;
1533

1534
    session = channel->session;
1535
    packet = _libssh2_list_first(&session->packets);
1536

1537
    while(packet) {
1538
        if(packet->data_len < 5) {
1539
            return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
1540
                                  "Packet too small");
1541
        }
1542

1543
        if(channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
1544
            if(extended == 1 &&
1545
                (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
1546
                 || packet->data[0] == SSH_MSG_CHANNEL_DATA)) {
1547
                return 1;
1548
            }
1549
            else if(extended == 0 &&
1550
                    packet->data[0] == SSH_MSG_CHANNEL_DATA) {
1551
                return 1;
1552
            }
1553
            /* else - no data of any type is ready to be read */
1554
        }
1555
        packet = _libssh2_list_next(&packet->node);
1556
    }
1557

1558
    return 0;
1559
}
1560

1561
/*
1562
 * poll_channel_write
1563
 *
1564
 * Returns 0 if writing to channel would block,
1565
 * non-0 if data can be written without blocking
1566
 */
1567
static inline int
1568
poll_channel_write(LIBSSH2_CHANNEL * channel)
1569
{
1570
    return channel->local.window_size ? 1 : 0;
1571
}
1572

1573
/* poll_listener_queued
1574
 *
1575
 * Returns 0 if no connections are waiting to be accepted
1576
 * non-0 if one or more connections are available
1577
 */
1578
static inline int
1579
poll_listener_queued(LIBSSH2_LISTENER * listener)
1580
{
1581
    return _libssh2_list_first(&listener->queue) ? 1 : 0;
1582
}
1583

1584
/*
1585
 * libssh2_poll
1586
 *
1587
 * Poll sockets, channels, and listeners for activity
1588
 */
1589
LIBSSH2_API int
1590
libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
1591
{
1592
    long timeout_remaining;
1593
    unsigned int i, active_fds;
1594
#ifdef HAVE_POLL
1595
    LIBSSH2_SESSION *session = NULL;
1596
#ifdef HAVE_ALLOCA
1597
    struct pollfd *sockets = alloca(sizeof(struct pollfd) * nfds);
1598
#else
1599
    struct pollfd sockets[256];
1600

1601
    if(nfds > 256)
1602
        /* systems without alloca use a fixed-size array, this can be fixed if
1603
           we really want to, at least if the compiler is a C99 capable one */
1604
        return -1;
1605
#endif
1606
    /* Setup sockets for polling */
1607
    for(i = 0; i < nfds; i++) {
1608
        fds[i].revents = 0;
1609
        switch(fds[i].type) {
1610
        case LIBSSH2_POLLFD_SOCKET:
1611
            sockets[i].fd = fds[i].fd.socket;
1612
            sockets[i].events = (short)fds[i].events;
1613
            sockets[i].revents = 0;
1614
            break;
1615

1616
        case LIBSSH2_POLLFD_CHANNEL:
1617
            sockets[i].fd = fds[i].fd.channel->session->socket_fd;
1618
            sockets[i].events = POLLIN;
1619
            sockets[i].revents = 0;
1620
            if(!session)
1621
                session = fds[i].fd.channel->session;
1622
            break;
1623

1624
        case LIBSSH2_POLLFD_LISTENER:
1625
            sockets[i].fd = fds[i].fd.listener->session->socket_fd;
1626
            sockets[i].events = POLLIN;
1627
            sockets[i].revents = 0;
1628
            if(!session)
1629
                session = fds[i].fd.listener->session;
1630
            break;
1631

1632
        default:
1633
            if(session)
1634
                _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
1635
                               "Invalid descriptor passed to libssh2_poll()");
1636
            return -1;
1637
        }
1638
    }
1639
#elif defined(HAVE_SELECT)
1640
    LIBSSH2_SESSION *session = NULL;
1641
    libssh2_socket_t maxfd = 0;
1642
    fd_set rfds, wfds;
1643
    struct timeval tv;
1644

1645
    FD_ZERO(&rfds);
1646
    FD_ZERO(&wfds);
1647
    for(i = 0; i < nfds; i++) {
1648
        fds[i].revents = 0;
1649
        switch(fds[i].type) {
1650
        case LIBSSH2_POLLFD_SOCKET:
1651
            if(fds[i].events & LIBSSH2_POLLFD_POLLIN) {
1652
#if defined(__GNUC__)
1653
#pragma GCC diagnostic push
1654
#pragma GCC diagnostic ignored "-Wsign-conversion"
1655
#endif
1656
                FD_SET(fds[i].fd.socket, &rfds);
1657
#if defined(__GNUC__)
1658
#pragma GCC diagnostic pop
1659
#endif
1660
                if(fds[i].fd.socket > maxfd)
1661
                    maxfd = fds[i].fd.socket;
1662
            }
1663
            if(fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
1664
#if defined(__GNUC__)
1665
#pragma GCC diagnostic push
1666
#pragma GCC diagnostic ignored "-Wsign-conversion"
1667
#endif
1668
                FD_SET(fds[i].fd.socket, &wfds);
1669
#if defined(__GNUC__)
1670
#pragma GCC diagnostic pop
1671
#endif
1672
                if(fds[i].fd.socket > maxfd)
1673
                    maxfd = fds[i].fd.socket;
1674
            }
1675
            break;
1676

1677
        case LIBSSH2_POLLFD_CHANNEL:
1678
#if defined(__GNUC__)
1679
#pragma GCC diagnostic push
1680
#pragma GCC diagnostic ignored "-Wsign-conversion"
1681
#endif
1682
            FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
1683
#if defined(__GNUC__)
1684
#pragma GCC diagnostic pop
1685
#endif
1686
            if(fds[i].fd.channel->session->socket_fd > maxfd)
1687
                maxfd = fds[i].fd.channel->session->socket_fd;
1688
            if(!session)
1689
                session = fds[i].fd.channel->session;
1690
            break;
1691

1692
        case LIBSSH2_POLLFD_LISTENER:
1693
#if defined(__GNUC__)
1694
#pragma GCC diagnostic push
1695
#pragma GCC diagnostic ignored "-Wsign-conversion"
1696
#endif
1697
            FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
1698
#if defined(__GNUC__)
1699
#pragma GCC diagnostic pop
1700
#endif
1701
            if(fds[i].fd.listener->session->socket_fd > maxfd)
1702
                maxfd = fds[i].fd.listener->session->socket_fd;
1703
            if(!session)
1704
                session = fds[i].fd.listener->session;
1705
            break;
1706

1707
        default:
1708
            if(session)
1709
                _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
1710
                               "Invalid descriptor passed to libssh2_poll()");
1711
            return -1;
1712
        }
1713
    }
1714
#else
1715
    /* No select() or poll()
1716
     * no sockets structure to setup
1717
     */
1718

1719
    timeout = 0;
1720
#endif /* HAVE_POLL or HAVE_SELECT */
1721

1722
    timeout_remaining = timeout;
1723
    do {
1724
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
1725
        int sysret;
1726
#endif
1727

1728
        active_fds = 0;
1729

1730
        for(i = 0; i < nfds; i++) {
1731
            if(fds[i].events != fds[i].revents) {
1732
                switch(fds[i].type) {
1733
                case LIBSSH2_POLLFD_CHANNEL:
1734
                    if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
1735
                        /* Want to be ready for read */
1736
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
1737
                        /* Not yet known to be ready for read */
1738
                        fds[i].revents |=
1739
                            libssh2_poll_channel_read(fds[i].fd.channel,
1740
                                                      0) ?
1741
                            LIBSSH2_POLLFD_POLLIN : 0;
1742
                    }
1743
                    if((fds[i].events & LIBSSH2_POLLFD_POLLEXT) &&
1744
                        /* Want to be ready for extended read */
1745
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) {
1746
                        /* Not yet known to be ready for extended read */
1747
                        fds[i].revents |=
1748
                            libssh2_poll_channel_read(fds[i].fd.channel,
1749
                                                      1) ?
1750
                            LIBSSH2_POLLFD_POLLEXT : 0;
1751
                    }
1752
                    if((fds[i].events & LIBSSH2_POLLFD_POLLOUT) &&
1753
                        /* Want to be ready for write */
1754
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) {
1755
                        /* Not yet known to be ready for write */
1756
                        fds[i].revents |=
1757
                            poll_channel_write(fds[i].fd. channel) ?
1758
                            LIBSSH2_POLLFD_POLLOUT : 0;
1759
                    }
1760
                    if(fds[i].fd.channel->remote.close
1761
                        || fds[i].fd.channel->local.close) {
1762
                        fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED;
1763
                    }
1764
                    if(fds[i].fd.channel->session->socket_state ==
1765
                        LIBSSH2_SOCKET_DISCONNECTED) {
1766
                        fds[i].revents |=
1767
                            LIBSSH2_POLLFD_CHANNEL_CLOSED |
1768
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1769
                    }
1770
                    break;
1771

1772
                case LIBSSH2_POLLFD_LISTENER:
1773
                    if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
1774
                        /* Want a connection */
1775
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
1776
                        /* No connections known of yet */
1777
                        fds[i].revents |=
1778
                            poll_listener_queued(fds[i].fd. listener) ?
1779
                            LIBSSH2_POLLFD_POLLIN : 0;
1780
                    }
1781
                    if(fds[i].fd.listener->session->socket_state ==
1782
                        LIBSSH2_SOCKET_DISCONNECTED) {
1783
                        fds[i].revents |=
1784
                            LIBSSH2_POLLFD_LISTENER_CLOSED |
1785
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1786
                    }
1787
                    break;
1788
                }
1789
            }
1790
            if(fds[i].revents) {
1791
                active_fds++;
1792
            }
1793
        }
1794

1795
        if(active_fds) {
1796
            /* Don't block on the sockets if we have channels/listeners which
1797
               are ready */
1798
            timeout_remaining = 0;
1799
        }
1800
#ifdef HAVE_POLL
1801

1802
        {
1803
            struct timeval tv_begin, tv_end;
1804

1805
            gettimeofday(&tv_begin, NULL);
1806
            sysret = poll(sockets, nfds, (int)timeout_remaining);
1807
            gettimeofday(&tv_end, NULL);
1808
            timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
1809
            timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
1810
        }
1811

1812
        if(sysret > 0) {
1813
            for(i = 0; i < nfds; i++) {
1814
                switch(fds[i].type) {
1815
                case LIBSSH2_POLLFD_SOCKET:
1816
                    fds[i].revents = sockets[i].revents;
1817
                    sockets[i].revents = 0; /* In case we loop again, be
1818
                                               nice */
1819
                    if(fds[i].revents) {
1820
                        active_fds++;
1821
                    }
1822
                    break;
1823
                case LIBSSH2_POLLFD_CHANNEL:
1824
                    if(sockets[i].events & POLLIN) {
1825
                        /* Spin session until no data available */
1826
                        while(_libssh2_transport_read(fds[i].fd.
1827
                                                      channel->session)
1828
                              > 0);
1829
                    }
1830
                    if(sockets[i].revents & POLLHUP) {
1831
                        fds[i].revents |=
1832
                            LIBSSH2_POLLFD_CHANNEL_CLOSED |
1833
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1834
                    }
1835
                    sockets[i].revents = 0;
1836
                    break;
1837
                case LIBSSH2_POLLFD_LISTENER:
1838
                    if(sockets[i].events & POLLIN) {
1839
                        /* Spin session until no data available */
1840
                        while(_libssh2_transport_read(fds[i].fd.
1841
                                                      listener->session)
1842
                              > 0);
1843
                    }
1844
                    if(sockets[i].revents & POLLHUP) {
1845
                        fds[i].revents |=
1846
                            LIBSSH2_POLLFD_LISTENER_CLOSED |
1847
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1848
                    }
1849
                    sockets[i].revents = 0;
1850
                    break;
1851
                }
1852
            }
1853
        }
1854
#elif defined(HAVE_SELECT)
1855
        tv.tv_sec = timeout_remaining / 1000;
1856
#ifdef libssh2_usec_t
1857
        tv.tv_usec = (libssh2_usec_t)((timeout_remaining % 1000) * 1000);
1858
#else
1859
        tv.tv_usec = (timeout_remaining % 1000) * 1000;
1860
#endif
1861

1862
        {
1863
            struct timeval tv_begin, tv_end;
1864

1865
            gettimeofday(&tv_begin, NULL);
1866
            sysret = select((int)(maxfd + 1), &rfds, &wfds, NULL, &tv);
1867
            gettimeofday(&tv_end, NULL);
1868

1869
            timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
1870
            timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
1871
        }
1872

1873
        if(sysret > 0) {
1874
            for(i = 0; i < nfds; i++) {
1875
                switch(fds[i].type) {
1876
                case LIBSSH2_POLLFD_SOCKET:
1877
#if defined(__GNUC__)
1878
#pragma GCC diagnostic push
1879
#pragma GCC diagnostic ignored "-Wsign-conversion"
1880
#endif
1881
                    if(FD_ISSET(fds[i].fd.socket, &rfds)) {
1882
                        fds[i].revents |= LIBSSH2_POLLFD_POLLIN;
1883
                    }
1884
                    if(FD_ISSET(fds[i].fd.socket, &wfds)) {
1885
                        fds[i].revents |= LIBSSH2_POLLFD_POLLOUT;
1886
                    }
1887
                    if(fds[i].revents) {
1888
                        active_fds++;
1889
                    }
1890
#if defined(__GNUC__)
1891
#pragma GCC diagnostic pop
1892
#endif
1893
                    break;
1894

1895
                case LIBSSH2_POLLFD_CHANNEL:
1896
                    if(FD_ISSET(fds[i].fd.channel->session->socket_fd,
1897
                                &rfds)) {
1898
                        /* Spin session until no data available */
1899
                        while(_libssh2_transport_read(fds[i].fd.
1900
                                                      channel->session)
1901
                              > 0);
1902
                    }
1903
                    break;
1904

1905
                case LIBSSH2_POLLFD_LISTENER:
1906
                    if(FD_ISSET
1907
                        (fds[i].fd.listener->session->socket_fd, &rfds)) {
1908
                        /* Spin session until no data available */
1909
                        while(_libssh2_transport_read(fds[i].fd.
1910
                                                      listener->session)
1911
                              > 0);
1912
                    }
1913
                    break;
1914
                }
1915
            }
1916
        }
1917
#endif /* else no select() or poll() -- timeout (and by extension
1918
        * timeout_remaining) will be equal to 0 */
1919
    } while((timeout_remaining > 0) && !active_fds);
1920

1921
    return active_fds;
1922
}
1923

1924
/*
1925
 * libssh2_session_block_directions
1926
 *
1927
 * Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
1928
 * Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked
1929
 * or LIBSSH2_SOCKET_BLOCK_OUTBOUND if send() blocked
1930
 */
1931
LIBSSH2_API int
1932
libssh2_session_block_directions(LIBSSH2_SESSION *session)
1933
{
1934
    return session->socket_block_directions;
1935
}
1936

1937
/* libssh2_session_banner_get
1938
 * Get the remote banner (server ID string)
1939
 */
1940

1941
LIBSSH2_API const char *
1942
libssh2_session_banner_get(LIBSSH2_SESSION *session)
1943
{
1944
    /* to avoid a coredump when session is NULL */
1945
    if(!session)
1946
        return NULL;
1947

1948
    if(!session->remote.banner)
1949
        return NULL;
1950

1951
    return (const char *) session->remote.banner;
1952
}
1953

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.