~ubuntu-branches/ubuntu/precise/libssh/precise

« back to all changes in this revision

Viewing changes to src/poll.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-06-15 15:48:07 UTC
  • mfrom: (1.1.10 upstream) (4.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20110615154807-3muklcqfftr1vtch
Tags: 0.5.0-2
* debian/patches/0002-Check-for-NULL-pointers-in-string-c.patch:
  Consolidate patch (Should fix previous REJECT)
* Support multiarch spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * poll.c - poll wrapper
 
3
 *
 
4
 * This file is part of the SSH Library
 
5
 *
 
6
 * Copyright (c) 2009-2010 by Andreas Schneider <mail@cynapses.org>
 
7
 * Copyright (c) 2003-2009 by Aris Adamantiadis
 
8
 * Copyright (c) 2009 Aleksandar Kanchev
 
9
 *
 
10
 * The SSH Library is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU Lesser General Public License as published by
 
12
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 
13
 * option) any later version.
 
14
 *
 
15
 * The SSH Library is distributed in the hope that it will be useful, but
 
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
17
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
18
 * License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU Lesser General Public License
 
21
 * along with the SSH Library; see the file COPYING.  If not, write to
 
22
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
23
 * MA 02111-1307, USA.
 
24
 *
 
25
 * vim: ts=2 sw=2 et cindent
 
26
 */
 
27
 
 
28
#include "config.h"
 
29
 
 
30
#include <errno.h>
 
31
 
 
32
#include "libssh/priv.h"
 
33
#include "libssh/libssh.h"
 
34
#include "libssh/poll.h"
 
35
#include "libssh/socket.h"
 
36
#include "libssh/session.h"
 
37
 
 
38
#ifndef SSH_POLL_CTX_CHUNK
 
39
#define SSH_POLL_CTX_CHUNK                      5
 
40
#endif
 
41
 
 
42
/**
 
43
 * @defgroup libssh_poll The SSH poll functions.
 
44
 * @ingroup libssh
 
45
 *
 
46
 * Add a generic way to handle sockets asynchronously.
 
47
 *
 
48
 * It's based on poll objects, each of which store a socket, its events and a
 
49
 * callback, which gets called whenever an event is set. The poll objects are
 
50
 * attached to a poll context, which should be allocated on per thread basis.
 
51
 *
 
52
 * Polling the poll context will poll all the attached poll objects and call
 
53
 * their callbacks (handlers) if any of the socket events are set. This should
 
54
 * be done within the main loop of an application.
 
55
 *
 
56
 * @{
 
57
 */
 
58
 
 
59
struct ssh_poll_handle_struct {
 
60
  ssh_poll_ctx ctx;
 
61
  union {
 
62
    socket_t fd;
 
63
    size_t idx;
 
64
  } x;
 
65
  short events;
 
66
  ssh_poll_callback cb;
 
67
  void *cb_data;
 
68
};
 
69
 
 
70
struct ssh_poll_ctx_struct {
 
71
  ssh_poll_handle *pollptrs;
 
72
  ssh_pollfd_t *pollfds;
 
73
  size_t polls_allocated;
 
74
  size_t polls_used;
 
75
  size_t chunk_size;
 
76
};
 
77
 
 
78
#ifdef HAVE_POLL
 
79
#include <poll.h>
 
80
 
 
81
void ssh_poll_init(void) {
 
82
    return;
 
83
}
 
84
 
 
85
void ssh_poll_cleanup(void) {
 
86
    return;
 
87
}
 
88
 
 
89
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
 
90
  return poll((struct pollfd *) fds, nfds, timeout);
 
91
}
 
92
 
 
93
#else /* HAVE_POLL */
 
94
 
 
95
typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int);
 
96
static poll_fn ssh_poll_emu;
 
97
 
 
98
#include <sys/types.h>
 
99
 
 
100
#ifdef _WIN32
 
101
#ifndef STRICT
 
102
#define STRICT
 
103
#endif /* STRICT */
 
104
 
 
105
#include <time.h>
 
106
#include <windows.h>
 
107
#include <winsock2.h>
 
108
#else /* _WIN32 */
 
109
#include <sys/select.h>
 
110
#include <sys/socket.h>
 
