bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / network_io / win32 / sockets.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_arch_networkio.h"
18 #include "apr_network_io.h"
19 #include "apr_general.h"
20 #include "apr_lib.h"
21 #include "apr_portable.h"
22 #include "apr_strings.h"
23 #include <string.h>
24 #include "apr_arch_inherit.h"
25 #include "apr_arch_misc.h"
26
27 static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */
28
29 static apr_status_t socket_cleanup(void *sock)
30 {
31     apr_socket_t *thesocket = sock;
32
33     if (thesocket->socketdes != INVALID_SOCKET) {
34         if (closesocket(thesocket->socketdes) == SOCKET_ERROR) {
35             return apr_get_netos_error();
36         }
37         thesocket->socketdes = INVALID_SOCKET;
38     }
39 #if APR_HAS_SENDFILE
40     if (thesocket->overlapped) {
41         CloseHandle(thesocket->overlapped->hEvent);
42         thesocket->overlapped = NULL;
43     }
44 #endif
45     return APR_SUCCESS;
46 }
47
48 static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol)
49 {
50     sock->type = type;
51     sock->protocol = protocol;
52     apr_sockaddr_vars_set(sock->local_addr, family, 0);
53     apr_sockaddr_vars_set(sock->remote_addr, family, 0);
54 }                                                                                                  
55 static void alloc_socket(apr_socket_t **new, apr_pool_t *p)
56 {
57     *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
58     (*new)->cntxt = p;
59     (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
60                                                        sizeof(apr_sockaddr_t));
61     (*new)->local_addr->pool = p;
62     (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
63                                                         sizeof(apr_sockaddr_t));
64     (*new)->remote_addr->pool = p;
65 }
66
67 APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock,
68                                                   int *protocol)
69 {
70     *protocol = sock->protocol;
71     return APR_SUCCESS;
72 }
73
74 APR_DECLARE(apr_status_t) apr_socket_create_ex(apr_socket_t **new, int family,
75                                                int type, int protocol, 
76                                                apr_pool_t *cont)
77 {
78     int downgrade = (family == AF_UNSPEC);
79
80     if (family == AF_UNSPEC) {
81 #if APR_HAVE_IPV6
82         family = AF_INET6;
83 #else
84         family = AF_INET;
85 #endif
86     }
87
88     alloc_socket(new, cont);
89
90     /* For right now, we are not using socket groups.  We may later.
91      * No flags to use when creating a socket, so use 0 for that parameter as well.
92      */
93     (*new)->socketdes = socket(family, type, protocol);
94 #if APR_HAVE_IPV6
95     if ((*new)->socketdes == INVALID_SOCKET && downgrade) {
96         family = AF_INET;
97         (*new)->socketdes = socket(family, type, protocol);
98     }
99 #endif
100
101     if ((*new)->socketdes == INVALID_SOCKET) {
102         return apr_get_netos_error();
103     }
104
105 #ifdef WIN32
106     /* Socket handles are never truly inheritable, there are too many
107      * bugs associated.  WSADuplicateSocket will copy them, but for our
108      * purposes, always transform the socket() created as a non-inherited
109      * handle
110      */
111 #if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
112     IF_WIN_OS_IS_UNICODE {
113         /* A different approach.  Many users report errors such as 
114          * (32538)An operation was attempted on something that is not 
115          * a socket.  : Parent: WSADuplicateSocket failed...
116          *
117          * This appears that the duplicated handle is no longer recognized
118          * as a socket handle.  SetHandleInformation should overcome that
119          * problem by not altering the handle identifier.  But this won't
120          * work on 9x - it's unsupported.
121          */
122         SetHandleInformation((HANDLE) (*new)->socketdes, 
123                              HANDLE_FLAG_INHERIT, 0);
124     }
125 #endif
126 #if APR_HAS_ANSI_FS || defined(_WIN32_WCE)
127     ELSE_WIN_OS_IS_ANSI {
128         HANDLE hProcess = GetCurrentProcess();
129         HANDLE dup;
130         if (DuplicateHandle(hProcess, (HANDLE) (*new)->socketdes, hProcess, 
131                             &dup, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
132             closesocket((*new)->socketdes);
133             (*new)->socketdes = (SOCKET) dup;
134         }
135     }
136 #endif
137
138 #endif /* def WIN32 */
139
140     set_socket_vars(*new, family, type, protocol);
141
142     (*new)->timeout = -1;
143     (*new)->disconnected = 0;
144
145     apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), 
146                         socket_cleanup, apr_pool_cleanup_null);
147
148     return APR_SUCCESS;
149
150
151 APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family,
152                                             int type, apr_pool_t *cont)
153 {
154     return apr_socket_create_ex(new, family, type, 0, cont);
155 }
156
157 APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket,
158                                               apr_shutdown_how_e how)
159 {
160     int winhow = 0;
161
162 #ifdef SD_RECEIVE
163     switch (how) {
164         case APR_SHUTDOWN_READ: {
165             winhow = SD_RECEIVE;
166             break;
167         }
168         case APR_SHUTDOWN_WRITE: {
169             winhow = SD_SEND;
170             break;
171         }
172         case APR_SHUTDOWN_READWRITE: {
173             winhow = SD_BOTH;
174             break;
175         }
176         default:
177             return APR_BADARG;
178     }
179 #endif
180     if (shutdown(thesocket->socketdes, winhow) == 0) {
181         return APR_SUCCESS;
182     }
183     else {
184         return apr_get_netos_error();
185     }
186 }
187
188 APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket)
189 {
190     apr_pool_cleanup_kill(thesocket->cntxt, thesocket, socket_cleanup);
191     return socket_cleanup(thesocket);
192 }
193
194 APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock,
195                                           apr_sockaddr_t *sa)
196 {
197     if (bind(sock->socketdes, 
198              (struct sockaddr *)&sa->sa, 
199              sa->salen) == -1) {
200         return apr_get_netos_error();
201     }
202     else {
203         sock->local_addr = sa;
204         if (sock->local_addr->sa.sin.sin_port == 0) {
205             sock->local_port_unknown = 1; /* ephemeral port */
206         }
207         return APR_SUCCESS;
208     }
209 }
210
211 APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock,
212                                             apr_int32_t backlog)
213 {
214     if (listen(sock->socketdes, backlog) == SOCKET_ERROR)
215         return apr_get_netos_error();
216     else
217         return APR_SUCCESS;
218 }
219
220 APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, 
221                                             apr_socket_t *sock, apr_pool_t *p)
222 {
223     SOCKET s;
224     struct sockaddr sa;
225     int salen = sizeof(sock->remote_addr->sa);
226
227     /* Don't allocate the memory until after we call accept. This allows
228        us to work with nonblocking sockets. */
229     s = accept(sock->socketdes, (struct sockaddr *)&sa, &salen);
230     if (s == INVALID_SOCKET) {
231         return apr_get_netos_error();
232     }
233
234     alloc_socket(new, p);
235     set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, 
236                     sock->protocol);
237
238     (*new)->timeout = -1;   
239     (*new)->disconnected = 0;
240
241     (*new)->socketdes = s;
242     /* XXX next line looks bogus w.r.t. AF_INET6 support */
243     (*new)->remote_addr->salen = sizeof((*new)->remote_addr->sa);
244     memcpy (&(*new)->remote_addr->sa, &sa, salen);
245     *(*new)->local_addr = *sock->local_addr;
246
247     /* The above assignment just overwrote the pool entry. Setting the local_addr 
248        pool for the accepted socket back to what it should be.  Otherwise all 
249        allocations for this socket will come from a server pool that is not
250        freed until the process goes down.*/
251     (*new)->local_addr->pool = p;
252
253     /* fix up any pointers which are no longer valid */
254     if (sock->local_addr->sa.sin.sin_family == AF_INET) {
255         (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
256     }
257 #if APR_HAVE_IPV6
258     else if (sock->local_addr->sa.sin.sin_family == AF_INET6) {
259         (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr;
260     }
261 #endif
262     (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
263     if (sock->local_port_unknown) {
264         /* not likely for a listening socket, but theoretically possible :) */
265         (*new)->local_port_unknown = 1;
266     }
267
268 #if APR_TCP_NODELAY_INHERITED
269     if (apr_is_option_set(sock->netmask, APR_TCP_NODELAY) == 1) {
270         apr_set_option(&(*new)->netmask, APR_TCP_NODELAY, 1);
271     }
272 #endif /* TCP_NODELAY_INHERITED */
273 #if APR_O_NONBLOCK_INHERITED
274     if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) == 1) {
275         apr_set_option(&(*new)->netmask, APR_SO_NONBLOCK, 1);
276     }
277 #endif /* APR_O_NONBLOCK_INHERITED */
278
279     if (sock->local_interface_unknown ||
280         !memcmp(sock->local_addr->ipaddr_ptr,
281                 generic_inaddr_any,
282                 sock->local_addr->ipaddr_len)) {
283         /* If the interface address inside the listening socket's local_addr wasn't
284          * up-to-date, we don't know local interface of the connected socket either.
285          *
286          * If the listening socket was not bound to a specific interface, we
287          * don't know the local_addr of the connected socket.
288          */
289         (*new)->local_interface_unknown = 1;
290     }
291
292     apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), 
293                         socket_cleanup, apr_pool_cleanup_null);
294     return APR_SUCCESS;
295 }
296
297 APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, 
298                                              apr_sockaddr_t *sa)
299 {
300     apr_status_t rv;
301
302     if ((sock->socketdes == INVALID_SOCKET) || (!sock->local_addr)) {
303         return APR_ENOTSOCK;
304     }
305
306     if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin,
307                 sa->salen) == SOCKET_ERROR) {
308         int rc;
309         struct timeval tv, *tvptr;
310         fd_set wfdset, efdset;
311
312         rv = apr_get_netos_error();
313         if (rv != APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
314             return rv;
315         }
316
317         if (sock->timeout == 0) {
318             /* Tell the app that the connect is in progress...
319              * Gotta play some games here.  connect on Unix will return 
320              * EINPROGRESS under the same circumstances that Windows 
321              * returns WSAEWOULDBLOCK. Do some adhoc canonicalization...
322              */
323             return APR_FROM_OS_ERROR(WSAEINPROGRESS);
324         }
325
326         /* wait for the connect to complete or timeout */
327         FD_ZERO(&wfdset);
328         FD_SET(sock->socketdes, &wfdset);
329         FD_ZERO(&efdset);
330         FD_SET(sock->socketdes, &efdset);
331
332         if (sock->timeout < 0) {
333             tvptr = NULL;
334         }
335         else {
336             /* casts for winsock/timeval definition */
337             tv.tv_sec =  (long)apr_time_sec(sock->timeout);
338             tv.tv_usec = (int)apr_time_usec(sock->timeout);
339             tvptr = &tv;
340         }
341         rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr);
342         if (rc == SOCKET_ERROR) {
343             return apr_get_netos_error();
344         }
345         else if (!rc) {
346             return APR_FROM_OS_ERROR(WSAETIMEDOUT);
347         }
348         /* Evaluate the efdset */
349         if (FD_ISSET(sock->socketdes, &efdset)) {
350             /* The connect failed. */
351             int rclen = sizeof(rc);
352             if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) {
353                 return apr_get_netos_error();
354             }
355             return APR_FROM_OS_ERROR(rc);
356         }
357     }
358     /* connect was OK .. amazing */
359     sock->remote_addr = sa;
360     if (sock->local_addr->sa.sin.sin_port == 0) {
361         sock->local_port_unknown = 1;
362     }
363     if (!memcmp(sock->local_addr->ipaddr_ptr,
364                 generic_inaddr_any,
365                 sock->local_addr->ipaddr_len)) {
366         /* not bound to specific local interface; connect() had to assign
367          * one for the socket
368          */
369         sock->local_interface_unknown = 1;
370     }
371     return APR_SUCCESS;
372 }
373
374 APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key,
375                                              apr_socket_t *sock)
376 {
377     sock_userdata_t *cur = sock->userdata;
378
379     *data = NULL;
380
381     while (cur) {
382         if (!strcmp(cur->key, key)) {
383             *data = cur->data;
384             break;
385         }
386         cur = cur->next;
387     }
388
389     return APR_SUCCESS;
390 }
391
392 APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data,
393                                              const char *key,
394                                              apr_status_t (*cleanup)(void *))
395 {
396     sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t));
397
398     new->key = apr_pstrdup(sock->cntxt, key);
399     new->data = data;
400     new->next = sock->userdata;
401     sock->userdata = new;
402
403     if (cleanup) {
404         apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup);
405     }
406
407     return APR_SUCCESS;
408 }
409
410 APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock,
411                                           apr_socket_t *sock)
412 {
413     *thesock = sock->socketdes;
414     return APR_SUCCESS;
415 }
416
417 APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock,
418                                            apr_os_sock_info_t *os_sock_info,
419                                            apr_pool_t *cont)
420 {
421     alloc_socket(apr_sock, cont);
422 #ifdef APR_ENABLE_FOR_1_0 /* no protocol field yet */
423     set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
424 #else
425     set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, 0);
426 #endif
427     (*apr_sock)->timeout = -1;
428     (*apr_sock)->disconnected = 0;
429     (*apr_sock)->socketdes = *os_sock_info->os_sock;
430     if (os_sock_info->local) {
431         memcpy(&(*apr_sock)->local_addr->sa.sin, 
432                os_sock_info->local, 
433                (*apr_sock)->local_addr->salen);
434         (*apr_sock)->local_addr->pool = cont;
435         /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
436         (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
437     }
438     else {
439         (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
440     }
441     if (os_sock_info->remote) {
442         memcpy(&(*apr_sock)->remote_addr->sa.sin, 
443                os_sock_info->remote,
444                (*apr_sock)->remote_addr->salen);
445         (*apr_sock)->remote_addr->pool = cont;
446         /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
447         (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
448     }
449     else {
450         (*apr_sock)->remote_addr_unknown = 1;
451     }
452         
453     apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock), 
454                         socket_cleanup, apr_pool_cleanup_null);
455
456     return APR_SUCCESS;
457 }
458
459 APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock,
460                                           apr_os_sock_t *thesock,
461                                           apr_pool_t *cont)
462 {
463     if ((*sock) == NULL) {
464         alloc_socket(sock, cont);
465         /* XXX figure out the actual socket type here */
466         /* *or* just decide that apr_os_sock_put() has to be told the family and type */
467         set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0);
468         (*sock)->timeout = -1;
469         (*sock)->disconnected = 0;
470     }
471     (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
472     (*sock)->remote_addr_unknown = 1;
473     (*sock)->socketdes = *thesock;
474     return APR_SUCCESS;
475 }
476
477
478 /* Sockets cannot be inherited through the standard sockets
479  * inheritence.  WSADuplicateSocket must be used.
480  * This is not trivial to implement.
481  */
482
483 APR_DECLARE(apr_status_t) apr_socket_inherit_set(apr_socket_t *socket)    
484 {    
485     return APR_ENOTIMPL;
486 }    
487 /* Deprecated */    
488 APR_DECLARE(void) apr_socket_set_inherit(apr_socket_t *socket)    
489 {    
490     apr_socket_inherit_set(socket);    
491 }
492
493 APR_DECLARE(apr_status_t) apr_socket_inherit_unset(apr_socket_t *socket)    
494 {    
495     return APR_ENOTIMPL;
496 }    
497 /* Deprecated */    
498 APR_DECLARE(void) apr_socket_unset_inherit(apr_socket_t *socket)    
499 {    
500     apr_socket_inherit_unset(socket);    
501 }
502 /* Deprecated */
503 APR_DECLARE(apr_status_t) apr_shutdown(apr_socket_t *thesocket,
504                                        apr_shutdown_how_e how)
505 {
506     return apr_socket_shutdown(thesocket, how);
507 }
508
509 /* Deprecated */
510 APR_DECLARE(apr_status_t) apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa)
511 {
512     return apr_socket_bind(sock, sa);
513 }
514
515 /* Deprecated */
516 APR_DECLARE(apr_status_t) apr_listen(apr_socket_t *sock, apr_int32_t backlog)
517 {
518     return apr_socket_listen(sock, backlog);
519 }
520
521 /* Deprecated */
522 APR_DECLARE(apr_status_t) apr_accept(apr_socket_t **new, apr_socket_t *sock,
523                                      apr_pool_t *p)
524 {
525     return apr_socket_accept(new, sock, p);
526 }
527
528 /* Deprecated */
529 APR_DECLARE(apr_status_t) apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
530 {
531     return apr_socket_connect(sock, sa);
532 }