Fixed bug #830: pkg-config support. YAZ installs yaz.pc for Debian
[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.2 2007-01-12 21:03:31 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
19 #if HAVE_SYS_TYPES_H
20 #include <sys/types.h>
21 #endif
22 #if HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
25 #if HAVE_SYS_POLL_H
26 #include <sys/poll.h>
27 #endif
28 #if HAVE_SYS_SELECT_H
29 #include <sys/select.h>
30 #endif
31 #ifdef WIN32
32 #if FD_SETSIZE < 512
33 #define FD_SETSIZE 512
34 #endif
35 #include <winsock.h>
36 #endif
37
38
39 ZOOM_API(int)
40     ZOOM_event_sys_select(int no, ZOOM_connection *cs)
41 {
42     struct timeval tv;
43     fd_set input, output, except;
44     int i, r;
45     int max_fd = 0;
46     int timeout = 30;
47     int nfds = 0;
48
49     FD_ZERO(&input);
50     FD_ZERO(&output);
51     FD_ZERO(&except);
52
53     for (i = 0; i<no; i++)
54     {
55         ZOOM_connection c = cs[i];
56         int fd, mask;
57         
58         if (!c)
59             continue;
60         fd = ZOOM_connection_get_socket(c);
61         mask = ZOOM_connection_get_mask(c);
62         timeout = ZOOM_connection_get_timeout(c);
63
64         if (fd == -1)
65             continue;
66         if (max_fd < fd)
67             max_fd = fd;
68         
69         if (mask & ZOOM_SELECT_READ)
70             FD_SET(fd, &input);
71         if (mask & ZOOM_SELECT_WRITE)
72             FD_SET(fd, &output);
73         if (mask & ZOOM_SELECT_EXCEPT)
74             FD_SET(fd, &except);
75         if (mask)
76             nfds++;
77     }
78     if (nfds == 0)
79         return 0;
80
81     tv.tv_sec = timeout;
82     tv.tv_usec = 0;
83
84     while ((r = select(max_fd+1, &input, &output, &except,
85                        (timeout == -1 ? 0 : &tv))) < 0 && errno == EINTR)
86     {
87         ;
88     }
89     if (r < 0)
90     {
91         yaz_log(YLOG_WARN|YLOG_ERRNO, "ZOOM_event_sys_select");
92         return r;
93     }
94
95     for (i = 0; i<no; i++)
96     {
97         ZOOM_connection c = cs[i];
98         int fd, mask;
99
100         if (!c)
101             continue;
102         fd = ZOOM_connection_get_socket(c);
103         mask = 0;
104         if (r)
105         {
106             /* no timeout and real socket */
107             if (FD_ISSET(fd, &input))
108                 mask += ZOOM_SELECT_READ;
109             if (FD_ISSET(fd, &output))
110                 mask += ZOOM_SELECT_WRITE;
111             if (FD_ISSET(fd, &except))
112                 mask += ZOOM_SELECT_EXCEPT;
113             if (mask)
114                 ZOOM_connection_fire_event_socket(c, mask);
115         }
116         else
117             ZOOM_connection_fire_event_timeout(c);
118     }
119     return r;
120 }
121
122 #if HAVE_SYS_POLL_H
123 ZOOM_API(int)
124     ZOOM_event_sys_poll(int no, ZOOM_connection *cs)
125 {
126     struct pollfd pollfds[1024];
127     ZOOM_connection poll_cs[1024];
128     int i, r;
129     int nfds = 0;
130     int timeout = 30;
131
132     for (i = 0; i<no; i++)
133     {
134         ZOOM_connection c = cs[i];
135         int fd, mask;
136         
137         if (!c)
138             continue;
139         fd = ZOOM_connection_get_socket(c);
140         mask = ZOOM_connection_get_mask(c);
141         timeout = ZOOM_connection_get_timeout(c);
142
143         if (fd == -1)
144             continue;
145         if (mask)
146         {
147             short poll_events = 0;
148
149             if (mask & ZOOM_SELECT_READ)
150                 poll_events += POLLIN;
151             if (mask & ZOOM_SELECT_WRITE)
152                 poll_events += POLLOUT;
153             if (mask & ZOOM_SELECT_EXCEPT)
154                 poll_events += POLLERR;
155             pollfds[nfds].fd = fd;
156             pollfds[nfds].events = poll_events;
157             pollfds[nfds].revents = 0;
158             poll_cs[nfds] = c;
159             nfds++;
160         }
161     }
162     if (nfds == 0)
163         return 0;
164     while ((r = poll(pollfds, nfds,
165          (timeout == -1 ? -1 : timeout * 1000))) < 0
166           && errno == EINTR)
167     {
168         ;
169     }
170     if (r < 0)
171     {
172         yaz_log(YLOG_WARN|YLOG_ERRNO, "ZOOM_event_sys_poll");
173         return r;
174     }
175     for (i = 0; i<nfds; i++)
176     {
177         ZOOM_connection c = poll_cs[i];
178         if (r)
179         {
180             int mask = 0;
181             if (pollfds[i].revents & POLLIN)
182                 mask += ZOOM_SELECT_READ;
183             if (pollfds[i].revents & POLLOUT)
184                 mask += ZOOM_SELECT_WRITE;
185             if (pollfds[i].revents & POLLERR)
186                 mask += ZOOM_SELECT_EXCEPT;
187             ZOOM_connection_fire_event_socket(c, mask);
188         }
189         else
190             ZOOM_connection_fire_event_timeout(c);
191     }
192     return r;
193 }
194 #endif
195
196 ZOOM_API(int)
197     ZOOM_event(int no, ZOOM_connection *cs)
198 {
199     int r;
200
201     r = ZOOM_event_nonblock(no, cs);
202     if (r)
203         return r;
204 #if HAVE_SYS_POLL_H
205     ZOOM_event_sys_poll(no, cs);
206 #else
207     ZOOM_event_sys_select(no, cs);
208 #endif
209     return ZOOM_event_nonblock(no, cs);
210 }
211
212 /*
213  * Local variables:
214  * c-basic-offset: 4
215  * indent-tabs-mode: nil
216  * End:
217  * vim: shiftwidth=4 tabstop=8 expandtab
218  */
219