111
#include <unistd.h>
 
112
#include <sys/time.h>
 
113
#endif /* _WIN32 */
 
114
 
 
115
 
 
116
/*
 
117
 * This is a poll(2)-emulation using select for systems not providing a native
 
118
 * poll implementation.
 
119
 *
 
120
 * Keep in mind that select is terribly inefficient. The interface is simply not
 
121
 * meant to be used with maximum descriptor value greater, say, 32 or so.  With
 
122
 * a value as high as 1024 on Linux you'll pay dearly in every single call.
 
123
 * poll() will be orders of magnitude faster.
 
124
 */
 
125
static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
 
126
  fd_set readfds, writefds, exceptfds;
 
127
  struct timeval tv, *ptv;
 
128
  socket_t max_fd;
 
129
  int rc;
 
130
  nfds_t i;
 
131
 
 
132
  if (fds == NULL) {
 
133
      errno = EFAULT;
 
134
      return -1;
 
135
  }
 
136
 
 
137
  FD_ZERO (&readfds);
 
138
  FD_ZERO (&writefds);
 
139
  FD_ZERO (&exceptfds);
 
140
 
 
141
  /* compute fd_sets and find largest descriptor */
 
142
  for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
 
143
      if (fds[i].fd == SSH_INVALID_SOCKET) {
 
144
          continue;
 
145
      }
 
146
#ifndef _WIN32
 
147
      if (fds[i].fd >= FD_SETSIZE) {
 
148
          rc = -1;
 
149
          break;
 
150
      }
 
151
#endif
 
152
 
 
153
      if (fds[i].events & (POLLIN | POLLRDNORM)) {
 
154
          FD_SET (fds[i].fd, &readfds);
 
155
      }
 
156
      if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
 
157
          FD_SET (fds[i].fd, &writefds);
 
158
      }
 
159
      if (fds[i].events & (POLLPRI | POLLRDBAND)) {
 
160
          FD_SET (fds[i].fd, &exceptfds);
 
161
      }
 
162
      if (fds[i].fd > max_fd &&
 
163
          (fds[i].events & (POLLIN | POLLOUT | POLLPRI |
 
164
                            POLLRDNORM | POLLRDBAND |
 
165
                            POLLWRNORM | POLLWRBAND))) {
 
166
          max_fd = fds[i].fd;
 
167
          rc = 0;
 
168
      }
 
169
  }
 
170
 
 
171
  if (max_fd == SSH_INVALID_SOCKET || rc == -1) {
 
172
      errno = EINVAL;
 
173
      return -1;
 
174
  }
 
175
 
 
176
  if (timeout < 0) {
 
177
      ptv = NULL;
 
178
  } else {
 
179
      ptv = &tv;
 
180
      if (timeout == 0) {
 
181
          tv.tv_sec = 0;
 
182
          tv.tv_usec = 0;
 
183
      } else {
 
184
          tv.tv_sec = timeout / 1000;
 
185
          tv.tv_usec = (timeout % 1000) * 1000;
 
186
      }
 
187
  }
 
188
 
 
189
  rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
 
190
  if (rc < 0) {
 
191
      return -1;
 
192
  }
 
193
 
 
194
  for (rc = 0, i = 0; i < nfds; i++)
 
195
    if (fds[i].fd >= 0) {
 
196
        fds[i].revents = 0;
 
197
 
 
198
        if (FD_ISSET(fds[i].fd, &readfds)) {
 
199
            int save_errno = errno;
 
200
            char data[64] = {0};
 
201
            int ret;
 
202
 
 
203
            /* support for POLLHUP */
 
204
            ret = recv(fds[i].fd, data, 64, MSG_PEEK);
 
205
#ifdef _WIN32
 
206
            if ((ret == -1) &&
 
207
                (errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
 
208
                 errno == WSAECONNABORTED || errno == WSAENETRESET)) {
 
209
#else
 
210
            if ((ret == -1) &&
 
211
                (errno == ESHUTDOWN || errno == ECONNRESET ||
 
212
                 errno == ECONNABORTED || errno == ENETRESET)) {
 
213
#endif
 
214
                fds[i].revents |= POLLHUP;
 
215
            } else {
 
216
                fds[i].revents |= fds[i].events & (POLLIN | POLLRDNORM);
 
217
            }
 
218
 
 
219
            errno = save_errno;
 
220
        }
 
221
        if (FD_ISSET(fds[i].fd, &writefds)) {
 
222
            fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND);
 
223
        }
 
224
 
 
225
        if (FD_ISSET(fds[i].fd, &exceptfds)) {
 
226
            fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND);
 
227
        }
 
