Code updates which makes things compile as C++. Mostly type casts were
[yaz-moved-to-github.git] / src / zoom-socket.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: zoom-socket.c,v 1.4 2007-05-06 20:12:20 adam Exp $
6  */
7 /**
8  * \file zoom-socket.c
9  * \brief Implements ZOOM C socket interface.
10  */
11
12 #include <assert.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <yaz/zoom.h>
16
17 #include <yaz/log.h>
18 #include <yaz/xmalloc.h>
19
20 #if HAVE_SYS_TYPES_H
21 #include <sys/types.h>
22 #endif
23 #if HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #endif
26 #if HAVE_SYS_POLL_H
27 #include <sys/poll.h>
28 #endif
29 #if HAVE_SYS_SELECT_H
30 #include <sys/select.h>
31 #endif
32 #ifdef WIN32
33 #if FD_SETSIZE < 512
34 #define FD_SETSIZE 512
35 #endif
36 #include <winsock.h>
37 #endif
38
39
40 /*
41  * Note that ZOOM_event_sys_select() is limited as to how many file
42  * descriptors it can multiplex due to its use of select() which in
43  * turn uses the statically defined fd_set type to be a bitmap of the
44  * file descriptors to check.  On Ubuntu 6.06 (and almost certainly on
45  * Debian, and probably on all Linuxes, and maybe all Unixes) this is
46  * by default set to 1024 (though it may be possible to override this
47  * using a #define before including <sys/select.h> -- I've not tried
48  * this).  1024 file descriptors is a lot, but not enough in all
49  * cases, e.g. when running IRSpy on a large target database.  So you
50  * should ensure that YAZ uses ZOOM_event_sys_poll() when possible.
51  */
52 ZOOM_API(int)
53     ZOOM_event_sys_select(int no, ZOOM_connection *cs)
54 {
55     struct timeval tv;
56     fd_set input, output, except;
57     int i, r;
58     int max_fd = 0;
59     int timeout = 30;
60     int nfds = 0;
61
62     FD_ZERO(&input);
63     FD_ZERO(&output);
64     FD_ZERO(&except);
65
66     for (i = 0; i<no; i++)
67     {
68         ZOOM_connection c = cs[i];
69         int fd, mask;
70         
71         if (!c)
72             continue;
73         fd = ZOOM_connection_get_socket(c);
74         mask = ZOOM_connection_get_mask(c);
75         timeout = ZOOM_connection_get_timeout(c);
76
77         if (fd == -1)
78             continue;
79         if (max_fd < fd)
80             max_fd = fd;
81         
82         if (mask & ZOOM_SELECT_READ)
83             FD_SET(fd, &input);
84         if (mask & ZOOM_SELECT_WRITE)
85             FD_SET(fd, &output);
86         if (mask & ZOOM_SELECT_EXCEPT)
87             FD_SET(fd, &except);
88         if (mask)
89             nfds++;
90     }
91     if (nfds == 0)
92         return 0;
93
94     tv.tv_sec = timeout;
95     tv.tv_usec = 0;
96
97     while ((r = select(max_fd+1, &input, &output, &except,
98                        (timeout == -1 ? 0 : &tv))) < 0 && errno == EINTR)
99     {
100         ;
101     }
102     if (r < 0)
103     {
104         yaz_log(YLOG_WARN|YLOG_ERRNO, "ZOOM_event_sys_select");
105         return r;
106     }
107
108     for (i = 0; i<no; i++)
109     {
110         ZOOM_connection c = cs[i];
111         int fd, mask;
112
113         if (!c)
114             continue;
115         fd = ZOOM_connection_get_socket(c);
116         mask = 0;
117         if (r)
118         {
119             /* no timeout and real socket */
120             if (FD_ISSET(fd, &input))
121                 mask += ZOOM_SELECT_READ;
122             if (FD_ISSET(fd, &output))
123                 mask += ZOOM_SELECT_WRITE;
124             if (FD_ISSET(fd, &except))
125                 mask += ZOOM_SELECT_EXCEPT;
126             if (mask)
127                 ZOOM_connection_fire_event_socket(c, mask);
128         }
129         else
130             ZOOM_connection_fire_event_timeout(c);
131     }
132     return r;
133 }
134
135 #if HAVE_SYS_POLL_H
136 ZOOM_API(int)
137     ZOOM_event_sys_poll(int no, ZOOM_connection *cs)
138 {
139     struct pollfd *pollfds = (struct pollfd *) xmalloc(no * sizeof *pollfds);
140     ZOOM_connection *poll_cs = (ZOOM_connection *)
141         xmalloc(no * sizeof *poll_cs);
142     int i, r;
143     int nfds = 0;
144     int timeout = 30;
145
146     for (i = 0; i<no; i++)
147     {
148         ZOOM_connection c = cs[i];
149         int fd, mask;
150         
151         if (!c)
152             continue;
153         fd = ZOOM_connection_get_socket(c);
154         mask = ZOOM_connection_get_mask(c);
155         timeout = ZOOM_connection_get_timeout(c);
156
157         if (fd == -1)
158             continue;
159         if (mask)
160         {
161             short poll_events = 0;
162
163             if (mask & ZOOM_SELECT_READ)
164                 poll_events += POLLIN;
165             if (mask & ZOOM_SELECT_WRITE)
166                 poll_events += POLLOUT;
167             if (mask & ZOOM_SELECT_EXCEPT)
168                 poll_events += POLLERR;
169             pollfds[nfds].fd = fd;
170             pollfds[nfds].events = poll_events;
171             pollfds[nfds].revents = 0;
172             poll_cs[nfds] = c;
173             nfds++;
174         }
175     }
176     if (nfds == 0) {
177         xfree(pollfds);
178         xfree(poll_cs);
179         return 0;
180     }
181     while ((r = poll(pollfds, nfds,
182          (timeout == -1 ? -1 : timeout * 1000))) < 0
183           && errno == EINTR)
184     {
185         ;
186     }
187     if (r < 0)
188     {
189         yaz_log(YLOG_WARN|YLOG_ERRNO, "ZOOM_event_sys_poll");
190         xfree(pollfds);
191         xfree(poll_cs);
192         return r;
193     }
194     for (i = 0; i<nfds; i++)
195     {
196         ZOOM_connection c = poll_cs[i];
197         if (r)
198         {
199             int mask = 0;
200             if (pollfds[i].revents & POLLIN)
201                 mask += ZOOM_SELECT_READ;
202             if (pollfds[i].revents & POLLOUT)
203                 mask += ZOOM_SELECT_WRITE;
204             if (pollfds[i].revents & POLLERR)
205                 mask += ZOOM_SELECT_EXCEPT;
206             ZOOM_connection_fire_event_socket(c, mask);
207         }
208         else
209             ZOOM_connection_fire_event_timeout(c);
210     }
211     xfree(pollfds);
212     xfree(poll_cs);
213     return r;
214 }
215 #endif
216
217 ZOOM_API(int)
218     ZOOM_event(int no, ZOOM_connection *cs)
219 {
220     int r;
221
222     r = ZOOM_event_nonblock(no, cs);
223     if (r)
224         return r;
225 #if HAVE_SYS_POLL_H
226     ZOOM_event_sys_poll(no, cs);
227 #else
228     ZOOM_event_sys_select(no, cs);
229 #endif
230     return ZOOM_event_nonblock(no, cs);
231 }
232
233 /*
234  * Local variables:
235  * c-basic-offset: 4
236  * indent-tabs-mode: nil
237  * End:
238  * vim: shiftwidth=4 tabstop=8 expandtab
239  */
240