upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / server / listen.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr_network_io.h"
18 #include "apr_strings.h"
19
20 #define APR_WANT_STRFUNC
21 #include "apr_want.h"
22
23 #define CORE_PRIVATE
24 #include "ap_config.h"
25 #include "httpd.h"
26 #include "http_config.h"
27 #include "ap_listen.h"
28 #include "http_log.h"
29 #include "mpm.h"
30 #include "mpm_common.h"
31
32 ap_listen_rec *ap_listeners = NULL;
33
34 #if APR_HAVE_IPV6
35 static int default_family = APR_UNSPEC;
36 #else
37 static int default_family = APR_INET;
38 #endif
39
40 static ap_listen_rec *old_listeners;
41 static int ap_listenbacklog;
42 static int send_buffer_size;
43 static int receive_buffer_size;
44
45 /* TODO: make_sock is just begging and screaming for APR abstraction */
46 static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
47 {
48     apr_socket_t *s = server->sd;
49     int one = 1;
50 #if APR_HAVE_IPV6
51 #ifdef AP_ENABLE_V4_MAPPED
52     int v6only_setting = 0;
53 #else
54     int v6only_setting = 1;
55 #endif
56 #endif
57     apr_status_t stat;
58
59 #ifndef WIN32
60     stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
61     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
62         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
63                       "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
64                       server->bind_addr);
65         apr_socket_close(s);
66         return stat;
67     }
68 #endif
69
70     stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
71     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
72         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
73                       "make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)",
74                       server->bind_addr);
75         apr_socket_close(s);
76         return stat;
77     }
78
79 #if APR_HAVE_IPV6
80     if (server->bind_addr->family == APR_INET6) {
81         stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
82         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
83             ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
84                           "make_sock: for address %pI, apr_socket_opt_set: "
85                           "(IPV6_V6ONLY)",
86                           server->bind_addr);
87             apr_socket_close(s);
88             return stat;
89         }
90     }
91 #endif
92
93     /*
94      * To send data over high bandwidth-delay connections at full
95      * speed we must force the TCP window to open wide enough to keep the
96      * pipe full.  The default window size on many systems
97      * is only 4kB.  Cross-country WAN connections of 100ms
98      * at 1Mb/s are not impossible for well connected sites.
99      * If we assume 100ms cross-country latency,
100      * a 4kB buffer limits throughput to 40kB/s.
101      *
102      * To avoid this problem I've added the SendBufferSize directive
103      * to allow the web master to configure send buffer size.
104      *
105      * The trade-off of larger buffers is that more kernel memory
106      * is consumed.  YMMV, know your customers and your network!
107      *
108      * -John Heidemann <johnh@isi.edu> 25-Oct-96
109      *
110      * If no size is specified, use the kernel default.
111      */
112     if (send_buffer_size) {
113         stat = apr_socket_opt_set(s, APR_SO_SNDBUF,  send_buffer_size);
114         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
115             ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
116                           "make_sock: failed to set SendBufferSize for "
117                           "address %pI, using default",
118                           server->bind_addr);
119             /* not a fatal error */
120         }
121     }
122     if (receive_buffer_size) {
123         stat = apr_socket_opt_set(s, APR_SO_RCVBUF, receive_buffer_size);
124         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
125             ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
126                           "make_sock: failed to set ReceiveBufferSize for "
127                           "address %pI, using default",
128                           server->bind_addr);
129             /* not a fatal error */
130         }
131     }
132
133 #if APR_TCP_NODELAY_INHERITED
134     ap_sock_disable_nagle(s);
135 #endif
136
137     if ((stat = apr_bind(s, server->bind_addr)) != APR_SUCCESS) {
138         ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p,
139                       "make_sock: could not bind to address %pI",
140                       server->bind_addr);
141         apr_socket_close(s);
142         return stat;
143     }
144
145     if ((stat = apr_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
146         ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p,
147                       "make_sock: unable to listen for connections "
148                       "on address %pI",
149                       server->bind_addr);
150         apr_socket_close(s);
151         return stat;
152     }
153
154 #ifdef WIN32
155     /* I seriously doubt that this would work on Unix; I have doubts that
156      * it entirely solves the problem on Win32.  However, since setting
157      * reuseaddr on the listener -prior- to binding the socket has allowed
158      * us to attach to the same port as an already running instance of
159      * Apache, or even another web server, we cannot identify that this
160      * port was exclusively granted to this instance of Apache.
161      *
162      * So set reuseaddr, but do not attempt to do so until we have the
163      * parent listeners successfully bound.
164      */
165     stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
166     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
167         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
168                     "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)", 
169                      server->bind_addr);
170         apr_socket_close(s);
171         return stat;
172     }
173 #endif
174
175 #if APR_HAS_SO_ACCEPTFILTER
176 #ifndef ACCEPT_FILTER_NAME
177 #define ACCEPT_FILTER_NAME "httpready"
178 #ifdef __FreeBSD_version
179 #if __FreeBSD_version < 411000 /* httpready was broken before 4.1.1 */
180 #undef ACCEPT_FILTER_NAME
181 #define ACCEPT_FILTER_NAME "dataready"
182 #endif
183 #endif
184 #endif
185     apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, "");
186 #endif
187
188     server->sd = s;
189     server->active = 1;
190
191 #ifdef MPM_ACCEPT_FUNC
192     server->accept_func = MPM_ACCEPT_FUNC;
193 #else
194     server->accept_func = NULL;
195 #endif
196
197     return APR_SUCCESS;
198 }
199
200 static apr_status_t close_listeners_on_exec(void *v)
201 {
202     ap_listen_rec *lr;
203
204     for (lr = ap_listeners; lr; lr = lr->next) {
205         apr_socket_close(lr->sd);
206         lr->active = 0;
207     }
208
209     return APR_SUCCESS;
210 }
211
212
213 static void find_default_family(apr_pool_t *p)
214 {
215 #if APR_HAVE_IPV6
216     /* We know the platform supports IPv6, but this particular
217      * system may not have IPv6 enabled.  See if we can get an
218      * AF_INET6 socket and bind to an ephemeral port.  (On most
219      * systems, getting an AF_INET6 socket is a sufficient test.
220      * On certain levels of OpenUNIX, getting the socket is
221      * successful but bind always returns ENETUNREACH.)
222      */
223     if (default_family == APR_UNSPEC) {
224         apr_status_t sock_rv;
225         apr_socket_t *tmp_sock;
226         apr_sockaddr_t *sa;
227
228         if ((sock_rv = apr_socket_create(&tmp_sock, APR_INET6, SOCK_STREAM, p)) 
229             == APR_SUCCESS &&
230             apr_sockaddr_info_get(&sa, NULL, APR_INET6, 0, 0, p) == APR_SUCCESS &&
231             apr_bind(tmp_sock, sa) == APR_SUCCESS) { 
232             default_family = APR_INET6;
233         }
234         else {
235             default_family = APR_INET;
236         }
237         if (sock_rv == APR_SUCCESS) {
238             apr_socket_close(tmp_sock);
239         }
240     }
241 #endif
242 }
243
244
245 static const char *alloc_listener(process_rec *process, char *addr, apr_port_t port)
246 {
247     ap_listen_rec **walk;
248     ap_listen_rec *new;
249     apr_status_t status;
250     apr_port_t oldport;
251     apr_sockaddr_t *sa;
252
253     if (!addr) { /* don't bind to specific interface */
254         find_default_family(process->pool);
255         switch(default_family) {
256         case APR_INET:
257             addr = "0.0.0.0";
258             break;
259
260 #if APR_HAVE_IPV6
261         case APR_INET6:
262             addr = "::";
263             break;
264 #endif
265
266         default:
267             ap_assert(1 != 1); /* should not occur */
268         }
269     }
270
271     /* see if we've got an old listener for this address:port */
272     for (walk = &old_listeners; *walk; walk = &(*walk)->next) {
273         sa = (*walk)->bind_addr;
274         /* Some listeners are not real so they will not have a bind_addr. */
275         if (sa) {
276             apr_sockaddr_port_get(&oldport, sa);
277             if (!strcmp(sa->hostname, addr) && port == oldport) {
278                 /* re-use existing record */
279                 new = *walk;
280                 *walk = new->next;
281                 new->next = ap_listeners;
282                 ap_listeners = new;
283                 return NULL;
284             }
285         }
286     }
287
288     /* this has to survive restarts */
289     new = apr_palloc(process->pool, sizeof(ap_listen_rec));
290     new->active = 0;
291     if ((status = apr_sockaddr_info_get(&new->bind_addr, addr, APR_UNSPEC,
292                                         port, 0, process->pool))
293         != APR_SUCCESS) {
294         ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
295                       "alloc_listener: failed to set up sockaddr for %s",
296                       addr);
297         return "Listen setup failed";
298     }
299     if ((status = apr_socket_create(&new->sd,
300                                     new->bind_addr->family,
301                                     SOCK_STREAM, process->pool))
302         != APR_SUCCESS) {
303         ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
304                       "alloc_listener: failed to get a socket for %s", addr);
305         return "Listen setup failed";
306     }
307
308     new->next = ap_listeners;
309     ap_listeners = new;
310     return NULL;
311 }
312
313 static int ap_listen_open(apr_pool_t *pool, apr_port_t port)
314 {
315     ap_listen_rec *lr;
316     ap_listen_rec *next;
317     int num_open;
318     const char *userdata_key = "ap_listen_open";
319     void *data;
320
321     /* Don't allocate a default listener.  If we need to listen to a
322      * port, then the user needs to have a Listen directive in their
323      * config file.
324      */
325     num_open = 0;
326     for (lr = ap_listeners; lr; lr = lr->next) {
327         if (lr->active) {
328             ++num_open;
329         }
330         else {
331             if (make_sock(pool, lr) == APR_SUCCESS) {
332                 ++num_open;
333                 lr->active = 1;
334             }
335             else {
336                 /* fatal error */
337                 return -1;
338             }
339         }
340     }
341
342     /* close the old listeners */
343     for (lr = old_listeners; lr; lr = next) {
344         apr_socket_close(lr->sd);
345         lr->active = 0;
346         next = lr->next;
347     }
348     old_listeners = NULL;
349
350 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
351     /* if multiple listening sockets, make them non-blocking so that
352      * if select()/poll() reports readability for a reset connection that
353      * is already forgotten about by the time we call accept, we won't
354      * be hung until another connection arrives on that port
355      */
356     if (ap_listeners && ap_listeners->next) {
357         for (lr = ap_listeners; lr; lr = lr->next) {
358             apr_status_t status;
359
360             status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
361             if (status != APR_SUCCESS) {
362                 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
363                               "ap_listen_open: unable to make socket non-blocking");
364                 return -1;
365             }
366         }
367     }
368 #endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
369
370     /* we come through here on both passes of the open logs phase
371      * only register the cleanup once... otherwise we try to close
372      * listening sockets twice when cleaning up prior to exec
373      */
374     apr_pool_userdata_get(&data, userdata_key, pool);
375     if (!data) {
376         apr_pool_userdata_set((const void *)1, userdata_key,
377                               apr_pool_cleanup_null, pool);
378         apr_pool_cleanup_register(pool, NULL, apr_pool_cleanup_null,
379                                   close_listeners_on_exec);
380     }
381
382     return num_open ? 0 : -1;
383 }
384
385 int ap_setup_listeners(server_rec *s)
386 {
387     ap_listen_rec *lr;
388     int num_listeners = 0;
389
390     if (ap_listen_open(s->process->pool, s->port)) {
391        return 0;
392     }
393
394     for (lr = ap_listeners; lr; lr = lr->next) {
395         num_listeners++;
396     }
397
398     return num_listeners;
399 }
400
401 void ap_listen_pre_config(void)
402 {
403     old_listeners = ap_listeners;
404     ap_listeners = NULL;
405     ap_listenbacklog = DEFAULT_LISTENBACKLOG;
406 }
407
408
409 const char *ap_set_listener(cmd_parms *cmd, void *dummy, const char *ips)
410 {
411     char *host, *scope_id;
412     apr_port_t port;
413     apr_status_t rv;
414     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
415
416     if (err != NULL) {
417         return err;
418     }
419
420     rv = apr_parse_addr_port(&host, &scope_id, &port, ips, cmd->pool);
421     if (rv != APR_SUCCESS) {
422         return "Invalid address or port";
423     }
424
425     if (host && !strcmp(host, "*")) {
426         host = NULL;
427     }
428
429     if (scope_id) {
430         /* XXX scope id support is useful with link-local IPv6 addresses */
431         return "Scope id is not supported";
432     }
433
434     if (!port) {
435         return "Port must be specified";
436     }
437
438     return alloc_listener(cmd->server->process, host, port);
439 }
440
441 const char *ap_set_listenbacklog(cmd_parms *cmd, void *dummy, const char *arg)
442 {
443     int b;
444     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
445
446     if (err != NULL) {
447         return err;
448     }
449
450     b = atoi(arg);
451     if (b < 1) {
452         return "ListenBacklog must be > 0";
453     }
454
455     ap_listenbacklog = b;
456     return NULL;
457 }
458
459 const char *ap_set_send_buffer_size(cmd_parms *cmd, void *dummy,
460                                     const char *arg)
461 {
462     int s = atoi(arg);
463     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
464
465     if (err != NULL) {
466         return err;
467     }
468
469     if (s < 512 && s != 0) {
470         return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
471     }
472
473     send_buffer_size = s;
474     return NULL;
475 }
476
477 AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd,
478                                                            void *dummy,
479                                                            const char *arg)
480 {
481     int s = atoi(arg);
482     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
483
484     if (err != NULL) {
485         return err;
486     }
487
488     if (s < 512 && s != 0) {
489         return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
490     }
491
492     receive_buffer_size = s;
493     return NULL;
494 }