228
 
 
229
        if (fds[i].revents & ~POLLHUP) {
 
230
          rc++;
 
231
        }
 
232
    } else {
 
233
        fds[i].revents = POLLNVAL;
 
234
    }
 
235
 
 
236
  return rc;
 
237
}
 
238
 
 
239
void ssh_poll_init(void) {
 
240
    ssh_poll_emu = bsd_poll;
 
241
}
 
242
 
 
243
void ssh_poll_cleanup(void) {
 
244
    ssh_poll_emu = bsd_poll;
 
245
}
 
246
 
 
247
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
 
248
    return (ssh_poll_emu)(fds, nfds, timeout);
 
249
}
 
250
 
 
251
#endif /* HAVE_POLL */
 
252
 
 
253
/**
 
254
 * @brief  Allocate a new poll object, which could be used within a poll context.
 
255
 *
 
256
 * @param  fd           Socket that will be polled.
 
257
 * @param  events       Poll events that will be monitored for the socket. i.e.
 
258
 *                      POLLIN, POLLPRI, POLLOUT
 
259
 * @param  cb           Function to be called if any of the events are set.
 
260
 *
 
261
 * @param  userdata     Userdata to be passed to the callback function. NULL if
 
262
 *                      not needed.
 
263
 *
 
264
 * @return              A new poll object, NULL on error
 
265
 */
 
266
 
 
267
ssh_poll_handle ssh_poll_new(socket_t fd, short events, ssh_poll_callback cb,
 
268
    void *userdata) {
 
269
    ssh_poll_handle p;
 
270
 
 
271
    p = malloc(sizeof(struct ssh_poll_handle_struct));
 
272
    if (p == NULL) {
 
273
        return NULL;
 
274
    }
 
275
    ZERO_STRUCTP(p);
 
276
 
 
277
    p->x.fd = fd;
 
278
    p->events = events;
 
279
    if (cb != NULL) {
 
280
        p->cb = cb;
 
281
    }
 
282
    if (userdata != NULL) {
 
283
        p->cb_data = userdata;
 
284
    }
 
285
 
 
286
    return p;
 
287
}
 
288
 
 
289
 
 
290
/**
 
291
 * @brief  Free a poll object.
 
292
 *
 
293
 * @param  p            Pointer to an already allocated poll object.
 
294
 */
 
295
 
 
296
void ssh_poll_free(ssh_poll_handle p) {
 
297
        if(p->ctx != NULL){
 
298
                ssh_poll_ctx_remove(p->ctx,p);
 
299
                p->ctx=NULL;
 
300
        }
 
301
  SAFE_FREE(p);
 
302
}
 
303
 
 
304
/**
 
305
 * @brief  Get the poll context of a poll object.
 
306
 *
 
307
 * @param  p            Pointer to an already allocated poll object.
 
308
 *
 
309
 * @return              Poll context or NULL if the poll object isn't attached.
 
310
 */
 
311
ssh_poll_ctx ssh_poll_get_ctx(ssh_poll_handle p) {
 
312
  return p->ctx;
 
313
}
 
314
 
 
315
/**
 
316
 * @brief  Get the events of a poll object.
 
317
 *
 
318
 * @param  p            Pointer to an already allocated poll object.
 
319
 *
 
320
 * @return              Poll events.
 
321
 */
 
322
short ssh_poll_get_events(ssh_poll_handle p) {
 
323
  return p->events;
 
324
}
 
325
 
 
326
/**
 
327
 * @brief  Set the events of a poll object. The events will also be propagated
 
328
 *         to an associated poll context.
 
329
 *
 
330
 * @param  p            Pointer to an already allocated poll object.
 
331
 * @param  events       Poll events.
 
332
 */
 
