bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / network_io / win32 / sockopt.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_strings.h"
21 #include <string.h>
22
23 apr_status_t soblock(SOCKET sd)
24 {
25     u_long zero = 0;
26
27     if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
28         return apr_get_netos_error();
29     }
30     return APR_SUCCESS;
31 }
32
33 apr_status_t sononblock(SOCKET sd)
34 {
35     u_long one = 1;
36
37     if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
38         return apr_get_netos_error();
39     }
40     return APR_SUCCESS;
41 }
42
43
44 APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
45 {
46     apr_status_t stat;
47
48     if (t == 0) {
49         /* Set the socket non-blocking if it was previously blocking */
50         if (sock->timeout != 0) {
51             if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
52                 return stat;
53         }
54     }
55     else if (t > 0) {
56         /* Set the socket to blocking if it was previously non-blocking */
57         if (sock->timeout == 0) {
58             if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
59                 return stat;
60         }
61         /* Reset socket timeouts if the new timeout differs from the old timeout */
62         if (sock->timeout != t) 
63         {
64             /* Win32 timeouts are in msec, represented as int */
65             sock->timeout_ms = (int)apr_time_as_msec(t);
66             setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
67                        (char *) &sock->timeout_ms, 
68                        sizeof(sock->timeout_ms));
69             setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
70                        (char *) &sock->timeout_ms, 
71                        sizeof(sock->timeout_ms));
72         }
73     }
74     else if (t < 0) {
75         int zero = 0;
76         /* Set the socket to blocking with infinite timeouts */
77         if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
78             return stat;
79         setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
80                    (char *) &zero, sizeof(zero));
81         setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
82                    (char *) &zero, sizeof(zero));
83     }
84     sock->timeout = t;
85     return APR_SUCCESS;
86 }
87
88
89 APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock,
90                                              apr_int32_t opt, apr_int32_t on)
91 {
92     int one;
93     apr_status_t stat;
94
95     one = on ? 1 : 0;
96
97     switch (opt) {
98     case APR_SO_TIMEOUT: 
99     {
100         /* XXX: To be deprecated */
101         return apr_socket_timeout_set(sock, on);
102     }
103     case APR_SO_KEEPALIVE:
104         if (on != apr_is_option_set(sock->netmask, APR_SO_KEEPALIVE)) {
105             if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, 
106                            (void *)&one, sizeof(int)) == -1) {
107                 return apr_get_netos_error();
108             }
109             apr_set_option(&sock->netmask,APR_SO_KEEPALIVE, on);
110         }
111         break;
112     case APR_SO_DEBUG:
113         if (on != apr_is_option_set(sock->netmask, APR_SO_DEBUG)) {
114             if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, 
115                            (void *)&one, sizeof(int)) == -1) {
116                 return apr_get_netos_error();
117             }
118             apr_set_option(&sock->netmask, APR_SO_DEBUG, on);
119         }
120         break;
121     case APR_SO_SNDBUF:
122         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF,
123                        (void *)&on, sizeof(int)) == -1) {
124             return apr_get_netos_error();
125         }
126         break;
127     case APR_SO_RCVBUF:
128         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF,
129                        (void *)&on, sizeof(int)) == -1) {
130             return apr_get_netos_error();
131         }
132         break;
133     case APR_SO_REUSEADDR:
134         if (on != apr_is_option_set(sock->netmask, APR_SO_REUSEADDR)) {
135             if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, 
136                            (void *)&one, sizeof(int)) == -1) {
137                 return apr_get_netos_error();
138             }
139             apr_set_option(&sock->netmask, APR_SO_REUSEADDR, on);
140         }
141         break;
142     case APR_SO_NONBLOCK:
143         if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) != on) {
144             if (on) {
145                 if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) 
146                     return stat;
147             }
148             else {
149                 if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
150                     return stat;
151             }
152             apr_set_option(&sock->netmask, APR_SO_NONBLOCK, on);
153         }
154         break;
155     case APR_SO_LINGER:
156     {
157         if (apr_is_option_set(sock->netmask, APR_SO_LINGER) != on) {
158             struct linger li;
159             li.l_onoff = on;
160             li.l_linger = APR_MAX_SECS_TO_LINGER;
161             if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, 
162                            (char *) &li, sizeof(struct linger)) == -1) {
163                 return apr_get_netos_error();
164             }
165             apr_set_option(&sock->netmask, APR_SO_LINGER, on);
166         }
167         break;
168     }
169     case APR_TCP_NODELAY:
170         if (apr_is_option_set(sock->netmask, APR_TCP_NODELAY) != on) {
171             int optlevel = IPPROTO_TCP;
172             int optname = TCP_NODELAY;
173
174 #if APR_HAVE_SCTP
175             if (sock->protocol == IPPROTO_SCTP) {
176                 optlevel = IPPROTO_SCTP;
177                 optname = SCTP_NODELAY;
178             }
179 #endif
180             if (setsockopt(sock->socketdes, optlevel, optname,
181                            (void *)&on, sizeof(int)) == -1) {
182                 return apr_get_netos_error();
183             }
184             apr_set_option(&sock->netmask, APR_TCP_NODELAY, on);
185         }
186         break;
187     case APR_IPV6_V6ONLY:
188 #if APR_HAVE_IPV6 && defined(IPV6_V6ONLY)
189         /* we don't know the initial setting of this option,
190          * so don't check sock->netmask since that optimization
191          * won't work
192          */
193         if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY,
194                        (void *)&on, sizeof(int)) == -1) {
195             return apr_get_netos_error();
196         }
197         apr_set_option(&sock->netmask, APR_IPV6_V6ONLY, on);
198 #else
199         return APR_ENOTIMPL;
200 #endif
201         break;
202     default:
203         return APR_EINVAL;
204         break;
205     }
206     return APR_SUCCESS;
207 }
208
209
210 APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
211 {
212     *t = sock->timeout;
213     return APR_SUCCESS;
214 }
215
216
217 APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
218                                              apr_int32_t opt, apr_int32_t *on)
219 {
220     switch (opt) {
221     case APR_SO_TIMEOUT: 
222         /* XXX: to be deprecated */
223         *on = (apr_int32_t)sock->timeout;
224         break;
225     case APR_SO_DISCONNECTED:
226         *on = sock->disconnected;
227         break;
228     case APR_SO_KEEPALIVE:
229     case APR_SO_DEBUG:
230     case APR_SO_REUSEADDR:
231     case APR_SO_NONBLOCK:
232     case APR_SO_LINGER:
233     default:
234         *on = apr_is_option_set(sock->netmask, opt);
235     }
236     return APR_SUCCESS;
237 }
238
239
240 /* deprecated */
241 APR_DECLARE(apr_status_t) apr_setsocketopt(apr_socket_t *sock,
242                                            apr_int32_t opt, apr_int32_t on)
243 {
244     return apr_socket_opt_set(sock, opt, on);
245 }
246
247 APR_DECLARE(apr_status_t) apr_getsocketopt(apr_socket_t *sock,
248                                            apr_int32_t opt, apr_int32_t *on)
249 {
250     return apr_socket_opt_get(sock, opt, on);
251 }
252                                            
253
254 APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
255 {
256     u_long oobmark;
257
258     if (ioctlsocket(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0)
259         return apr_get_netos_error();
260
261     *atmark = (oobmark != 0);
262
263     return APR_SUCCESS;
264 }
265
266
267 APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len,
268                                           apr_pool_t *cont)
269 {
270     if (gethostname(buf, len) == -1) {
271         buf[0] = '\0';
272         return apr_get_netos_error();
273     }
274     else if (!memchr(buf, '\0', len)) { /* buffer too small */
275         buf[0] = '\0';
276         return APR_ENAMETOOLONG;
277     }
278     return APR_SUCCESS;
279 }
280