1 /*
2 ** Copyright (C) 2006 Olivier DEMBOUR
3 ** $Id: select.c,v 1.1.2.4 2010/01/20 15:42:56 dembour Exp $
4 **
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with This program; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdio.h>
22
23 #ifndef _WIN32
24 #include <sys/wait.h>
25 #include <sys/select.h>
26 #include <strings.h>
27 #else
28 #include "mywin32.h"
29 #endif
30
31 #include "dns.h"
32 #include "list.h"
33 #include "myerror.h"
34 #include "client.h"
35 #include "debug.h"
36 #include "queue.h"
37 #include "socket.h"
38
39 #ifdef _WIN32
add_event(WSAEVENT event,HANDLE * rfds,int max_fd)40 int add_event(WSAEVENT event, HANDLE *rfds, int max_fd)
41 {
42 rfds[max_fd] = event;
43 return ((int) (max_fd+1));
44 }
45 #else
add_socket(socket_t socket,fd_set * rfds,socket_t max_fd)46 int add_socket(socket_t socket, fd_set *rfds, socket_t max_fd)
47 {
48 FD_SET(socket, rfds);
49 return ((int)(MAX(max_fd, socket)));
50 }
51 #endif
52
53 #ifdef _WIN32
win_prepare_select(t_conf * conf,WSAEVENT * rfds,struct timeval * tv)54 int win_prepare_select(t_conf *conf, WSAEVENT *rfds, struct timeval *tv)
55 {
56 int max_fd = 0;
57 t_simple_list *client;
58
59 max_fd = add_event(conf->event_udp, rfds, max_fd);
60
61 for (client = conf->client; client; client = client->next)
62 {
63 if (socket_is_valid(client->fd_ro))
64 {
65 queue_put_nop(conf, client);
66 if ((client->control.data_pending < MAX_DATA_SIZE)
67 && ((client->control.data_pending + client->control.nop_pending < WINDOW_SIZE)))
68 {
69 if (client->control.event && socket_is_valid(client->fd_ro))
70 max_fd = add_event(client->control.event, rfds, max_fd);
71 else
72 {
73 if (client->pid != (process_t)-1) {
74 // watch for pipe I/O completion
75 max_fd = add_event(client->control.aio.hEvent, rfds, max_fd);
76 }
77 }
78 }
79 else
80 {
81 if (client->control.nop_pending == 0xffff)
82 {
83 DPRINTF(1, "WTF !\n");
84 exit(0);
85 }
86 SetEvent(conf->event_udp);
87 }
88 if (client->pid != (process_t)-1) {
89 // watch for process event (dead)
90 max_fd = add_event(client->pid, rfds, max_fd);
91 }
92 }
93 }
94 /* select only if sd_tcp is alive */
95 if (socket_is_valid(conf->sd_tcp))
96 max_fd = add_event(conf->event_tcp, rfds, max_fd);
97 tv->tv_sec = SOCKET_TIMEOUT;
98 tv->tv_usec = 0;
99 return (max_fd);
100 }
101
102 #else
103
unix_prepare_select(t_conf * conf,fd_set * rfds,struct timeval * tv)104 int unix_prepare_select(t_conf *conf, fd_set *rfds, struct timeval *tv)
105 {
106 int max_fd = 0;
107 t_simple_list *client;
108
109 FD_ZERO(rfds);
110 for (client = conf->client; client; client = client->next)
111 {
112 if (socket_is_valid(client->fd_ro))
113 {
114 queue_put_nop(conf, client);
115 if (!(client->control.data_pending >= MAX_DATA_SIZE)
116 && (!(client->control.data_pending + client->control.nop_pending >= WINDOW_SIZE)))
117 {
118 if (socket_is_valid(client->fd_ro))
119 max_fd = add_socket(client->fd_ro, rfds, max_fd);
120 }
121 }
122 }
123 max_fd = add_socket(conf->sd_udp, rfds, max_fd);
124 // fuck Windows, not queue debug
125 if ((!conf->use_stdin) && (debug > 1))
126 max_fd = add_socket(0, rfds, max_fd);
127
128 /* select only if sd_tcp is alive */
129 if (socket_is_valid(conf->sd_tcp))
130 max_fd = add_socket(conf->sd_tcp, rfds, max_fd);
131 tv->tv_sec = SOCKET_TIMEOUT;
132 tv->tv_usec = 0;
133 return (max_fd);
134 }
135 #endif
136
137 /**
138 * @brief prepare the fd_set for select or HANDLE for Windows
139 * @param[in] conf configuration
140 * @param[in] rfds the fd_set
141 * @param[in] tv timeval structure
142 * @retval last file descriptor
143 */
144
prepare_select(t_conf * conf,fd_set * rfds,struct timeval * tv)145 int prepare_select(t_conf *conf, fd_set *rfds, struct timeval *tv)
146 {
147 #ifndef _WIN32
148 return (unix_prepare_select(conf, rfds, tv));
149 #else
150 return (win_prepare_select(conf, (WSAEVENT *)rfds, tv));
151 #endif
152 }
153