333
void ssh_poll_set_events(ssh_poll_handle p, short events) {
 
334
  p->events = events;
 
335
  if (p->ctx != NULL) {
 
336
    p->ctx->pollfds[p->x.idx].events = events;
 
337
  }
 
338
}
 
339
 
 
340
/**
 
341
 * @brief  Set the file descriptor of a poll object. The FD will also be propagated
 
342
 *         to an associated poll context.
 
343
 *
 
344
 * @param  p            Pointer to an already allocated poll object.
 
345
 * @param  fd       New file descriptor.
 
346
 */
 
347
void ssh_poll_set_fd(ssh_poll_handle p, socket_t fd) {
 
348
  if (p->ctx != NULL) {
 
349
    p->ctx->pollfds[p->x.idx].fd = fd;
 
350
  } else {
 
351
        p->x.fd = fd;
 
352
  }
 
353
}
 
354
 
 
355
/**
 
356
 * @brief  Add extra events to a poll object. Duplicates are ignored.
 
357
 *         The events will also be propagated to an associated poll context.
 
358
 *
 
359
 * @param  p            Pointer to an already allocated poll object.
 
360
 * @param  events       Poll events.
 
361
 */
 
362
void ssh_poll_add_events(ssh_poll_handle p, short events) {
 
363
  ssh_poll_set_events(p, ssh_poll_get_events(p) | events);
 
364
}
 
365
 
 
366
/**
 
367
 * @brief  Remove events from a poll object. Non-existent are ignored.
 
368
 *         The events will also be propagated to an associated poll context.
 
369
 *
 
370
 * @param  p            Pointer to an already allocated poll object.
 
371
 * @param  events       Poll events.
 
372
 */
 
373
void ssh_poll_remove_events(ssh_poll_handle p, short events) {
 
374
  ssh_poll_set_events(p, ssh_poll_get_events(p) & ~events);
 
375
}
 
376
 
 
377
/**
 
378
 * @brief  Get the raw socket of a poll object.
 
379
 *
 
380
 * @param  p            Pointer to an already allocated poll object.
 
381
 *
 
382
 * @return              Raw socket.
 
383
 */
 
384
 
 
385
socket_t ssh_poll_get_fd(ssh_poll_handle p) {
 
386
  if (p->ctx != NULL) {
 
387
    return p->ctx->pollfds[p->x.idx].fd;
 
388
  }
 
389
 
 
390
  return p->x.fd;
 
391
}
 
392
/**
 
393
 * @brief  Set the callback of a poll object.
 
394
 *
 
395
 * @param  p            Pointer to an already allocated poll object.
 
396
 * @param  cb           Function to be called if any of the events are set.
 
397
 * @param  userdata     Userdata to be passed to the callback function. NULL if
 
398
 *                      not needed.
 
399
 */
 
400
void ssh_poll_set_callback(ssh_poll_handle p, ssh_poll_callback cb, void *userdata) {
 
401
  if (cb != NULL) {
 
402
    p->cb = cb;
 
403
    p->cb_data = userdata;
 
404
  }
 
405
}
 
406
 
 
407
/**
 
408
 * @brief  Create a new poll context. It could be associated with many poll object
 
409
 *         which are going to be polled at the same time as the poll context. You
 
410
 *         would need a single poll context per thread.
 
411
 *
 
412
 * @param  chunk_size   The size of the memory chunk that will be allocated, when
 
413
 *                      more memory is needed. This is for efficiency reasons,
 
414
 *                      i.e. don't allocate memory for each new poll object, but
 
415
 *                      for the next 5. Set it to 0 if you want to use the
 
416
 *                      library's default value.
 
417
 */
 
418
ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size) {
 
419
    ssh_poll_ctx ctx;
 
420
 
 
421
    ctx = malloc(sizeof(struct ssh_poll_ctx_struct));
 
422
    if (ctx == NULL) {
 
423
        return NULL;
 
424
    }
 
425
    ZERO_STRUCTP(ctx);
 
426
 
 
427
    if (chunk_size == 0) {
 
428
        chunk_size = SSH_POLL_CTX_CHUNK;
 
429
    }
 
430
 
 
431
    ctx->chunk_size = chunk_size;
 
432
 
 
433
    return ctx;
 
434
}
 
