1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
#include "apr_arch_networkio.h"
18
#include "apr_network_io.h"
19
#include "apr_general.h"
20
#include "apr_strings.h"
23
apr_status_t soblock(SOCKET sd)
27
if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
28
return apr_get_netos_error();
33
apr_status_t sononblock(SOCKET sd)
37
if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
38
return apr_get_netos_error();
44
APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
49
/* Set the socket non-blocking if it was previously blocking */
50
if (sock->timeout != 0) {
51
if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
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)
61
/* Reset socket timeouts if the new timeout differs from the old timeout */
62
if (sock->timeout != t)
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));
76
/* Set the socket to blocking with infinite timeouts */
77
if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
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));
89
APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock,
90
apr_int32_t opt, apr_int32_t on)
98
case APR_SO_KEEPALIVE:
99
if (on != apr_is_option_set(sock, APR_SO_KEEPALIVE)) {
100
if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE,
101
(void *)&one, sizeof(int)) == -1) {
102
return apr_get_netos_error();
104
apr_set_option(sock, APR_SO_KEEPALIVE, on);
108
if (on != apr_is_option_set(sock, APR_SO_DEBUG)) {
109
if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG,
110
(void *)&one, sizeof(int)) == -1) {
111
return apr_get_netos_error();
113
apr_set_option(sock, APR_SO_DEBUG, on);
117
if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF,
118
(void *)&on, sizeof(int)) == -1) {
119
return apr_get_netos_error();
123
if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF,
124
(void *)&on, sizeof(int)) == -1) {
125
return apr_get_netos_error();
128
case APR_SO_REUSEADDR:
129
if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) {
130
if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR,
131
(void *)&one, sizeof(int)) == -1) {
132
return apr_get_netos_error();
134
apr_set_option(sock, APR_SO_REUSEADDR, on);
137
case APR_SO_NONBLOCK:
138
if (apr_is_option_set(sock, APR_SO_NONBLOCK) != on) {
140
if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
144
if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
147
apr_set_option(sock, APR_SO_NONBLOCK, on);
152
if (apr_is_option_set(sock, APR_SO_LINGER) != on) {
155
li.l_linger = APR_MAX_SECS_TO_LINGER;
156
if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER,
157
(char *) &li, sizeof(struct linger)) == -1) {
158
return apr_get_netos_error();
160
apr_set_option(sock, APR_SO_LINGER, on);
164
case APR_TCP_DEFER_ACCEPT:
165
#if defined(TCP_DEFER_ACCEPT)
166
if (apr_is_option_set(sock, APR_TCP_DEFER_ACCEPT) != on) {
167
int optlevel = IPPROTO_TCP;
168
int optname = TCP_DEFER_ACCEPT;
170
if (setsockopt(sock->socketdes, optlevel, optname,
171
(void *)&on, sizeof(int)) == -1) {
174
apr_set_option(sock, APR_TCP_DEFER_ACCEPT, on);
179
case APR_TCP_NODELAY:
180
if (apr_is_option_set(sock, APR_TCP_NODELAY) != on) {
181
int optlevel = IPPROTO_TCP;
182
int optname = TCP_NODELAY;
185
if (sock->protocol == IPPROTO_SCTP) {
186
optlevel = IPPROTO_SCTP;
187
optname = SCTP_NODELAY;
190
if (setsockopt(sock->socketdes, optlevel, optname,
191
(void *)&on, sizeof(int)) == -1) {
192
return apr_get_netos_error();
194
apr_set_option(sock, APR_TCP_NODELAY, on);
197
case APR_IPV6_V6ONLY:
198
#if APR_HAVE_IPV6 && defined(IPV6_V6ONLY)
199
/* we don't know the initial setting of this option,
200
* so don't check sock->options since that optimization
203
if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY,
204
(void *)&on, sizeof(int)) == -1) {
205
return apr_get_netos_error();
207
apr_set_option(sock, APR_IPV6_V6ONLY, on);
220
APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
227
APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
228
apr_int32_t opt, apr_int32_t *on)
231
case APR_SO_DISCONNECTED:
232
*on = sock->disconnected;
234
case APR_SO_KEEPALIVE:
236
case APR_SO_REUSEADDR:
237
case APR_SO_NONBLOCK:
240
*on = apr_is_option_set(sock, opt);
247
APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
251
if (ioctlsocket(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0)
252
return apr_get_netos_error();
254
*atmark = (oobmark != 0);
260
APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len,
263
if (gethostname(buf, len) == -1) {
265
return apr_get_netos_error();
267
else if (!memchr(buf, '\0', len)) { /* buffer too small */
269
return APR_ENAMETOOLONG;