aboutsummaryrefslogtreecommitdiff
path: root/src/common/fakepoll.c
blob: 712f2bd3655e58c611dba7d265c812145c6936b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* Copyright 2002,2003 Nick Mathewson, Roger Dingledine */
/* See LICENSE for licensing information */
/* $Id$ */
const char fakepoll_c_id[] = "$Id$";

/**
 * \file fakepoll.c
 *
 * \brief On systems where poll() doesn't exist, fake it with select().
 **/

#include "orconfig.h"
#include "fakepoll.h"

#define MAXCONNECTIONS 10000 /* XXXX copied from or.h */
#define FD_SETSIZE MAXCONNECTIONS

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif

#include <assert.h>
#include <stdlib.h>
#include "util.h"
#include "log.h"

#ifndef USE_FAKE_POLL
int
tor_poll(struct pollfd *ufds, unsigned int nfds, int timeout)
{
        unsigned int i;
        for (i=0;i<nfds;++i) {
                tor_assert(ufds[i].fd >= 0);
        }
        return poll(ufds,nfds,timeout);
}
#else

int
tor_poll(struct pollfd *ufds, unsigned int nfds, int timeout)
{
        unsigned int idx;
        int maxfd, fd;
        int r;
#ifdef MS_WINDOWS
        int any_fds_set = 0;
#endif
        fd_set readfds, writefds, exceptfds;
#ifdef USING_FAKE_TIMEVAL
#undef timeval
#undef tv_sec
#undef tv_usec
#endif
        struct timeval _timeout;
        _timeout.tv_sec = timeout/1000;
        _timeout.tv_usec = (timeout%1000)*1000;
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);
        FD_ZERO(&exceptfds);

        maxfd = -1;
        for (idx = 0; idx < nfds; ++idx) {
                ufds[idx].revents = 0;
                fd = ufds[idx].fd;
                tor_assert(fd >= 0);
                if (fd > maxfd) {
                  maxfd = fd;
#ifdef MS_WINDOWS
                  any_fds_set = 1;
#endif
                }
                if (ufds[idx].events & POLLIN)
                        FD_SET(fd, &readfds);
                if (ufds[idx].events & POLLOUT)
                        FD_SET(fd, &writefds);
                FD_SET(fd, &exceptfds);
        }
#ifdef MS_WINDOWS
        if (!any_fds_set) {
                Sleep(timeout);
                return 0;
        }
#endif
        r = select(maxfd+1, &readfds, &writefds, &exceptfds,
                   timeout == -1 ? NULL : &_timeout);
        if (r <= 0)
                return r;
        r = 0;
        for (idx = 0; idx < nfds; ++idx) {
                fd = ufds[idx].fd;
                if (FD_ISSET(fd, &readfds))
                        ufds[idx].revents |= POLLIN;
                if (FD_ISSET(fd, &writefds))
                        ufds[idx].revents |= POLLOUT;
                if (FD_ISSET(fd, &exceptfds))
                        ufds[idx].revents |= POLLERR;
                if (ufds[idx].revents)
                        ++r;
        }
        return r;
}
#endif