435
 
 
436
/**
 
437
 * @brief  Free a poll context.
 
438
 *
 
439
 * @param  ctx          Pointer to an already allocated poll context.
 
440
 */
 
441
void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
 
442
  if (ctx->polls_allocated > 0) {
 
443
    register size_t i, used;
 
444
 
 
445
    used = ctx->polls_used;
 
446
    for (i = 0; i < used; ) {
 
447
      ssh_poll_handle p = ctx->pollptrs[i];
 
448
      socket_t fd = ctx->pollfds[i].fd;
 
449
 
 
450
      /* force poll object removal */
 
451
      if (p->cb && p->cb(p, fd, POLLERR, p->cb_data) < 0) {
 
452
        if(ctx->polls_used < used) {
 
453
            used = ctx->polls_used;
 
454
        } else {
 
455
            /* nothing to do */
 
456
            i++;
 
457
        }
 
458
      } else {
 
459
        i++;
 
460
      }
 
461
    }
 
462
 
 
463
    SAFE_FREE(ctx->pollptrs);
 
464
    SAFE_FREE(ctx->pollfds);
 
465
  }
 
466
 
 
467
  SAFE_FREE(ctx);
 
468
}
 
469
 
 
470
static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size) {
 
471
  ssh_poll_handle *pollptrs;
 
472
  ssh_pollfd_t *pollfds;
 
473
 
 
474
  pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle *) * new_size);
 
475
  if (pollptrs == NULL) {
 
476
    return -1;
 
477
  }
 
478
 
 
479
  pollfds = realloc(ctx->pollfds, sizeof(ssh_pollfd_t) * new_size);
 
480
  if (pollfds == NULL) {
 
481
    ctx->pollptrs = realloc(pollptrs, sizeof(ssh_poll_handle *) * ctx->polls_allocated);
 
482
    return -1;
 
483
  }
 
484
 
 
485
  ctx->pollptrs = pollptrs;
 
486
  ctx->pollfds = pollfds;
 
487
  ctx->polls_allocated = new_size;
 
488
 
 
489
  return 0;
 
490
}
 
491
 
 
492
/**
 
493
 * @brief  Add a poll object to a poll context.
 
494
 *
 
495
 * @param  ctx          Pointer to an already allocated poll context.
 
496
 * @param  p            Pointer to an already allocated poll object.
 
497
 *
 
498
 * @return              0 on success, < 0 on error
 
499
 */
 
500
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
 
501
  socket_t fd;
 
502
 
 
503
  if (p->ctx != NULL) {
 
504
    /* already attached to a context */
 
505
    return -1;
 
506
  }
 
507
 
 
508
  if (ctx->polls_used == ctx->polls_allocated &&
 
509
      ssh_poll_ctx_resize(ctx, ctx->polls_allocated + ctx->chunk_size) < 0) {
 
510
    return -1;
 
511
  }
 
512
 
 
513
  fd = p->x.fd;
 
514
  p->x.idx = ctx->polls_used++;
 
515
  ctx->pollptrs[p->x.idx] = p;
 
516
  ctx->pollfds[p->x.idx].fd = fd;
 
517
  ctx->pollfds[p->x.idx].events = p->events;
 
518
  ctx->pollfds[p->x.idx].revents = 0;
 
519
  p->ctx = ctx;
 
520
 
 
521
  return 0;
 
522
}
 
523
 
 
524
/**
 
525
 * @brief  Add a socket object to a poll context.
 
526
 *
 
527
 * @param  ctx          Pointer to an already allocated poll context.
 
528
 * @param  s            A SSH socket handle
 
529
 *
 
530
 * @return              0 on success, < 0 on error
 
531
 */
 
532
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, ssh_socket s) {
 
533
  ssh_poll_handle p_in, p_out;
 
534
  int ret;
 
535
  p_in=ssh_socket_get_poll_handle_in(s);
 
536
  if(p_in==NULL)
 
537
        return -1;
 
538
  ret = ssh_poll_ctx_add(ctx,p_in);
 
539
  if(ret != 0)
 
540
    return ret;
 
541
  p_out=ssh_socket_get_poll_handle_out(s);
 
542
  if(p_in != p_out)
 
543
    ret = ssh_poll_ctx_add(ctx,p_out);
 
544
  return ret;
 
545
}
 
546
 
 
547
 
 
548
/**
 
549
 * @brief  Remove a poll object from a poll context.
 
550
 *
 
551
 * @param  ctx          Pointer to an already allocated poll context.
 
552
 * @param  p            Pointer to an already allocated poll object.
 
553
 */
 
554
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) {
 
555
  size_t i;
 
556
 
 
557
  i = p->x.idx;
 
558
  p->x.fd = ctx->pollfds[i].fd;
 
559
  p->ctx = NULL;
 
560
 
 
561
  ctx->polls_used--;
 
562
 
 
563
  /* fill the empty poll slot with the last one */
 
564
  if (ctx->polls_used > 0 && ctx->polls_used != i) {
 
565
    ctx->pollfds[i] = ctx->pollfds[ctx->polls_used];
 
566
    ctx->pollptrs[i] = ctx->pollptrs[ctx->polls_used];
 
567
  }
 
568
 
 
569
  /* this will always leave at least chunk_size polls allocated */
 
570
  if (ctx->polls_allocated - ctx->polls_used > ctx->chunk_size) {
 
571
    ssh_poll_ctx_resize(ctx, ctx->polls_allocated - ctx->chunk_size);
 
572
  }
 
573
}
 
574
 
 
575
/**
 
576
 * @brief  Poll all the sockets associated through a poll object with a
 
577
 *         poll context. If any of the events are set after the poll, the
 
578
 *         call back function of the socket will be called.
 
579
 *         This function should be called once within the programs main loop.
 
580
 *
 
581
 * @param  ctx          Pointer to an already allocated poll context.
 
582
 * @param  timeout      An upper limit on the time for which ssh_poll_ctx() will
 
583
 *                      block, in milliseconds. Specifying a negative value
 
584
 *                      means an infinite timeout. This parameter is passed to
 
585
 *                      the poll() function.
 
586
 * @returns SSH_OK      No error.
 
587
 *          SSH_ERROR   Error happened during the poll.
 
588
 *          SSH_AGAIN   Timeout occured
 
589
 */
 
590
 
 
591
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
 
592
  int rc;
 
593
  int i, used;
 
594
  ssh_poll_handle p;
 
595
  socket_t fd;
 
596
  int revents;
 
597
 
 
598
  if (!ctx->polls_used)
 
599
    return 0;
 
600
 
 
601
  rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
 
602
  if(rc < 0)
 
603
    return SSH_ERROR;
 
604
  if (rc == 0)
 
605
    return SSH_AGAIN;
 
606
  used = ctx->polls_used;
 
607
  for (i = 0; i < used && rc > 0; ) {
 
608
    if (!ctx->pollfds[i].revents) {
 
609
      i++;
 
610
    } else {
 
611
      p = ctx->pollptrs[i];
 
612
      fd = ctx->pollfds[i].fd;
 
613
      revents = ctx->pollfds[i].revents;
 
614
 
 
615
      if (p->cb(p, fd, revents, p->cb_data) < 0) {
 
616
        /* the poll was removed, reload the used counter and start again */
 
617
        used = ctx->polls_used;
 
618
        i=0;
 
619
      } else {
 
620
        ctx->pollfds[i].revents = 0;
 
621
        i++;
 
622
      }
 
623
 
 
624
      rc--;
 
625
    }
 
626
  }
 
627
 
 
628
  return rc;
 
629
}
 
630
 
 
631
/**
 
632
 * @internal
 
633
 * @brief gets the default poll structure for the current session,
 
634
 * when used in blocking mode.
 
635
 * @param session SSH session
 
636
 * @returns the default ssh_poll_ctx
 
637
 */
 
638
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session){
 
639
        if(session->default_poll_ctx != NULL)
 
640
                return session->default_poll_ctx;
 
641
        /* 2 is enough for the default one */
 
642
        session->default_poll_ctx = ssh_poll_ctx_new(2);
 
643
        return session->default_poll_ctx;
 
644
}
 
645
 
 
646
/** @} */
 
647
 
 
648
/* vim: set ts=4 sw=4 et cindent: */