diff options
author | hongbotian <hongbo.tianhongbo@huawei.com> | 2015-11-30 01:45:08 -0500 |
---|---|---|
committer | hongbotian <hongbo.tianhongbo@huawei.com> | 2015-11-30 01:45:08 -0500 |
commit | e8ec7aa8e38a93f5b034ac74cebce5de23710317 (patch) | |
tree | aa031937bf856c1f8d6ad7877b8d2cb0224da5ef /rubbos/app/httpd-2.0.64/srclib/apr/network_io | |
parent | cc40af334e619bb549038238507407866f774f8f (diff) |
upload http
JIRA: BOTTLENECK-10
Change-Id: I7598427ff904df438ce77c2819ee48ac75ffa8da
Signed-off-by: hongbotian <hongbo.tianhongbo@huawei.com>
Diffstat (limited to 'rubbos/app/httpd-2.0.64/srclib/apr/network_io')
41 files changed, 5912 insertions, 0 deletions
diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/Makefile.in b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/Makefile.in new file mode 100644 index 00000000..b2c93fbb --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/Makefile.in @@ -0,0 +1,14 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +TARGETS = sendrecv.lo socketcommon.lo + +# bring in rules.mk for standard functionality +@INCLUDE_RULES@ + +INCDIR=../../include +OSDIR=$(INCDIR)/arch/@OSDIR@ +DEFOSDIR=$(INCDIR)/arch/@DEFAULT_OSDIR@ +INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) + +# DO NOT REMOVE diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/sendrecv.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/sendrecv.c new file mode 100644 index 00000000..a9e7d443 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/sendrecv.c @@ -0,0 +1,252 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#if BEOS_BONE /* BONE uses the unix code - woohoo */ +#include "../unix/sendrecv.c" +#else +#include "apr_arch_networkio.h" +#include "apr_time.h" + +apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read) +{ + struct timeval tv, *tvptr; + fd_set fdset; + int srv; + + do { + FD_ZERO(&fdset); + FD_SET(sock->socketdes, &fdset); + if (sock->timeout < 0) { + tvptr = NULL; + } + else { + tv.tv_sec = sock->timeout / APR_USEC_PER_SEC; + tv.tv_usec = sock->timeout % APR_USEC_PER_SEC; + tvptr = &tv; + } + srv = select(sock->socketdes + 1, + for_read ? &fdset : NULL, + for_read ? NULL : &fdset, + NULL, + tvptr); + /* TODO - timeout should be smaller on repeats of this loop */ + } while (srv == -1 && errno == EINTR); + + if (srv == 0) { + return APR_TIMEUP; + } + else if (srv < 0) { + return errno; + } + return APR_SUCCESS; +} + +#define SEND_WAIT APR_USEC_PER_SEC / 10 + +APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = send(sock->socketdes, buf, (*len), 0); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { + apr_int32_t snooze_val = SEND_WAIT; + apr_int32_t zzz = 0; + + do { + rv = send(sock->socketdes, buf, (*len), 0); + if (rv == -1 && errno == EWOULDBLOCK){ + apr_sleep (snooze_val); + zzz += snooze_val; + snooze_val += SEND_WAIT; + /* have we passed our timeout value */ + if (zzz > (sock->timeout * APR_USEC_PER_SEC)) + break; + } + } while (rv == -1 && (errno == EINTR || errno == EWOULDBLOCK)); + } + if (rv == -1) { + *len = 0; + return errno; + } + (*len) = rv; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = recv(sock->socketdes, buf, (*len), 0); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = recv(sock->socketdes, buf, (*len), 0); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + (*len) = rv; + if (rv == 0) + return APR_EOF; + return APR_SUCCESS; +} + +/* BeOS doesn't have writev for sockets so we use the following instead... + */ +APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t * sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + *len = vec[0].iov_len; + return apr_socket_send(sock, vec[0].iov_base, len); +} + +APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) + && sock->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + *len = rv; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + if (from == NULL){ + return APR_ENOMEM; + /* Not sure if this is correct. Maybe we should just allocate + the memory?? + */ + } + + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && + sock->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + + (*len) = rv; + if (rv == 0) + return APR_EOF; + + return APR_SUCCESS; +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + return apr_socket_send(sock, buf, len); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_sendv(apr_socket_t * sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + return apr_socket_sendv(sock, vec, nvec, len); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + return apr_socket_sendto(sock, where, flags, buf, len); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + return apr_socket_recvfrom(from, sock, flags, buf, len); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + return apr_socket_recv(sock, buf, len); +} + +#endif diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/socketcommon.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/socketcommon.c new file mode 100644 index 00000000..cdadc856 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/beos/socketcommon.c @@ -0,0 +1,5 @@ +#include "../unix/inet_ntop.c" +#include "../unix/inet_pton.c" +#include "../unix/sockets.c" +#include "../unix/sockaddr.c" +#include "../unix/sockopt.c" diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/Makefile.in b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/Makefile.in new file mode 100644 index 00000000..04b8e32d --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/Makefile.in @@ -0,0 +1,22 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +TARGETS = \ + sendrecv.lo \ + sendrecv_udp.lo \ + sockets.lo \ + sockopt.lo \ + sockaddr.lo \ + inet_ntop.lo \ + inet_pton.lo \ + os2calls.lo + +# bring in rules.mk for standard functionality +@INCLUDE_RULES@ + +INCDIR=../../include +OSDIR=$(INCDIR)/arch/@OSDIR@ +DEFOSDIR=$(INCDIR)/arch/@DEFAULT_OSDIR@ +INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) + +# DO NOT REMOVE diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/inet_ntop.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/inet_ntop.c new file mode 100644 index 00000000..f1f79d49 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/inet_ntop.c @@ -0,0 +1 @@ +#include "../unix/inet_ntop.c" diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/inet_pton.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/inet_pton.c new file mode 100644 index 00000000..dbd3ac45 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/inet_pton.c @@ -0,0 +1 @@ +#include "../unix/inet_pton.c" diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/os2calls.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/os2calls.c new file mode 100644 index 00000000..6bf1fcd0 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/os2calls.c @@ -0,0 +1,132 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_portable.h" +#include "apr_general.h" +#include "apr_lib.h" + +static int os2_socket_init(int, int ,int); + +int (*apr_os2_socket)(int, int, int) = os2_socket_init; +int (*apr_os2_select)(int *, int, int, int, long) = NULL; +int (*apr_os2_sock_errno)() = NULL; +int (*apr_os2_accept)(int, struct sockaddr *, int *) = NULL; +int (*apr_os2_bind)(int, struct sockaddr *, int) = NULL; +int (*apr_os2_connect)(int, struct sockaddr *, int) = NULL; +int (*apr_os2_getpeername)(int, struct sockaddr *, int *) = NULL; +int (*apr_os2_getsockname)(int, struct sockaddr *, int *) = NULL; +int (*apr_os2_getsockopt)(int, int, int, char *, int *) = NULL; +int (*apr_os2_ioctl)(int, int, caddr_t, int) = NULL; +int (*apr_os2_listen)(int, int) = NULL; +int (*apr_os2_recv)(int, char *, int, int) = NULL; +int (*apr_os2_send)(int, const char *, int, int) = NULL; +int (*apr_os2_setsockopt)(int, int, int, char *, int) = NULL; +int (*apr_os2_shutdown)(int, int) = NULL; +int (*apr_os2_soclose)(int) = NULL; +int (*apr_os2_writev)(int, struct iovec *, int) = NULL; +int (*apr_os2_sendto)(int, const char *, int, int, const struct sockaddr *, int); +int (*apr_os2_recvfrom)(int, char *, int, int, struct sockaddr *, int *); + +static HMODULE hSO32DLL; + +static int os2_fn_link() +{ + DosEnterCritSec(); /* Stop two threads doing this at the same time */ + + if (apr_os2_socket == os2_socket_init) { + ULONG rc; + char errorstr[200]; + + rc = DosLoadModule(errorstr, sizeof(errorstr), "SO32DLL", &hSO32DLL); + + if (rc) + return APR_OS2_STATUS(rc); + + rc = DosQueryProcAddr(hSO32DLL, 0, "SOCKET", &apr_os2_socket); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SELECT", &apr_os2_select); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SOCK_ERRNO", &apr_os2_sock_errno); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "ACCEPT", &apr_os2_accept); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "BIND", &apr_os2_bind); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "CONNECT", &apr_os2_connect); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "GETPEERNAME", &apr_os2_getpeername); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "GETSOCKNAME", &apr_os2_getsockname); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "GETSOCKOPT", &apr_os2_getsockopt); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "IOCTL", &apr_os2_ioctl); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "LISTEN", &apr_os2_listen); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "RECV", &apr_os2_recv); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SEND", &apr_os2_send); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SETSOCKOPT", &apr_os2_setsockopt); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SHUTDOWN", &apr_os2_shutdown); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SOCLOSE", &apr_os2_soclose); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "WRITEV", &apr_os2_writev); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SENDTO", &apr_os2_sendto); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "RECVFROM", &apr_os2_recvfrom); + + if (rc) + return APR_OS2_STATUS(rc); + } + + DosExitCritSec(); + return APR_SUCCESS; +} + + + +static int os2_socket_init(int domain, int type, int protocol) +{ + int rc = os2_fn_link(); + if (rc == APR_SUCCESS) + return apr_os2_socket(domain, type, protocol); + return rc; +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sendrecv.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sendrecv.c new file mode 100644 index 00000000..73b12c2b --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sendrecv.c @@ -0,0 +1,177 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_network_io.h" +#include "apr_lib.h" +#include <sys/time.h> + +APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int fds, err = 0; + + if (*len > 65536) { + *len = 65536; + } + + do { + if (!sock->nonblock || err == SOCEWOULDBLOCK) { + fds = sock->socketdes; + rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); + + if (rv != 1) { + *len = 0; + err = sock_errno(); + + if (rv == 0) + return APR_TIMEUP; + + if (err == SOCEINTR) + continue; + + return APR_OS2_STATUS(err); + } + } + + rv = send(sock->socketdes, buf, (*len), 0); + err = rv < 0 ? sock_errno() : 0; + } while (err == SOCEINTR || err == SOCEWOULDBLOCK); + + if (err) { + *len = 0; + return APR_OS2_STATUS(err); + } + + (*len) = rv; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int fds, err = 0; + + do { + if (!sock->nonblock || (err == SOCEWOULDBLOCK && sock->timeout != 0)) { + fds = sock->socketdes; + rv = select(&fds, 1, 0, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); + + if (rv != 1) { + *len = 0; + err = sock_errno(); + + if (rv == 0) + return APR_TIMEUP; + + if (err == SOCEINTR) + continue; + + return APR_OS2_STATUS(err); + } + } + + rv = recv(sock->socketdes, buf, (*len), 0); + err = rv < 0 ? sock_errno() : 0; + } while (err == SOCEINTR || (err == SOCEWOULDBLOCK && sock->timeout != 0)); + + if (err) { + *len = 0; + return APR_OS2_STATUS(err); + } + + (*len) = rv; + return rv == 0 ? APR_EOF : APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + apr_status_t rv; + struct iovec *tmpvec; + int fds, err = 0; + int nv_tosend, total = 0; + + /* Make sure writev() only gets fed 64k at a time */ + for ( nv_tosend = 0; nv_tosend < nvec && total + vec[nv_tosend].iov_len < 65536; nv_tosend++ ) { + total += vec[nv_tosend].iov_len; + } + + tmpvec = alloca(sizeof(struct iovec) * nv_tosend); + memcpy(tmpvec, vec, sizeof(struct iovec) * nv_tosend); + + do { + if (!sock->nonblock || err == SOCEWOULDBLOCK) { + fds = sock->socketdes; + rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); + + if (rv != 1) { + *len = 0; + err = sock_errno(); + + if (rv == 0) + return APR_TIMEUP; + + if (err == SOCEINTR) + continue; + + return APR_OS2_STATUS(err); + } + } + + rv = writev(sock->socketdes, tmpvec, nv_tosend); + err = rv < 0 ? sock_errno() : 0; + } while (err == SOCEINTR || err == SOCEWOULDBLOCK); + + if (err) { + *len = 0; + return APR_OS2_STATUS(err); + } + + *len = rv; + return APR_SUCCESS; +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + return apr_socket_send(sock, buf, len); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + return apr_socket_sendv(sock, vec, nvec, len); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + return apr_socket_recv(sock, buf, len); +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sendrecv_udp.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sendrecv_udp.c new file mode 100644 index 00000000..0e23d11e --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sendrecv_udp.c @@ -0,0 +1,122 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_network_io.h" +#include "apr_support.h" +#include "apr_lib.h" +#include <sys/time.h> + + +APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int serrno; + + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && (serrno = sock_errno()) == EINTR); + + if (rv == -1 && serrno == SOCEWOULDBLOCK && sock->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = sendto(sock->socketdes, buf, *len, flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && (serrno = sock_errno()) == SOCEINTR); + } + } + + if (rv == -1) { + *len = 0; + return APR_FROM_OS_ERROR(serrno); + } + + *len = rv; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int serrno; + + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && (serrno = sock_errno()) == EINTR); + + if (rv == -1 && serrno == SOCEWOULDBLOCK && sock->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 1); + + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = recvfrom(sock->socketdes, buf, *len, flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && (serrno = sock_errno()) == EINTR); + } + } + + if (rv == -1) { + (*len) = 0; + return APR_FROM_OS_ERROR(serrno); + } + + (*len) = rv; + + if (rv == 0 && sock->type == SOCK_STREAM) + return APR_EOF; + + return APR_SUCCESS; +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + return apr_socket_sendto(sock, where, flags, buf, len); +} + + + +APR_DECLARE(apr_status_t) apr_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + return apr_socket_recvfrom(from, sock, flags, buf, len); +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockaddr.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockaddr.c new file mode 100644 index 00000000..2afe4b77 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockaddr.c @@ -0,0 +1 @@ +#include "../unix/sockaddr.c" diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockets.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockets.c new file mode 100644 index 00000000..38196642 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockets.c @@ -0,0 +1,343 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_arch_inherit.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_portable.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include <errno.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/tcp.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include "apr_arch_os2calls.h" + +static apr_status_t socket_cleanup(void *sock) +{ + apr_socket_t *thesocket = sock; + + if (thesocket->socketdes < 0) { + return APR_EINVALSOCK; + } + + if (soclose(thesocket->socketdes) == 0) { + thesocket->socketdes = -1; + return APR_SUCCESS; + } + else { + return APR_OS2_STATUS(sock_errno()); + } +} + +static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) +{ + sock->type = type; + sock->protocol = protocol; + apr_sockaddr_vars_set(sock->local_addr, family, 0); + apr_sockaddr_vars_set(sock->remote_addr, family, 0); +} + +static void alloc_socket(apr_socket_t **new, apr_pool_t *p) +{ + *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); + (*new)->cntxt = p; + (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->local_addr->pool = p; + (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->remote_addr->pool = p; +} + +APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, int *protocol) +{ + *protocol = sock->protocol; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_create_ex(apr_socket_t **new, int family, int type, + int protocol, apr_pool_t *cont) +{ + int downgrade = (family == AF_UNSPEC); + + if (family == AF_UNSPEC) { +#if APR_HAVE_IPV6 + family = AF_INET6; +#else + family = AF_INET; +#endif + } + + alloc_socket(new, cont); + + (*new)->socketdes = socket(family, type, protocol); +#if APR_HAVE_IPV6 + if ((*new)->socketdes < 0 && downgrade) { + family = AF_INET; + (*new)->socketdes = socket(family, type, protocol); + } +#endif + + if ((*new)->socketdes < 0) { + return APR_OS2_STATUS(sock_errno()); + } + set_socket_vars(*new, family, type, protocol); + + (*new)->timeout = -1; + (*new)->nonblock = FALSE; + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family, int type, + apr_pool_t *cont) +{ + return apr_socket_create_ex(new, family, type, 0, cont); +} + +APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + if (shutdown(thesocket->socketdes, how) == 0) { + return APR_SUCCESS; + } + else { + return APR_OS2_STATUS(sock_errno()); + } +} + +APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket) +{ + apr_pool_cleanup_kill(thesocket->cntxt, thesocket, socket_cleanup); + return socket_cleanup(thesocket); +} + +APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + if (bind(sock->socketdes, + (struct sockaddr *)&sa->sa, + sa->salen) == -1) + return APR_OS2_STATUS(sock_errno()); + else { + sock->local_addr = sa; + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */ + sock->local_port_unknown = 1; /* kernel got us an ephemeral port */ + } + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, + apr_int32_t backlog) +{ + if (listen(sock->socketdes, backlog) == -1) + return APR_OS2_STATUS(sock_errno()); + else + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, + apr_socket_t *sock, + apr_pool_t *connection_context) +{ + alloc_socket(new, connection_context); + set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, sock->protocol); + + (*new)->timeout = -1; + (*new)->nonblock = FALSE; + + (*new)->socketdes = accept(sock->socketdes, + (struct sockaddr *)&(*new)->remote_addr->sa, + &(*new)->remote_addr->salen); + + if ((*new)->socketdes < 0) { + return APR_OS2_STATUS(sock_errno()); + } + + *(*new)->local_addr = *sock->local_addr; + (*new)->local_addr->pool = connection_context; + (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); + + /* fix up any pointers which are no longer valid */ + if (sock->local_addr->sa.sin.sin_family == AF_INET) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; + } + + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + if ((connect(sock->socketdes, (struct sockaddr *)&sa->sa.sin, + sa->salen) < 0) && + (sock_errno() != SOCEINPROGRESS)) { + return APR_OS2_STATUS(sock_errno()); + } + else { + int namelen = sizeof(sock->local_addr->sa.sin); + getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa.sin, + &namelen); + sock->remote_addr = sa; + return APR_SUCCESS; + } +} + + +APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key, + apr_socket_t *sock) +{ + sock_userdata_t *cur = sock->userdata; + + *data = NULL; + + while (cur) { + if (!strcmp(cur->key, key)) { + *data = cur->data; + break; + } + cur = cur->next; + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, const char *key, + apr_status_t (*cleanup) (void *)) +{ + sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t)); + + new->key = apr_pstrdup(sock->cntxt, key); + new->data = data; + new->next = sock->userdata; + sock->userdata = new; + + if (cleanup) { + apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock) +{ + *thesock = sock->socketdes; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont) +{ + alloc_socket(apr_sock, cont); +#ifdef APR_ENABLE_FOR_1_0 /* no protocol field yet */ + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); +#else + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, 0); +#endif + (*apr_sock)->timeout = -1; + (*apr_sock)->socketdes = *os_sock_info->os_sock; + if (os_sock_info->local) { + memcpy(&(*apr_sock)->local_addr->sa.sin, + os_sock_info->local, + (*apr_sock)->local_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; + } + if (os_sock_info->remote) { + memcpy(&(*apr_sock)->remote_addr->sa.sin, + os_sock_info->remote, + (*apr_sock)->remote_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->remote_addr_unknown = 1; + } + + apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock), + socket_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, apr_pool_t *cont) +{ + if (cont == NULL) { + return APR_ENOPOOL; + } + if ((*sock) == NULL) { + alloc_socket(sock, cont); + set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0); + (*sock)->timeout = -1; + } + + (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; + (*sock)->remote_addr_unknown = 1; + (*sock)->socketdes = *thesock; + return APR_SUCCESS; +} + +APR_IMPLEMENT_INHERIT_SET(socket, inherit, cntxt, socket_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, cntxt, socket_cleanup) + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + return apr_socket_shutdown(thesocket, how); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + return apr_socket_bind(sock, sa); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_listen(apr_socket_t *sock, apr_int32_t backlog) +{ + return apr_socket_listen(sock, backlog); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_accept(apr_socket_t **new, apr_socket_t *sock, + apr_pool_t *connection_context) +{ + return apr_socket_accept(new, sock, connection_context); +} + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + return apr_socket_connect(sock, sa); +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockopt.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockopt.c new file mode 100644 index 00000000..5a668d14 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/os2/sockopt.c @@ -0,0 +1,161 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include <errno.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/tcp.h> +#include <netinet/in.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/so_ioctl.h> + + +APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, + apr_interval_time_t t) +{ + sock->timeout = t; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + int one; + struct linger li; + + if (on) + one = 1; + else + one = 0; + + if (opt & APR_SO_KEEPALIVE) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_DEBUG) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_REUSEADDR) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_SNDBUF) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void *)&on, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_NONBLOCK) { + if (ioctl(sock->socketdes, FIONBIO, (caddr_t)&one, sizeof(one)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } else { + sock->nonblock = one; + } + } + if (opt & APR_SO_LINGER) { + li.l_onoff = on; + li.l_linger = APR_MAX_SECS_TO_LINGER; + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_TIMEOUT) { + /* XXX: To be deprecated */ + return apr_socket_timeout_set(sock, on); + } + if (opt & APR_TCP_NODELAY) { + if (setsockopt(sock->socketdes, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, + apr_interval_time_t *t) +{ + *t = sock->timeout; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + switch(opt) { + case APR_SO_TIMEOUT: + /* XXX: To be deprecated */ + *on = (apr_int32_t)sock->timeout; + break; + default: + return APR_EINVAL; + } + return APR_SUCCESS; +} + + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_setsocketopt(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + return apr_socket_opt_set(sock, opt, on); +} + +APR_DECLARE(apr_status_t) apr_getsocketopt(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + return apr_socket_opt_get(sock, opt, on); +} + + +APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark) +{ + int oobmark; + + if (ioctl(sock->socketdes, SIOCATMARK, (void*)&oobmark, sizeof(oobmark)) < 0) { + return APR_OS2_STATUS(sock_errno()); + } + + *atmark = (oobmark != 0); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_gethostname(char *buf, apr_int32_t len, + apr_pool_t *cont) +{ + if (gethostname(buf, len) == -1) { + buf[0] = '\0'; + return APR_OS2_STATUS(sock_errno()); + } + else if (!memchr(buf, '\0', len)) { /* buffer too small */ + buf[0] = '\0'; + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/inet_ntop.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/inet_ntop.o Binary files differnew file mode 100644 index 00000000..817cc79d --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/inet_ntop.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/inet_pton.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/inet_pton.o Binary files differnew file mode 100644 index 00000000..2e7742cd --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/inet_pton.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sendrecv.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sendrecv.o Binary files differnew file mode 100644 index 00000000..491c3a31 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sendrecv.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockaddr.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockaddr.o Binary files differnew file mode 100644 index 00000000..b2e965fb --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockaddr.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockets.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockets.o Binary files differnew file mode 100644 index 00000000..fef86515 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockets.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockopt.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockopt.o Binary files differnew file mode 100644 index 00000000..d0d49c18 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/.libs/sockopt.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/Makefile b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/Makefile new file mode 100644 index 00000000..a942d0d5 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/Makefile @@ -0,0 +1,20 @@ +srcdir = . + + +TARGETS = \ + sendrecv.lo \ + sockets.lo \ + sockopt.lo \ + sockaddr.lo \ + inet_ntop.lo \ + inet_pton.lo + +# bring in rules.mk for standard functionality +include /bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr/build/apr_rules.mk + +INCDIR=../../include +OSDIR=$(INCDIR)/arch/unix +DEFOSDIR=$(INCDIR)/arch/unix +INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) + +# DO NOT REMOVE diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/Makefile.in b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/Makefile.in new file mode 100644 index 00000000..3ea7d03b --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/Makefile.in @@ -0,0 +1,20 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +TARGETS = \ + sendrecv.lo \ + sockets.lo \ + sockopt.lo \ + sockaddr.lo \ + inet_ntop.lo \ + inet_pton.lo + +# bring in rules.mk for standard functionality +@INCLUDE_RULES@ + +INCDIR=../../include +OSDIR=$(INCDIR)/arch/@OSDIR@ +DEFOSDIR=$(INCDIR)/arch/@DEFAULT_OSDIR@ +INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) + +# DO NOT REMOVE diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.c new file mode 100644 index 00000000..78dd3baa --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.c @@ -0,0 +1,243 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "apr_private.h" +#include "apr_arch_networkio.h" +#include "apr_strings.h" + +#if APR_HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if APR_HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if APR_HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if APR_HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#include <string.h> +#if APR_HAVE_ERRNO_H +#include <errno.h> +#endif +#include <stdio.h> + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 +#endif + +#ifndef INT16SZ +#define INT16SZ sizeof(apr_int16_t) +#endif + +#ifndef __P +#define __P(x) x +#endif + +#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT) +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const unsigned char *src, char *dst, apr_size_t size)); +#if APR_HAVE_IPV6 +static const char *inet_ntop6 __P((const unsigned char *src, char *dst, apr_size_t size)); +#endif + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#if APR_HAVE_IPV6 + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const unsigned char *src, char *dst, apr_size_t size) +{ + const apr_size_t MIN_SIZE = 16; /* space for 255.255.255.255\0 */ + int n = 0; + char *next = dst; + + if (size < MIN_SIZE) { + errno = ENOSPC; + return NULL; + } + do { + unsigned char u = *src++; + if (u > 99) { + *next++ = '0' + u/100; + u %= 100; + *next++ = '0' + u/10; + u %= 10; + } + else if (u > 9) { + *next++ = '0' + u/10; + u %= 10; + } + *next++ = '0' + u; + *next++ = '.'; + n++; + } while (n < 4); + *--next = 0; + return dst; +} + +#if APR_HAVE_IPV6 +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(const unsigned char *src, char *dst, apr_size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best = {-1, 0}, cur = {-1, 0}; + unsigned int words[IN6ADDRSZ / INT16SZ]; + int i; + const unsigned char *next_src, *src_end; + unsigned int *next_dest; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + next_src = src; + src_end = src + IN6ADDRSZ; + next_dest = words; + i = 0; + do { + unsigned int next_word = (unsigned int)*next_src++; + next_word <<= 8; + next_word |= (unsigned int)*next_src++; + *next_dest++ = next_word; + + if (next_word == 0) { + if (cur.base == -1) { + cur.base = i; + cur.len = 1; + } + else { + cur.len++; + } + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) { + best = cur; + } + cur.base = -1; + } + } + + i++; + } while (next_src < src_end); + + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) { + best = cur; + } + } + if (best.base != -1 && best.len < 2) { + best.base = -1; + } + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (IN6ADDRSZ / INT16SZ);) { + /* Are we inside the best run of 0x00's? */ + if (i == best.base) { + *tp++ = ':'; + i += best.len; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) { + *tp++ = ':'; + } + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) { + return (NULL); + } + tp += strlen(tp); + break; + } + tp += apr_snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]); + i++; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { + *tp++ = ':'; + } + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((apr_size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} +#endif diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.lo b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.lo new file mode 100644 index 00000000..2345ed35 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.lo @@ -0,0 +1,12 @@ +# inet_ntop.lo - a libtool object file +# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/inet_ntop.o' + +# Name of the non-PIC object. +non_pic_object='inet_ntop.o' + diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.o Binary files differnew file mode 100644 index 00000000..0812ba54 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_ntop.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.c new file mode 100644 index 00000000..550ab2a4 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.c @@ -0,0 +1,240 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "apr_private.h" +#include "apr_arch_networkio.h" + +#if APR_HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if APR_HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if APR_HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if APR_HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#include <string.h> +#if APR_HAVE_ERRNO_H +#include <errno.h> +#endif + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 +#endif + +#ifndef INT16SZ +#define INT16SZ sizeof(apr_int16_t) +#endif + +#ifndef INADDRSZ +#define INADDRSZ 4 +#endif + +#ifndef __P +#define __P(x) x +#endif + +#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT) +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 __P((const char *src, unsigned char *dst)); +#if APR_HAVE_IPV6 +static int inet_pton6 __P((const char *src, unsigned char *dst)); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +apr_inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); +#if APR_HAVE_IPV6 + case AF_INET6: + return (inet_pton6(src, dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + unsigned int new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + + memcpy(dst, tmp, INADDRSZ); + return (1); +} + +#if APR_HAVE_IPV6 +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + unsigned int val; + + memset((tp = tmp), '\0', IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, IN6ADDRSZ); + return (1); +} +#endif diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.lo b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.lo new file mode 100644 index 00000000..780b7a7b --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.lo @@ -0,0 +1,12 @@ +# inet_pton.lo - a libtool object file +# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/inet_pton.o' + +# Name of the non-PIC object. +non_pic_object='inet_pton.o' + diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.o Binary files differnew file mode 100644 index 00000000..0601b0dd --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/inet_pton.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.c new file mode 100644 index 00000000..bf1bf99f --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.c @@ -0,0 +1,1014 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_support.h" + +#if APR_HAS_SENDFILE +/* This file is needed to allow us access to the apr_file_t internals. */ +#include "apr_arch_file_io.h" +#endif /* APR_HAS_SENDFILE */ + +/* sys/sysctl.h is only needed on FreeBSD for include_hdrs_in_length() */ +#if defined(__FreeBSD__) && defined(HAVE_SYS_SYSCTL_H) +#include <sys/sysctl.h> +#endif + +apr_status_t apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + if (sock->netmask & APR_INCOMPLETE_WRITE) { + sock->netmask &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = write(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) + && apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + apr_status_t arv; +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = write(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) && rv < *len) { + sock->netmask |= APR_INCOMPLETE_WRITE; + } + (*len) = rv; + return APR_SUCCESS; +} + +apr_status_t apr_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len) +{ + apr_ssize_t rv; + apr_status_t arv; + + if (sock->netmask & APR_INCOMPLETE_READ) { + sock->netmask &= ~APR_INCOMPLETE_READ; + goto do_select; + } + + do { + rv = read(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = read(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) && rv < *len) { + sock->netmask |= APR_INCOMPLETE_READ; + } + (*len) = rv; + if (rv == 0) { + return APR_EOF; + } + return APR_SUCCESS; +} + +apr_status_t apr_socket_sendto(apr_socket_t *sock, apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) + && apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + *len = rv; + return APR_SUCCESS; +} + +apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + + (*len) = rv; + if (rv == 0 && sock->type == SOCK_STREAM) { + return APR_EOF; + } + + return APR_SUCCESS; +} + +#ifdef HAVE_WRITEV +apr_status_t apr_socket_sendv(apr_socket_t * sock, const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + apr_ssize_t rv; + apr_size_t requested_len = 0; + apr_int32_t i; + + for (i = 0; i < nvec; i++) { + requested_len += vec[i].iov_len; + } + + if (sock->netmask & APR_INCOMPLETE_WRITE) { + sock->netmask &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = writev(sock->socketdes, vec, nvec); + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + apr_status_t arv; +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = writev(sock->socketdes, vec, nvec); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) && + rv < requested_len) { + sock->netmask |= APR_INCOMPLETE_WRITE; + } + (*len) = rv; + return APR_SUCCESS; +} +#endif + +#if APR_HAS_SENDFILE + +/* TODO: Verify that all platforms handle the fd the same way, + * i.e. that they don't move the file pointer. + */ +/* TODO: what should flags be? int_32? */ + +/* Define a structure to pass in when we have a NULL header value */ +static apr_hdtr_t no_hdtr; + +#if defined(__linux__) && defined(HAVE_WRITEV) + +apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, + apr_size_t *len, apr_int32_t flags) +{ + off_t off = *offset; + int rv, nbytes = 0, total_hdrbytes, i; + apr_status_t arv; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + if (hdtr->numheaders > 0) { + apr_size_t hdrbytes; + + /* cork before writing headers */ + rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 1); + if (rv != APR_SUCCESS) { + return rv; + } + + /* Now write the headers */ + arv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, + &hdrbytes); + if (arv != APR_SUCCESS) { + *len = 0; + return errno; + } + nbytes += hdrbytes; + + /* If this was a partial write and we aren't doing timeouts, + * return now with the partial byte count; this is a non-blocking + * socket. + */ + total_hdrbytes = 0; + for (i = 0; i < hdtr->numheaders; i++) { + total_hdrbytes += hdtr->headers[i].iov_len; + } + if (hdrbytes < total_hdrbytes) { + *len = hdrbytes; + return apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + } + } + + if (sock->netmask & APR_INCOMPLETE_WRITE) { + sock->netmask &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = sendfile(sock->socketdes, /* socket */ + file->filedes, /* open file descriptor of the file to be sent */ + &off, /* where in the file to start */ + *len); /* number of bytes to send */ + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK) && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = sendfile(sock->socketdes, /* socket */ + file->filedes, /* open file descriptor of the file to be sent */ + &off, /* where in the file to start */ + *len); /* number of bytes to send */ + } while (rv == -1 && errno == EINTR); + } + } + + if (rv == -1) { + *len = nbytes; + rv = errno; + apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + return rv; + } + + nbytes += rv; + + if (rv < *len) { + *len = nbytes; + arv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + if (rv > 0) { + + /* If this was a partial write, return now with the + * partial byte count; this is a non-blocking socket. + */ + + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + sock->netmask |= APR_INCOMPLETE_WRITE; + } + return arv; + } + else { + /* If the file got smaller mid-request, eventually the offset + * becomes equal to the new file size and the kernel returns 0. + * Make this an error so the caller knows to log something and + * exit. + */ + return APR_EOF; + } + } + + /* Now write the footers */ + if (hdtr->numtrailers > 0) { + apr_size_t trbytes; + arv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, + &trbytes); + nbytes += trbytes; + if (arv != APR_SUCCESS) { + *len = nbytes; + rv = errno; + apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + return rv; + } + } + + apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + + (*len) = nbytes; + return rv < 0 ? errno : APR_SUCCESS; +} + +#elif defined(__FreeBSD__) + +static int include_hdrs_in_length(void) +{ +#ifdef HAVE_SYS_SYSCTL_H +/* this assumes: + * if the header exists, so does the sysctlbyname() syscall, and + * if the header doesn't exist, the kernel is really old + */ + +/* see + * http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/param.h#rev1.61.2.29 + * for kernel version number + * + * http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/kern/uipc_syscalls.c#rev1.65.2.10 + * for the sendfile patch + */ +#define KERNEL_WITH_SENDFILE_LENGTH_FIX 460001 + + typedef enum { UNKNOWN = 0, + NEW, + OLD + } api_e; + + static api_e api; + int kernel_version; + apr_size_t kernel_version_size; + + if (api != UNKNOWN) { + return (api == OLD); + } + kernel_version = 0; /* silence compiler warning */ + kernel_version_size = sizeof(kernel_version); + if (sysctlbyname("kern.osreldate", &kernel_version, + &kernel_version_size, NULL, 0) == 0 && + kernel_version < KERNEL_WITH_SENDFILE_LENGTH_FIX) { + api = OLD; + return 1; + } + /* size of kern.osreldate's output might change in the future + * causing the sysctlbyname to fail, + * but if it's the future, we should use the newer API + */ + api = NEW; + return 0; +#else + /* the build system's kernel is older than 3.4. Use the old API */ + return 1; +#endif +} + +/* Release 3.1 or greater */ +apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file, + apr_hdtr_t * hdtr, apr_off_t * offset, + apr_size_t * len, apr_int32_t flags) +{ + off_t nbytes = 0; + int rv, i; + struct sf_hdtr headerstruct; + apr_size_t bytes_to_send = *len; + + /* Ignore flags for now. */ + flags = 0; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + else if (hdtr->numheaders && include_hdrs_in_length()) { + + /* On early versions of FreeBSD sendfile, the number of bytes to send + * must include the length of the headers. Don't look at the man page + * for this :( Instead, look at the the logic in + * src/sys/kern/uipc_syscalls::sendfile(). + * + * This was fixed in the middle of 4.6-STABLE + */ + for (i = 0; i < hdtr->numheaders; i++) { + bytes_to_send += hdtr->headers[i].iov_len; + } + } + + headerstruct.headers = hdtr->headers; + headerstruct.hdr_cnt = hdtr->numheaders; + headerstruct.trailers = hdtr->trailers; + headerstruct.trl_cnt = hdtr->numtrailers; + + /* FreeBSD can send the headers/footers as part of the system call */ + do { + if (sock->netmask & APR_INCOMPLETE_WRITE) { + apr_status_t arv; + sock->netmask &= ~APR_INCOMPLETE_WRITE; + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + if (bytes_to_send) { + /* We won't dare call sendfile() if we don't have + * header or file bytes to send because bytes_to_send == 0 + * means send the whole file. + */ + rv = sendfile(file->filedes, /* file to be sent */ + sock->socketdes, /* socket */ + *offset, /* where in the file to start */ + bytes_to_send, /* number of bytes to send */ + &headerstruct, /* Headers/footers */ + &nbytes, /* number of bytes written */ + flags); /* undefined, set to 0 */ + + if (rv == -1) { + if (errno == EAGAIN) { + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + sock->netmask |= APR_INCOMPLETE_WRITE; + } + /* FreeBSD's sendfile can return -1/EAGAIN even if it + * sent bytes. Sanitize the result so we get normal EAGAIN + * semantics w.r.t. bytes sent. + */ + if (nbytes) { + /* normal exit for a big file & non-blocking io */ + (*len) = nbytes; + return APR_SUCCESS; + } + } + } + else { /* rv == 0 (or the kernel is broken) */ + if (nbytes == 0) { + /* Most likely the file got smaller after the stat. + * Return an error so the caller can do the Right Thing. + */ + (*len) = nbytes; + return APR_EOF; + } + } + } + else { + /* just trailer bytes... use writev() + */ + rv = writev(sock->socketdes, + hdtr->trailers, + hdtr->numtrailers); + if (rv > 0) { + nbytes = rv; + rv = 0; + } + else { + nbytes = 0; + } + } + if (rv == -1 && + errno == EAGAIN && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + } while (rv == -1 && (errno == EINTR || errno == EAGAIN)); + + (*len) = nbytes; + if (rv == -1) { + return errno; + } + return APR_SUCCESS; +} + +#elif defined(__hpux) || defined(__hpux__) + +/* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */ + +/* HP-UX Version 10.30 or greater + * (no worries, because we only get here if autoconfiguration found sendfile) + */ + +/* ssize_t sendfile(int s, int fd, off_t offset, size_t nbytes, + * const struct iovec *hdtrl, int flags); + * + * nbytes is the number of bytes to send just from the file; as with FreeBSD, + * if nbytes == 0, the rest of the file (from offset) is sent + */ + +apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, + apr_size_t *len, apr_int32_t flags) +{ + int i; + apr_ssize_t rc; + apr_size_t nbytes = *len, headerlen, trailerlen; + struct iovec hdtrarray[2]; + char *headerbuf, *trailerbuf; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + /* HP-UX can only send one header iovec and one footer iovec; try to + * only allocate storage to combine input iovecs when we really have to + */ + + switch(hdtr->numheaders) { + case 0: + hdtrarray[0].iov_base = NULL; + hdtrarray[0].iov_len = 0; + break; + case 1: + hdtrarray[0] = hdtr->headers[0]; + break; + default: + headerlen = 0; + for (i = 0; i < hdtr->numheaders; i++) { + headerlen += hdtr->headers[i].iov_len; + } + + /* XXX: BUHHH? wow, what a memory leak! */ + headerbuf = hdtrarray[0].iov_base = apr_palloc(sock->cntxt, headerlen); + hdtrarray[0].iov_len = headerlen; + + for (i = 0; i < hdtr->numheaders; i++) { + memcpy(headerbuf, hdtr->headers[i].iov_base, + hdtr->headers[i].iov_len); + headerbuf += hdtr->headers[i].iov_len; + } + } + + switch(hdtr->numtrailers) { + case 0: + hdtrarray[1].iov_base = NULL; + hdtrarray[1].iov_len = 0; + break; + case 1: + hdtrarray[1] = hdtr->trailers[0]; + break; + default: + trailerlen = 0; + for (i = 0; i < hdtr->numtrailers; i++) { + trailerlen += hdtr->trailers[i].iov_len; + } + + /* XXX: BUHHH? wow, what a memory leak! */ + trailerbuf = hdtrarray[1].iov_base = apr_palloc(sock->cntxt, trailerlen); + hdtrarray[1].iov_len = trailerlen; + + for (i = 0; i < hdtr->numtrailers; i++) { + memcpy(trailerbuf, hdtr->trailers[i].iov_base, + hdtr->trailers[i].iov_len); + trailerbuf += hdtr->trailers[i].iov_len; + } + } + + do { + if (nbytes) { /* any bytes to send from the file? */ + rc = sendfile(sock->socketdes, /* socket */ + file->filedes, /* file descriptor to send */ + *offset, /* where in the file to start */ + nbytes, /* number of bytes to send from file */ + hdtrarray, /* Headers/footers */ + flags); /* undefined, set to 0 */ + } + else { /* we can't call sendfile() with no bytes to send from the file */ + rc = writev(sock->socketdes, hdtrarray, 2); + } + } while (rc == -1 && errno == EINTR); + + while (rc == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK) && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + if (nbytes) { + rc = sendfile(sock->socketdes, /* socket */ + file->filedes, /* file descriptor to send */ + *offset, /* where in the file to start */ + nbytes, /* number of bytes to send from file */ + hdtrarray, /* Headers/footers */ + flags); /* undefined, set to 0 */ + } + else { /* we can't call sendfile() with no bytes to send from the file */ + rc = writev(sock->socketdes, hdtrarray, 2); + } + } while (rc == -1 && errno == EINTR); + } + } + + if (rc == -1) { + *len = 0; + return errno; + } + + /* Set len to the number of bytes written */ + *len = rc; + return APR_SUCCESS; +} +#elif defined(_AIX) || defined(__MVS__) +/* AIX and OS/390 have the same send_file() interface. + * + * subtle differences: + * AIX doesn't update the file ptr but OS/390 does + * + * availability (correctly determined by autoconf): + * + * AIX - version 4.3.2 with APAR IX85388, or version 4.3.3 and above + * OS/390 - V2R7 and above + */ +apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file, + apr_hdtr_t * hdtr, apr_off_t * offset, + apr_size_t * len, apr_int32_t flags) +{ + int i, ptr, rv = 0; + void * hbuf=NULL, * tbuf=NULL; + apr_status_t arv; + struct sf_parms parms; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + /* word to the wise: by default, AIX stores files sent by send_file() + * in the network buffer cache... there are supposedly scenarios + * where the most recent copy of the file won't be sent, but I can't + * recreate the potential problem, perhaps because of the way we + * use send_file()... if you suspect such a problem, try turning + * on the SF_SYNC_CACHE flag + */ + + /* AIX can also send the headers/footers as part of the system call */ + parms.header_length = 0; + if (hdtr && hdtr->numheaders) { + if (hdtr->numheaders == 1) { + parms.header_data = hdtr->headers[0].iov_base; + parms.header_length = hdtr->headers[0].iov_len; + } + else { + for (i = 0; i < hdtr->numheaders; i++) { + parms.header_length += hdtr->headers[i].iov_len; + } +#if 0 + /* Keepalives make apr_palloc a bad idea */ + hbuf = malloc(parms.header_length); +#else + /* but headers are small, so maybe we can hold on to the + * memory for the life of the socket... + */ + hbuf = apr_palloc(sock->cntxt, parms.header_length); +#endif + ptr = 0; + for (i = 0; i < hdtr->numheaders; i++) { + memcpy((char *)hbuf + ptr, hdtr->headers[i].iov_base, + hdtr->headers[i].iov_len); + ptr += hdtr->headers[i].iov_len; + } + parms.header_data = hbuf; + } + } + else parms.header_data = NULL; + parms.trailer_length = 0; + if (hdtr && hdtr->numtrailers) { + if (hdtr->numtrailers == 1) { + parms.trailer_data = hdtr->trailers[0].iov_base; + parms.trailer_length = hdtr->trailers[0].iov_len; + } + else { + for (i = 0; i < hdtr->numtrailers; i++) { + parms.trailer_length += hdtr->trailers[i].iov_len; + } +#if 0 + /* Keepalives make apr_palloc a bad idea */ + tbuf = malloc(parms.trailer_length); +#else + tbuf = apr_palloc(sock->cntxt, parms.trailer_length); +#endif + ptr = 0; + for (i = 0; i < hdtr->numtrailers; i++) { + memcpy((char *)tbuf + ptr, hdtr->trailers[i].iov_base, + hdtr->trailers[i].iov_len); + ptr += hdtr->trailers[i].iov_len; + } + parms.trailer_data = tbuf; + } + } + else { + parms.trailer_data = NULL; + } + + /* Whew! Headers and trailers set up. Now for the file data */ + + parms.file_descriptor = file->filedes; + parms.file_offset = *offset; + parms.file_bytes = *len; + + /* O.K. All set up now. Let's go to town */ + + if (sock->netmask & APR_INCOMPLETE_WRITE) { + sock->netmask &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = send_file(&(sock->socketdes), /* socket */ + &(parms), /* all data */ + flags); /* flags */ + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK) && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = send_file(&(sock->socketdes), /* socket */ + &(parms), /* all data */ + flags); /* flags */ + } while (rv == -1 && errno == EINTR); + } + } + + (*len) = parms.bytes_sent; + +#if 0 + /* Clean up after ourselves */ + if(hbuf) free(hbuf); + if(tbuf) free(tbuf); +#endif + + if (rv == -1) { + return errno; + } + + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) && + (parms.bytes_sent < (parms.file_bytes + parms.header_length + parms.trailer_length))) { + sock->netmask |= APR_INCOMPLETE_WRITE; + } + + return APR_SUCCESS; +} +#elif defined(__osf__) && defined (__alpha) +/* Tru64's sendfile implementation doesn't work, and we need to make sure that + * we don't use it until it is fixed. If it is used as it is now, it will + * hang the machine and the only way to fix it is a reboot. + */ +#elif defined(HAVE_SENDFILEV) +/* Solaris 8's sendfilev() interface + * + * SFV_FD_SELF refers to our memory space. + * + * Required Sparc patches (or newer): + * 111297-01, 108528-09, 109472-06, 109234-03, 108995-02, 111295-01, 109025-03, + * 108991-13 + * Required x86 patches (or newer): + * 111298-01, 108529-09, 109473-06, 109235-04, 108996-02, 111296-01, 109026-04, + * 108992-13 + */ +apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, + apr_size_t *len, apr_int32_t flags) +{ + apr_status_t rv, arv; + apr_size_t nbytes; + sendfilevec_t *sfv; + int vecs, curvec, i, repeat; + apr_size_t requested_len = 0; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + /* Calculate how much space we need. */ + vecs = hdtr->numheaders + hdtr->numtrailers + 1; + sfv = apr_palloc(sock->cntxt, sizeof(sendfilevec_t) * vecs); + + curvec = 0; + + /* Add the headers */ + for (i = 0; i < hdtr->numheaders; i++, curvec++) { + sfv[curvec].sfv_fd = SFV_FD_SELF; + sfv[curvec].sfv_flag = 0; + sfv[curvec].sfv_off = (off_t)hdtr->headers[i].iov_base; + sfv[curvec].sfv_len = hdtr->headers[i].iov_len; + requested_len += sfv[curvec].sfv_len; + } + + /* If the len is 0, we skip the file. */ + if (*len) + { + sfv[curvec].sfv_fd = file->filedes; + sfv[curvec].sfv_flag = 0; + sfv[curvec].sfv_off = *offset; + sfv[curvec].sfv_len = *len; + requested_len += sfv[curvec].sfv_len; + + curvec++; + } + else { + vecs--; + } + + /* Add the footers */ + for (i = 0; i < hdtr->numtrailers; i++, curvec++) { + sfv[curvec].sfv_fd = SFV_FD_SELF; + sfv[curvec].sfv_flag = 0; + sfv[curvec].sfv_off = (off_t)hdtr->trailers[i].iov_base; + sfv[curvec].sfv_len = hdtr->trailers[i].iov_len; + requested_len += sfv[curvec].sfv_len; + } + + /* If the last write couldn't send all the requested data, + * wait for the socket to become writable before proceeding + */ + if (sock->netmask & APR_INCOMPLETE_WRITE) { + sock->netmask &= ~APR_INCOMPLETE_WRITE; + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + + /* Actually do the sendfilev + * + * Solaris may return -1/EAGAIN even if it sent bytes on a non-block sock. + * + * If no bytes were originally sent (nbytes == 0) and we are on a TIMEOUT + * socket (which as far as the OS is concerned is a non-blocking socket), + * we want to retry after waiting for the other side to read the data (as + * determined by poll). Once it is clear to send, we want to retry + * sending the sendfilevec_t once more. + */ + arv = 0; + do { + /* Clear out the repeat */ + repeat = 0; + + /* socket, vecs, number of vecs, bytes written */ + rv = sendfilev(sock->socketdes, sfv, vecs, &nbytes); + + if (rv == -1 && errno == EAGAIN) { + if (nbytes) { + rv = 0; + } + else if (!arv && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) == 1) { + apr_status_t t = apr_wait_for_io_or_timeout(NULL, sock, 0); + + if (t != APR_SUCCESS) { + *len = 0; + return t; + } + + arv = 1; + repeat = 1; + } + } + } while ((rv == -1 && errno == EINTR) || repeat); + + if (rv == -1) { + *len = 0; + return errno; + } + + /* Update how much we sent */ + *len = nbytes; + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) && + (*len < requested_len)) { + sock->netmask |= APR_INCOMPLETE_WRITE; + } + return APR_SUCCESS; +} +#else +#error APR has detected sendfile on your system, but nobody has written a +#error version of it for APR yet. To get past this, either write apr_sendfile +#error or change APR_HAS_SENDFILE in apr.h to 0. +#endif /* __linux__, __FreeBSD__, __HPUX__, _AIX, __MVS__, Tru64/OSF1 */ + +/* deprecated */ +apr_status_t apr_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, apr_size_t *len, + apr_int32_t flags) +{ + return apr_socket_sendfile(sock, file, hdtr, offset, len, flags); +} + +#endif /* APR_HAS_SENDFILE */ + +/* deprecated */ +apr_status_t apr_send(apr_socket_t *sock, const char *buf, apr_size_t *len) +{ + return apr_socket_send(sock, buf, len); +} + +/* deprecated */ +#ifdef HAVE_WRITEV +apr_status_t apr_sendv(apr_socket_t * sock, const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + return apr_socket_sendv(sock, vec, nvec, len); +} +#endif + +/* deprecated */ +apr_status_t apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, apr_size_t *len) +{ + return apr_socket_sendto(sock, where, flags, buf, len); +} + +/* deprecated */ +apr_status_t apr_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + return apr_socket_recvfrom(from, sock, flags, buf, len); +} + +/* deprecated */ +apr_status_t apr_recv(apr_socket_t *sock, char *buf, apr_size_t *len) +{ + return apr_socket_recv(sock, buf, len); +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.lo b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.lo new file mode 100644 index 00000000..efa524a6 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.lo @@ -0,0 +1,12 @@ +# sendrecv.lo - a libtool object file +# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/sendrecv.o' + +# Name of the non-PIC object. +non_pic_object='sendrecv.o' + diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.o Binary files differnew file mode 100644 index 00000000..4584807f --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sendrecv.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.c new file mode 100644 index 00000000..4ac965d7 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.c @@ -0,0 +1,985 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_strings.h" +#include "apr.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_private.h" + +#if APR_HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#define APR_WANT_STRFUNC +#include "apr_want.h" + +struct apr_ipsubnet_t { + int family; +#if APR_HAVE_IPV6 + apr_uint32_t sub[4]; /* big enough for IPv4 and IPv6 addresses */ + apr_uint32_t mask[4]; +#else + apr_uint32_t sub[1]; + apr_uint32_t mask[1]; +#endif +}; + +#if !defined(NETWARE) && !defined(WIN32) +#ifdef HAVE_SET_H_ERRNO +#define SET_H_ERRNO(newval) set_h_errno(newval) +#else +#define SET_H_ERRNO(newval) h_errno = (newval) +#endif +#else +#define SET_H_ERRNO(newval) +#endif + +#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYNAME_R) +/* This is the maximum size that may be returned from the reentrant + * gethostbyname_r function. If the system tries to use more, it + * should return ERANGE. + */ +#define GETHOSTBYNAME_BUFLEN 512 +#endif + +#ifdef _WIN32_WCE +/* XXX: BS solution. Need an HAVE_GETSERVBYNAME and actually + * do something here, to provide the obvious proto mappings. + */ +static void *getservbyname(const char *name, const char *proto) +{ + return NULL; +} +#endif + +static apr_status_t get_local_addr(apr_socket_t *sock) +{ + sock->local_addr->salen = sizeof(sock->local_addr->sa); + if (getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa, + &sock->local_addr->salen) < 0) { + return apr_get_netos_error(); + } + else { + sock->local_port_unknown = sock->local_interface_unknown = 0; + /* XXX assumes sin_port and sin6_port at same offset */ + sock->local_addr->port = ntohs(sock->local_addr->sa.sin.sin_port); + return APR_SUCCESS; + } +} + +static apr_status_t get_remote_addr(apr_socket_t *sock) +{ + sock->remote_addr->salen = sizeof(sock->remote_addr->sa); + if (getpeername(sock->socketdes, (struct sockaddr *)&sock->remote_addr->sa, + &sock->remote_addr->salen) < 0) { + return apr_get_netos_error(); + } + else { + sock->remote_addr_unknown = 0; + /* XXX assumes sin_port and sin6_port at same offset */ + sock->remote_addr->port = ntohs(sock->remote_addr->sa.sin.sin_port); + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_sockaddr_port_set(apr_sockaddr_t *sockaddr, + apr_port_t port) +{ + sockaddr->port = port; + /* XXX IPv6: assumes sin_port and sin6_port at same offset */ + sockaddr->sa.sin.sin_port = htons(port); + return APR_SUCCESS; +} + +/* XXX assumes IPv4... I don't think this function is needed anyway + * since we have apr_sockaddr_info_get(), but we need to clean up Apache's + * listen.c a bit more first. + */ +APR_DECLARE(apr_status_t) apr_sockaddr_ip_set(apr_sockaddr_t *sockaddr, + const char *addr) +{ + apr_uint32_t ipaddr; + + if (!strcmp(addr, APR_ANYADDR)) { + sockaddr->sa.sin.sin_addr.s_addr = htonl(INADDR_ANY); + return APR_SUCCESS; + } + + ipaddr = inet_addr(addr); + if (ipaddr == (apr_uint32_t)-1) { +#ifdef WIN32 + return WSAEADDRNOTAVAIL; +#else + return errno; +#endif + } + + sockaddr->sa.sin.sin_addr.s_addr = ipaddr; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_sockaddr_port_get(apr_port_t *port, + apr_sockaddr_t *sockaddr) +{ + *port = sockaddr->port; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr, + apr_sockaddr_t *sockaddr) +{ + *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len); + apr_inet_ntop(sockaddr->family, + sockaddr->ipaddr_ptr, + *addr, + sockaddr->addr_str_len); +#if APR_HAVE_IPV6 + if (sockaddr->family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr)) { + /* This is an IPv4-mapped IPv6 address; drop the leading + * part of the address string so we're left with the familiar + * IPv4 format. + */ + *addr += strlen("::ffff:"); + } +#endif + return APR_SUCCESS; +} + +void apr_sockaddr_vars_set(apr_sockaddr_t *addr, int family, apr_port_t port) +{ + addr->family = family; + addr->sa.sin.sin_family = family; + if (port) { + /* XXX IPv6: assumes sin_port and sin6_port at same offset */ + addr->sa.sin.sin_port = htons(port); + addr->port = port; + } + + if (family == APR_INET) { + addr->salen = sizeof(struct sockaddr_in); + addr->addr_str_len = 16; + addr->ipaddr_ptr = &(addr->sa.sin.sin_addr); + addr->ipaddr_len = sizeof(struct in_addr); + } +#if APR_HAVE_IPV6 + else if (family == APR_INET6) { + addr->salen = sizeof(struct sockaddr_in6); + addr->addr_str_len = 46; + addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr); + addr->ipaddr_len = sizeof(struct in6_addr); + } +#endif +} + +APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa, + apr_interface_e which, + apr_socket_t *sock) +{ + if (which == APR_LOCAL) { + if (sock->local_interface_unknown || sock->local_port_unknown) { + apr_status_t rv = get_local_addr(sock); + + if (rv != APR_SUCCESS) { + return rv; + } + } + *sa = sock->local_addr; + } + else if (which == APR_REMOTE) { + if (sock->remote_addr_unknown) { + apr_status_t rv = get_remote_addr(sock); + + if (rv != APR_SUCCESS) { + return rv; + } + } + *sa = sock->remote_addr; + } + else { + *sa = NULL; + return APR_EINVAL; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr, + char **scope_id, + apr_port_t *port, + const char *str, + apr_pool_t *p) +{ + const char *ch, *lastchar; + int big_port; + apr_size_t addrlen; + + *addr = NULL; /* assume not specified */ + *scope_id = NULL; /* assume not specified */ + *port = 0; /* assume not specified */ + + /* First handle the optional port number. That may be all that + * is specified in the string. + */ + ch = lastchar = str + strlen(str) - 1; + while (ch >= str && apr_isdigit(*ch)) { + --ch; + } + + if (ch < str) { /* Entire string is the port. */ + big_port = atoi(str); + if (big_port < 1 || big_port > 65535) { + return APR_EINVAL; + } + *port = big_port; + return APR_SUCCESS; + } + + if (*ch == ':' && ch < lastchar) { /* host and port number specified */ + if (ch == str) { /* string starts with ':' -- bad */ + return APR_EINVAL; + } + big_port = atoi(ch + 1); + if (big_port < 1 || big_port > 65535) { + return APR_EINVAL; + } + *port = big_port; + lastchar = ch - 1; + } + + /* now handle the hostname */ + addrlen = lastchar - str + 1; + +/* XXX we don't really have to require APR_HAVE_IPV6 for this; + * just pass char[] for ipaddr (so we don't depend on struct in6_addr) + * and always define APR_INET6 + */ +#if APR_HAVE_IPV6 + if (*str == '[') { + const char *end_bracket = memchr(str, ']', addrlen); + struct in6_addr ipaddr; + const char *scope_delim; + + if (!end_bracket || end_bracket != lastchar) { + *port = 0; + return APR_EINVAL; + } + + /* handle scope id; this is the only context where it is allowed */ + scope_delim = memchr(str, '%', addrlen); + if (scope_delim) { + if (scope_delim == end_bracket - 1) { /* '%' without scope id */ + *port = 0; + return APR_EINVAL; + } + addrlen = scope_delim - str - 1; + *scope_id = apr_palloc(p, end_bracket - scope_delim); + memcpy(*scope_id, scope_delim + 1, end_bracket - scope_delim - 1); + (*scope_id)[end_bracket - scope_delim - 1] = '\0'; + } + else { + addrlen = addrlen - 2; /* minus 2 for '[' and ']' */ + } + + *addr = apr_palloc(p, addrlen + 1); + memcpy(*addr, + str + 1, + addrlen); + (*addr)[addrlen] = '\0'; + if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) { + *addr = NULL; + *scope_id = NULL; + *port = 0; + return APR_EINVAL; + } + } + else +#endif + { + /* XXX If '%' is not a valid char in a DNS name, we *could* check + * for bogus scope ids first. + */ + *addr = apr_palloc(p, addrlen + 1); + memcpy(*addr, str, addrlen); + (*addr)[addrlen] = '\0'; + } + return APR_SUCCESS; +} + +#if defined(HAVE_GETADDRINFO) + +static apr_status_t call_resolver(apr_sockaddr_t **sa, + const char *hostname, apr_int32_t family, + apr_port_t port, apr_int32_t flags, + apr_pool_t *p) +{ + struct addrinfo hints, *ai, *ai_list; + apr_sockaddr_t *prev_sa; + int error; + char *servname = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + if(hostname == NULL) { +#ifdef AI_PASSIVE + /* If hostname is NULL, assume we are trying to bind to all + * interfaces. */ + hints.ai_flags |= AI_PASSIVE; +#endif + /* getaddrinfo according to RFC 2553 must have either hostname + * or servname non-NULL. + */ +#ifdef _AIX + /* But current AIX getaddrinfo() doesn't like servname = "0"; + * the "1" won't hurt since we use the port parameter to fill + * in the returned socket addresses later + */ + if (!port) { + servname = "1"; + } + else +#endif + servname = apr_itoa(p, port); + } + error = getaddrinfo(hostname, servname, &hints, &ai_list); + if (error) { +#ifndef WIN32 + if (error == EAI_SYSTEM) { + return errno; + } + else +#endif + { + /* issues with representing this with APR's error scheme: + * glibc uses negative values for these numbers, perhaps so + * they don't conflict with h_errno values... Tru64 uses + * positive values which conflict with h_errno values + */ +#if defined(NEGATIVE_EAI) + error = -error; +#endif + return error + APR_OS_START_EAIERR; + } + } + + prev_sa = NULL; + ai = ai_list; + while (ai) { /* while more addresses to report */ + apr_sockaddr_t *new_sa; + + /* Ignore anything bogus: getaddrinfo in some old versions of + * glibc will return AF_UNIX entries for AF_UNSPEC+AI_PASSIVE + * lookups. */ + if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { + ai = ai->ai_next; + continue; + } + + new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t)); + + new_sa->pool = p; + memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen); + apr_sockaddr_vars_set(new_sa, ai->ai_family, port); + + if (!prev_sa) { /* first element in new list */ + if (hostname) { + new_sa->hostname = apr_pstrdup(p, hostname); + } + *sa = new_sa; + } + else { + new_sa->hostname = prev_sa->hostname; + prev_sa->next = new_sa; + } + + prev_sa = new_sa; + ai = ai->ai_next; + } + freeaddrinfo(ai_list); + return APR_SUCCESS; +} + +static apr_status_t find_addresses(apr_sockaddr_t **sa, + const char *hostname, apr_int32_t family, + apr_port_t port, apr_int32_t flags, + apr_pool_t *p) +{ + if (flags & APR_IPV4_ADDR_OK) { + apr_status_t error = call_resolver(sa, hostname, AF_INET, port, flags, p); + +#if APR_HAVE_IPV6 + if (error) { + family = AF_INET6; /* try again */ + } + else +#endif + return error; + } +#if APR_HAVE_IPV6 + else if (flags & APR_IPV6_ADDR_OK) { + apr_status_t error = call_resolver(sa, hostname, AF_INET6, port, flags, p); + + if (error) { + family = AF_INET; /* try again */ + } + else { + return APR_SUCCESS; + } + } +#endif + + return call_resolver(sa, hostname, family, port, flags, p); +} + +#else /* end of HAVE_GETADDRINFO code */ + +static apr_status_t find_addresses(apr_sockaddr_t **sa, + const char *hostname, apr_int32_t family, + apr_port_t port, apr_int32_t flags, + apr_pool_t *p) +{ + struct hostent *hp; + apr_sockaddr_t *prev_sa; + int curaddr; +#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS) +#ifdef GETHOSTBYNAME_R_HOSTENT_DATA + struct hostent_data hd; +#else + /* If you see ERANGE, that means GETHOSBYNAME_BUFLEN needs to be + * bumped. */ + char tmp[GETHOSTBYNAME_BUFLEN]; +#endif + int hosterror; +#endif + struct hostent hs; + struct in_addr ipaddr; + char *addr_list[2]; + const char *orig_hostname = hostname; + + if (hostname == NULL) { + /* if we are given a NULL hostname, assume '0.0.0.0' */ + hostname = "0.0.0.0"; + } + + if (*hostname >= '0' && *hostname <= '9' && + strspn(hostname, "0123456789.") == strlen(hostname)) { + + ipaddr.s_addr = inet_addr(hostname); + addr_list[0] = (char *)&ipaddr; + addr_list[1] = NULL; /* just one IP in list */ + hs.h_addr_list = (char **)addr_list; + hp = &hs; + } + else { +#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS) +#if defined(GETHOSTBYNAME_R_HOSTENT_DATA) + /* AIX, HP/UX, D/UX et alia */ + gethostbyname_r(hostname, &hs, &hd); + hp = &hs; +#else +#if defined(GETHOSTBYNAME_R_GLIBC2) + /* Linux glibc2+ */ + gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, + &hp, &hosterror); +#else + /* Solaris, Irix et alia */ + hp = gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, + &hosterror); +#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */ + if (!hp) { + return (hosterror + APR_OS_START_SYSERR); + } +#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */ +#else + hp = gethostbyname(hostname); +#endif + + if (!hp) { +#ifdef WIN32 + return apr_get_netos_error(); +#else + return (h_errno + APR_OS_START_SYSERR); +#endif + } + } + + prev_sa = NULL; + curaddr = 0; + while (hp->h_addr_list[curaddr]) { + apr_sockaddr_t *new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t)); + + new_sa->pool = p; + new_sa->sa.sin.sin_addr = *(struct in_addr *)hp->h_addr_list[curaddr]; + apr_sockaddr_vars_set(new_sa, AF_INET, port); + + if (!prev_sa) { /* first element in new list */ + if (orig_hostname) { + new_sa->hostname = apr_pstrdup(p, orig_hostname); + } + *sa = new_sa; + } + else { + new_sa->hostname = prev_sa->hostname; + prev_sa->next = new_sa; + } + + prev_sa = new_sa; + ++curaddr; + } + + return APR_SUCCESS; +} + +#endif /* end of !HAVE_GETADDRINFO code */ + +APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa, + const char *hostname, + apr_int32_t family, apr_port_t port, + apr_int32_t flags, apr_pool_t *p) +{ + apr_int32_t masked; + *sa = NULL; + + if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) { + if (!hostname || + family != AF_UNSPEC || + masked == (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK)) { + return APR_EINVAL; + } +#if !APR_HAVE_IPV6 + if (flags & APR_IPV6_ADDR_OK) { + return APR_ENOTIMPL; + } +#endif + } +#if !APR_HAVE_IPV6 + /* What may happen is that APR is not IPv6-enabled, but we're still + * going to call getaddrinfo(), so we have to tell the OS we only + * want IPv4 addresses back since we won't know what to do with + * IPv6 addresses. + */ + if (family == APR_UNSPEC) { + family = APR_INET; + } +#endif + + return find_addresses(sa, hostname, family, port, flags, p); +} + +APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname, + apr_sockaddr_t *sockaddr, + apr_int32_t flags) +{ +#if defined(HAVE_GETNAMEINFO) + int rc; +#if defined(NI_MAXHOST) + char tmphostname[NI_MAXHOST]; +#else + char tmphostname[256]; +#endif + + /* don't know if it is portable for getnameinfo() to set h_errno; + * clear it then see if it was set */ + SET_H_ERRNO(0); + + /* default flags are NI_NAMREQD; otherwise, getnameinfo() will return + * a numeric address string if it fails to resolve the host name; + * that is *not* what we want here + * + * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling + * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc). + */ +#if APR_HAVE_IPV6 + if (sockaddr->family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) { + struct sockaddr_in tmpsa; + tmpsa.sin_family = AF_INET; + tmpsa.sin_port = 0; + tmpsa.sin_addr.s_addr = ((apr_uint32_t *)sockaddr->ipaddr_ptr)[3]; +#ifdef SIN6_LEN + tmpsa.sin_len = sizeof(tmpsa); +#endif + + rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa), + tmphostname, sizeof(tmphostname), NULL, 0, + flags != 0 ? flags : NI_NAMEREQD); + } + else +#endif + rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen, + tmphostname, sizeof(tmphostname), NULL, 0, + flags != 0 ? flags : NI_NAMEREQD); + if (rc != 0) { + *hostname = NULL; + +#ifndef WIN32 + /* something went wrong. Look at the EAI_ error code */ + if (rc == EAI_SYSTEM) { + /* EAI_SYSTEM System error returned in errno. */ + /* IMHO, Implementations that set h_errno a simply broken. */ + if (h_errno) { /* for broken implementations which set h_errno */ + return h_errno + APR_OS_START_SYSERR; + } + else { /* "normal" case */ + return errno + APR_OS_START_SYSERR; + } + } + else +#endif + { +#if defined(NEGATIVE_EAI) + if (rc < 0) rc = -rc; +#endif + return rc + APR_OS_START_EAIERR; /* return the EAI_ error */ + } + } + *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, + tmphostname); + return APR_SUCCESS; +#else +#if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS) +#ifdef GETHOSTBYNAME_R_HOSTENT_DATA + struct hostent_data hd; +#else + char tmp[GETHOSTBYNAME_BUFLEN]; +#endif + int hosterror; + struct hostent hs, *hptr; + +#if defined(GETHOSTBYNAME_R_HOSTENT_DATA) + /* AIX, HP/UX, D/UX et alia */ + gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET, &hs, &hd); + hptr = &hs; +#else +#if defined(GETHOSTBYNAME_R_GLIBC2) + /* Linux glibc2+ */ + gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET, + &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror); +#else + /* Solaris, Irix et alia */ + hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET, + &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror); +#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */ + if (!hptr) { + *hostname = NULL; + return hosterror + APR_OS_START_SYSERR; + } +#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */ +#else + struct hostent *hptr; + hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET); +#endif + + if (hptr) { + *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, hptr->h_name); + return APR_SUCCESS; + } + *hostname = NULL; +#if defined(WIN32) + return apr_get_netos_error(); +#elif defined(OS2) + return h_errno; +#else + return h_errno + APR_OS_START_SYSERR; +#endif +#endif +} + +APR_DECLARE(apr_status_t) apr_getservbyname(apr_sockaddr_t *sockaddr, + const char *servname) +{ + struct servent *se; + + if (servname == NULL) + return APR_EINVAL; + + if ((se = getservbyname(servname, NULL)) != NULL){ + sockaddr->port = htons(se->s_port); + sockaddr->servname = apr_pstrdup(sockaddr->pool, servname); + sockaddr->sa.sin.sin_port = se->s_port; + return APR_SUCCESS; + } + return APR_ENOENT; +} + +#define V4MAPPED_EQUAL(a,b) \ +((a)->sa.sin.sin_family == AF_INET && \ + (b)->sa.sin.sin_family == AF_INET6 && \ + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)(b)->ipaddr_ptr) && \ + !memcmp((a)->ipaddr_ptr, \ + &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12], \ + (a)->ipaddr_len)) + +APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1, + const apr_sockaddr_t *addr2) +{ + if (addr1->ipaddr_len == addr2->ipaddr_len && + !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)) { + return 1; + } +#if APR_HAVE_IPV6 + if (V4MAPPED_EQUAL(addr1, addr2)) { + return 1; + } + if (V4MAPPED_EQUAL(addr2, addr1)) { + return 1; + } +#endif + return 0; /* not equal */ +} + +static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network) +{ + /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */ + int shift; + char *s, *t; + int octet; + char buf[sizeof "255.255.255.255"]; + + if (strlen(network) < sizeof buf) { + strcpy(buf, network); + } + else { + return APR_EBADIP; + } + + /* parse components */ + s = buf; + ipsub->sub[0] = 0; + ipsub->mask[0] = 0; + shift = 24; + while (*s) { + t = s; + if (!apr_isdigit(*t)) { + return APR_EBADIP; + } + while (apr_isdigit(*t)) { + ++t; + } + if (*t == '.') { + *t++ = 0; + } + else if (*t) { + return APR_EBADIP; + } + if (shift < 0) { + return APR_EBADIP; + } + octet = atoi(s); + if (octet < 0 || octet > 255) { + return APR_EBADIP; + } + ipsub->sub[0] |= octet << shift; + ipsub->mask[0] |= 0xFFUL << shift; + s = t; + shift -= 8; + } + ipsub->sub[0] = ntohl(ipsub->sub[0]); + ipsub->mask[0] = ntohl(ipsub->mask[0]); + ipsub->family = AF_INET; + return APR_SUCCESS; +} + +/* return values: + * APR_EINVAL not an IP address; caller should see if it is something else + * APR_BADIP IP address portion is is not valid + * APR_BADMASK mask portion is not valid + */ + +static apr_status_t parse_ip(apr_ipsubnet_t *ipsub, const char *ipstr, int network_allowed) +{ + /* supported flavors of IP: + * + * . IPv6 numeric address string (e.g., "fe80::1") + * + * IMPORTANT: Don't store IPv4-mapped IPv6 address as an IPv6 address. + * + * . IPv4 numeric address string (e.g., "127.0.0.1") + * + * . IPv4 network string (e.g., "9.67") + * + * IMPORTANT: This network form is only allowed if network_allowed is on. + */ + int rc; + +#if APR_HAVE_IPV6 + rc = apr_inet_pton(AF_INET6, ipstr, ipsub->sub); + if (rc == 1) { + if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ipsub->sub)) { + /* apr_ipsubnet_test() assumes that we don't create IPv4-mapped IPv6 + * addresses; this of course forces the user to specify IPv4 addresses + * in a.b.c.d style instead of ::ffff:a.b.c.d style. + */ + return APR_EBADIP; + } + ipsub->family = AF_INET6; + } + else +#endif + { + rc = apr_inet_pton(AF_INET, ipstr, ipsub->sub); + if (rc == 1) { + ipsub->family = AF_INET; + } + } + if (rc != 1) { + if (network_allowed) { + return parse_network(ipsub, ipstr); + } + else { + return APR_EBADIP; + } + } + return APR_SUCCESS; +} + +static int looks_like_ip(const char *ipstr) +{ + if (strchr(ipstr, ':')) { + /* definitely not a hostname; assume it is intended to be an IPv6 address */ + return 1; + } + + /* simple IPv4 address string check */ + while ((*ipstr == '.') || apr_isdigit(*ipstr)) + ipstr++; + return (*ipstr == '\0'); +} + +static void fix_subnet(apr_ipsubnet_t *ipsub) +{ + /* in case caller specified more bits in network address than are + * valid according to the mask, turn off the extra bits + */ + int i; + + for (i = 0; i < sizeof ipsub->mask / sizeof(apr_int32_t); i++) { + ipsub->sub[i] &= ipsub->mask[i]; + } +} + +/* be sure not to store any IPv4 address as a v4-mapped IPv6 address */ +APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, const char *ipstr, + const char *mask_or_numbits, apr_pool_t *p) +{ + apr_status_t rv; + char *endptr; + long bits, maxbits = 32; + + /* filter out stuff which doesn't look remotely like an IP address; this helps + * callers like mod_access which have a syntax allowing hostname or IP address; + * APR_EINVAL tells the caller that it was probably not intended to be an IP + * address + */ + if (!looks_like_ip(ipstr)) { + return APR_EINVAL; + } + + *ipsub = apr_pcalloc(p, sizeof(apr_ipsubnet_t)); + + /* assume ipstr is an individual IP address, not a subnet */ + memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask); + + rv = parse_ip(*ipsub, ipstr, mask_or_numbits == NULL); + if (rv != APR_SUCCESS) { + return rv; + } + + if (mask_or_numbits) { +#if APR_HAVE_IPV6 + if ((*ipsub)->family == AF_INET6) { + maxbits = 128; + } +#endif + bits = strtol(mask_or_numbits, &endptr, 10); + if (*endptr == '\0' && bits > 0 && bits <= maxbits) { + /* valid num-bits string; fill in mask appropriately */ + int cur_entry = 0; + apr_int32_t cur_bit_value; + + memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask); + while (bits > 32) { + (*ipsub)->mask[cur_entry] = 0xFFFFFFFF; /* all 32 bits */ + bits -= 32; + ++cur_entry; + } + cur_bit_value = 0x80000000; + while (bits) { + (*ipsub)->mask[cur_entry] |= cur_bit_value; + --bits; + cur_bit_value /= 2; + } + (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]); + } + else if (apr_inet_pton(AF_INET, mask_or_numbits, (*ipsub)->mask) == 1 && + (*ipsub)->family == AF_INET) { + /* valid IPv4 netmask */ + } + else { + return APR_EBADMASK; + } + } + + fix_subnet(*ipsub); + + return APR_SUCCESS; +} + +APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa) +{ +#if APR_HAVE_IPV6 + /* XXX This line will segv on Win32 build with APR_HAVE_IPV6, + * but without the IPV6 drivers installed. + */ + if (sa->sa.sin.sin_family == AF_INET) { + if (ipsub->family == AF_INET && + ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0])) { + return 1; + } + } + else if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sa->ipaddr_ptr)) { + if (ipsub->family == AF_INET && + (((apr_uint32_t *)sa->ipaddr_ptr)[3] & ipsub->mask[0]) == ipsub->sub[0]) { + return 1; + } + } + else { + apr_uint32_t *addr = (apr_uint32_t *)sa->ipaddr_ptr; + + if ((addr[0] & ipsub->mask[0]) == ipsub->sub[0] && + (addr[1] & ipsub->mask[1]) == ipsub->sub[1] && + (addr[2] & ipsub->mask[2]) == ipsub->sub[2] && + (addr[3] & ipsub->mask[3]) == ipsub->sub[3]) { + return 1; + } + } +#else + if ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0]) { + return 1; + } +#endif /* APR_HAVE_IPV6 */ + return 0; /* no match */ +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.lo b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.lo new file mode 100644 index 00000000..e601fa5e --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.lo @@ -0,0 +1,12 @@ +# sockaddr.lo - a libtool object file +# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/sockaddr.o' + +# Name of the non-PIC object. +non_pic_object='sockaddr.o' + diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.o Binary files differnew file mode 100644 index 00000000..d4bd43ee --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockaddr.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.c new file mode 100644 index 00000000..6510388e --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.c @@ -0,0 +1,422 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_strings.h" +#include "apr_support.h" +#include "apr_portable.h" +#include "apr_arch_inherit.h" + +#if defined(BEOS) && !defined(BEOS_BONE) +#define close closesocket +#endif + +static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ + +static apr_status_t socket_cleanup(void *sock) +{ + apr_socket_t *thesocket = sock; + + if (close(thesocket->socketdes) == 0) { + thesocket->socketdes = -1; + return APR_SUCCESS; + } + else { + return errno; + } +} + +static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) +{ + sock->type = type; + sock->protocol = protocol; + apr_sockaddr_vars_set(sock->local_addr, family, 0); + apr_sockaddr_vars_set(sock->remote_addr, family, 0); + sock->netmask = 0; +#if defined(BEOS) && !defined(BEOS_BONE) + /* BeOS pre-BONE has TCP_NODELAY on by default and it can't be + * switched off! + */ + sock->netmask |= APR_TCP_NODELAY; +#endif +} + +static void alloc_socket(apr_socket_t **new, apr_pool_t *p) +{ + *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); + (*new)->cntxt = p; + (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->local_addr->pool = p; + (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->remote_addr->pool = p; +} + +apr_status_t apr_socket_protocol_get(apr_socket_t *sock, int *protocol) +{ + *protocol = sock->protocol; + return APR_SUCCESS; +} + +apr_status_t apr_socket_create_ex(apr_socket_t **new, int ofamily, int type, + int protocol, apr_pool_t *cont) +{ + int family = ofamily; + + if (family == APR_UNSPEC) { +#if APR_HAVE_IPV6 + family = APR_INET6; +#else + family = APR_INET; +#endif + } + + alloc_socket(new, cont); + + (*new)->socketdes = socket(family, type, protocol); + +#if APR_HAVE_IPV6 + if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC) { + family = APR_INET; + (*new)->socketdes = socket(family, type, protocol); + } +#endif + + if ((*new)->socketdes < 0) { + return errno; + } + set_socket_vars(*new, family, type, protocol); + + (*new)->timeout = -1; + (*new)->inherit = 0; + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), socket_cleanup, + socket_cleanup); + return APR_SUCCESS; +} + +apr_status_t apr_socket_create(apr_socket_t **new, int family, int type, + apr_pool_t *cont) +{ + return apr_socket_create_ex(new, family, type, 0, cont); +} + +apr_status_t apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + return (shutdown(thesocket->socketdes, how) == -1) ? errno : APR_SUCCESS; +} + +apr_status_t apr_socket_close(apr_socket_t *thesocket) +{ + return apr_pool_cleanup_run(thesocket->cntxt, thesocket, socket_cleanup); +} + +apr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + if (bind(sock->socketdes, + (struct sockaddr *)&sa->sa, sa->salen) == -1) { + return errno; + } + else { + sock->local_addr = sa; + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */ + sock->local_port_unknown = 1; /* kernel got us an ephemeral port */ + } + return APR_SUCCESS; + } +} + +apr_status_t apr_socket_listen(apr_socket_t *sock, apr_int32_t backlog) +{ + if (listen(sock->socketdes, backlog) == -1) + return errno; + else + return APR_SUCCESS; +} + +apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock, + apr_pool_t *connection_context) +{ + alloc_socket(new, connection_context); + set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, sock->protocol); + +#ifndef HAVE_POLL + (*new)->connected = 1; +#endif + (*new)->timeout = -1; + + (*new)->socketdes = accept(sock->socketdes, + (struct sockaddr *)&(*new)->remote_addr->sa, + &(*new)->remote_addr->salen); + + if ((*new)->socketdes < 0) { + return errno; + } +#ifdef TPF + if ((*new)->socketdes == 0) { + /* 0 is an invalid socket for TPF */ + return APR_EINTR; + } +#endif + + *(*new)->local_addr = *sock->local_addr; + + /* The above assignment just overwrote the pool entry. Setting the local_addr + pool for the accepted socket back to what it should be. Otherwise all + allocations for this socket will come from a server pool that is not + freed until the process goes down.*/ + (*new)->local_addr->pool = connection_context; + + /* fix up any pointers which are no longer valid */ + if (sock->local_addr->sa.sin.sin_family == AF_INET) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; + } +#if APR_HAVE_IPV6 + else if (sock->local_addr->sa.sin.sin_family == AF_INET6) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; + } +#endif + (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); + if (sock->local_port_unknown) { + /* not likely for a listening socket, but theoretically possible :) */ + (*new)->local_port_unknown = 1; + } + +#if APR_TCP_NODELAY_INHERITED + if (apr_is_option_set(sock->netmask, APR_TCP_NODELAY) == 1) { + apr_set_option(&(*new)->netmask, APR_TCP_NODELAY, 1); + } +#endif /* TCP_NODELAY_INHERITED */ +#if APR_O_NONBLOCK_INHERITED + if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) == 1) { + apr_set_option(&(*new)->netmask, APR_SO_NONBLOCK, 1); + } +#endif /* APR_O_NONBLOCK_INHERITED */ + + if (sock->local_interface_unknown || + !memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* If the interface address inside the listening socket's local_addr wasn't + * up-to-date, we don't know local interface of the connected socket either. + * + * If the listening socket was not bound to a specific interface, we + * don't know the local_addr of the connected socket. + */ + (*new)->local_interface_unknown = 1; + } + + (*new)->inherit = 0; + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), socket_cleanup, + socket_cleanup); + return APR_SUCCESS; +} + +apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + int rc; + + do { + rc = connect(sock->socketdes, + (const struct sockaddr *)&sa->sa.sin, + sa->salen); + } while (rc == -1 && errno == EINTR); + + /* we can see EINPROGRESS the first time connect is called on a non-blocking + * socket; if called again, we can see EALREADY + */ + if (rc == -1 && (errno == EINPROGRESS || errno == EALREADY) && + apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) { + rc = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (rc != APR_SUCCESS) { + return rc; + } + +#ifdef SO_ERROR + { + int error; + apr_socklen_t len = sizeof(error); + if ((rc = getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, + (char *)&error, &len)) < 0) { + return errno; + } + if (error) { + return error; + } + } +#endif /* SO_ERROR */ + } + + if (rc == -1 && errno != EISCONN) { + return errno; + } + + sock->remote_addr = sa; + if (sock->local_addr->port == 0) { + /* connect() got us an ephemeral port */ + sock->local_port_unknown = 1; + } + if (!memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* not bound to specific local interface; connect() had to assign + * one for the socket + */ + sock->local_interface_unknown = 1; + } +#ifndef HAVE_POLL + sock->connected=1; +#endif + return APR_SUCCESS; +} + +apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock) +{ + sock_userdata_t *cur = sock->userdata; + + *data = NULL; + + while (cur) { + if (!strcmp(cur->key, key)) { + *data = cur->data; + break; + } + cur = cur->next; + } + + return APR_SUCCESS; +} + +apr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, const char *key, + apr_status_t (*cleanup) (void *)) +{ + sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t)); + + new->key = apr_pstrdup(sock->cntxt, key); + new->data = data; + new->next = sock->userdata; + sock->userdata = new; + + if (cleanup) { + apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup); + } + + return APR_SUCCESS; +} + +apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock) +{ + *thesock = sock->socketdes; + return APR_SUCCESS; +} + +apr_status_t apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont) +{ + alloc_socket(apr_sock, cont); +#ifdef APR_ENABLE_FOR_1_0 /* no protocol field yet */ + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); +#else + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, 0); +#endif + (*apr_sock)->timeout = -1; + (*apr_sock)->socketdes = *os_sock_info->os_sock; + if (os_sock_info->local) { + memcpy(&(*apr_sock)->local_addr->sa.sin, + os_sock_info->local, + (*apr_sock)->local_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; + } + if (os_sock_info->remote) { +#ifndef HAVE_POLL + (*apr_sock)->connected = 1; +#endif + memcpy(&(*apr_sock)->remote_addr->sa.sin, + os_sock_info->remote, + (*apr_sock)->remote_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->remote_addr_unknown = 1; + } + + (*apr_sock)->inherit = 0; + apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock), + socket_cleanup, socket_cleanup); + return APR_SUCCESS; +} + +apr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, + apr_pool_t *cont) +{ + /* XXX Bogus assumption that *sock points at anything legit */ + if ((*sock) == NULL) { + alloc_socket(sock, cont); + /* XXX IPv6 figure out the family here! */ + /* XXX figure out the actual socket type here */ + /* *or* just decide that apr_os_sock_put() has to be told the family and type */ + set_socket_vars(*sock, APR_INET, SOCK_STREAM, 0); + (*sock)->timeout = -1; + } + (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; + (*sock)->remote_addr_unknown = 1; + (*sock)->socketdes = *thesock; + return APR_SUCCESS; +} + +APR_IMPLEMENT_INHERIT_SET(socket, inherit, cntxt, socket_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, cntxt, socket_cleanup) + +/* deprecated */ +apr_status_t apr_shutdown(apr_socket_t *thesocket, apr_shutdown_how_e how) +{ + return apr_socket_shutdown(thesocket, how); +} + +/* deprecated */ +apr_status_t apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + return apr_socket_bind(sock, sa); +} + +/* deprecated */ +apr_status_t apr_listen(apr_socket_t *sock, apr_int32_t backlog) +{ + return apr_socket_listen(sock, backlog); +} + +/* deprecated */ +apr_status_t apr_accept(apr_socket_t **new, apr_socket_t *sock, + apr_pool_t *connection_context) +{ + return apr_socket_accept(new, sock, connection_context); +} + +/* deprecated */ +apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + return apr_socket_connect(sock, sa); +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.lo b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.lo new file mode 100644 index 00000000..02c9a22e --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.lo @@ -0,0 +1,12 @@ +# sockets.lo - a libtool object file +# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/sockets.o' + +# Name of the non-PIC object. +non_pic_object='sockets.o' + diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.o Binary files differnew file mode 100644 index 00000000..c4cc3fb7 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockets.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.c new file mode 100644 index 00000000..039fda08 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.c @@ -0,0 +1,393 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_strings.h" + + +static apr_status_t soblock(int sd) +{ +/* BeOS uses setsockopt at present for non blocking... */ +#ifndef BEOS + int fd_flags; + + fd_flags = fcntl(sd, F_GETFL, 0); +#if defined(O_NONBLOCK) + fd_flags &= ~O_NONBLOCK; +#elif defined(O_NDELAY) + fd_flags &= ~O_NDELAY; +#elif defined(FNDELAY) + fd_flags &= ~FNDELAY; +#else +#error Please teach APR how to make sockets blocking on your platform. +#endif + if (fcntl(sd, F_SETFL, fd_flags) == -1) { + return errno; + } +#else + int on = 0; + if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0) + return errno; +#endif /* BEOS */ + return APR_SUCCESS; +} + +static apr_status_t sononblock(int sd) +{ +#ifndef BEOS + int fd_flags; + + fd_flags = fcntl(sd, F_GETFL, 0); +#if defined(O_NONBLOCK) + fd_flags |= O_NONBLOCK; +#elif defined(O_NDELAY) + fd_flags |= O_NDELAY; +#elif defined(FNDELAY) + fd_flags |= FNDELAY; +#else +#error Please teach APR how to make sockets non-blocking on your platform. +#endif + if (fcntl(sd, F_SETFL, fd_flags) == -1) { + return errno; + } +#else + int on = 1; + if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0) + return errno; +#endif /* BEOS */ + return APR_SUCCESS; +} + + +apr_status_t apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t) +{ + apr_status_t stat; + + /* If our timeout is positive or zero and our last timeout was + * negative, then we need to ensure that we are non-blocking. + * Conversely, if our timeout is negative and we had a positive + * or zero timeout, we must make sure our socket is blocking. + * We want to avoid calling fcntl more than necessary on the socket, + */ + if (t >= 0 && sock->timeout < 0) { + if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) != 1) { + if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) { + return stat; + } + apr_set_option(&sock->netmask, APR_SO_NONBLOCK, 1); + } + } + else if (t < 0 && sock->timeout >= 0) { + if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) != 0) { + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) { + return stat; + } + apr_set_option(&sock->netmask, APR_SO_NONBLOCK, 0); + } + } + /* must disable the incomplete read support if we disable + * a timeout + */ + if (t <= 0) { + sock->netmask &= ~APR_INCOMPLETE_READ; + } + sock->timeout = t; + apr_set_option(&sock->netmask, APR_SO_TIMEOUT, t > 0); + return APR_SUCCESS; +} + + +apr_status_t apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + int one; + apr_status_t rv; + + if (on) + one = 1; + else + one = 0; + switch(opt) { + case APR_SO_KEEPALIVE: +#ifdef SO_KEEPALIVE + if (on != apr_is_option_set(sock->netmask, APR_SO_KEEPALIVE)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask,APR_SO_KEEPALIVE, on); + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_SO_DEBUG: + if (on != apr_is_option_set(sock->netmask, APR_SO_DEBUG)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_SO_DEBUG, on); + } + break; + case APR_SO_REUSEADDR: + if (on != apr_is_option_set(sock->netmask, APR_SO_REUSEADDR)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_SO_REUSEADDR, on); + } + break; + case APR_SO_SNDBUF: +#ifdef SO_SNDBUF + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void *)&on, sizeof(int)) == -1) { + return errno; + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_SO_RCVBUF: +#ifdef SO_RCVBUF + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF, (void *)&on, sizeof(int)) == -1) { + return errno; + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_SO_NONBLOCK: + if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) != on) { + if (on) { + if ((rv = sononblock(sock->socketdes)) != APR_SUCCESS) + return rv; + } + else { + if ((rv = soblock(sock->socketdes)) != APR_SUCCESS) + return rv; + } + apr_set_option(&sock->netmask, APR_SO_NONBLOCK, on); + } + break; + case APR_SO_LINGER: +#ifdef SO_LINGER + if (apr_is_option_set(sock->netmask, APR_SO_LINGER) != on) { + struct linger li; + li.l_onoff = on; + li.l_linger = APR_MAX_SECS_TO_LINGER; + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_SO_LINGER, on); + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_SO_TIMEOUT: + /* XXX: To be deprecated */ + return apr_socket_timeout_set(sock, on); + break; + case APR_TCP_NODELAY: +#if defined(TCP_NODELAY) + if (apr_is_option_set(sock->netmask, APR_TCP_NODELAY) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_NODELAY; + +#if APR_HAVE_SCTP + if (sock->protocol == IPPROTO_SCTP) { + optlevel = IPPROTO_SCTP; + optname = SCTP_NODELAY; + } +#endif + if (setsockopt(sock->socketdes, optlevel, optname, (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_TCP_NODELAY, on); + } +#else + /* BeOS pre-BONE has TCP_NODELAY set by default. + * As it can't be turned off we might as well check if they're asking + * for it to be turned on! + */ +#ifdef BEOS + if (on == 1) + return APR_SUCCESS; + else +#endif + return APR_ENOTIMPL; +#endif + break; + case APR_TCP_NOPUSH: +#if APR_TCP_NOPUSH_FLAG + if (apr_is_option_set(sock->netmask, APR_TCP_NOPUSH) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_NODELAY; + +#if APR_HAVE_SCTP + if (sock->protocol == IPPROTO_SCTP) { + optlevel = IPPROTO_SCTP; + optname = SCTP_NODELAY; + } +#endif + /* OK we're going to change some settings here... */ + /* TCP_NODELAY is mutually exclusive, so do we have it set? */ + if (apr_is_option_set(sock->netmask, APR_TCP_NODELAY) == 1 && on) { + /* If we want to set NOPUSH then if we have the TCP_NODELAY + * flag set we need to switch it off... + */ + int tmpflag = 0; + if (setsockopt(sock->socketdes, optlevel, optname, + (void*)&tmpflag, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_RESET_NODELAY, 1); + apr_set_option(&sock->netmask, APR_TCP_NODELAY, 0); + } else if (on) { + apr_set_option(&sock->netmask, APR_RESET_NODELAY, 0); + } + /* OK, now we can just set the TCP_NOPUSH flag accordingly...*/ + if (setsockopt(sock->socketdes, IPPROTO_TCP, APR_TCP_NOPUSH_FLAG, + (void*)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_TCP_NOPUSH, on); + if (!on && apr_is_option_set(sock->netmask, APR_RESET_NODELAY)) { + int tmpflag = 1; + if (setsockopt(sock->socketdes, optlevel, optname, + (void*)&tmpflag, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_RESET_NODELAY,0); + apr_set_option(&sock->netmask, APR_TCP_NODELAY, 1); + } + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_INCOMPLETE_READ: + apr_set_option(&sock->netmask, APR_INCOMPLETE_READ, on); + break; + case APR_IPV6_V6ONLY: +#if APR_HAVE_IPV6 && defined(IPV6_V6ONLY) + /* we don't know the initial setting of this option, + * so don't check sock->netmask since that optimization + * won't work + */ + if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(&sock->netmask, APR_IPV6_V6ONLY, on); +#else + return APR_ENOTIMPL; +#endif + break; + default: + return APR_EINVAL; + } + + return APR_SUCCESS; +} + + +apr_status_t apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t) +{ + *t = sock->timeout; + return APR_SUCCESS; +} + + +apr_status_t apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + switch(opt) { + case APR_SO_TIMEOUT: + /* XXX: To be deprecated */ + *on = (apr_int32_t)sock->timeout; + break; + default: + *on = apr_is_option_set(sock->netmask, opt); + } + return APR_SUCCESS; +} + + +apr_status_t apr_socket_atmark(apr_socket_t *sock, int *atmark) +{ +/* In 1.0 we rely on compile failure to assure all platforms grabbed + * the correct header file support for SIOCATMARK, but we don't want + * to fail the build of 0.9. Keep things good for the released branch. + */ +#ifdef SIOCATMARK + int oobmark; + + if (ioctl(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0) + return apr_get_netos_error(); + + *atmark = (oobmark != 0); + + return APR_SUCCESS; +#else + return APR_ENOTIMPL; +#endif +} + + +/* deprecated */ +apr_status_t apr_setsocketopt(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + return apr_socket_opt_set(sock, opt, on); +} + +apr_status_t apr_getsocketopt(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + return apr_socket_opt_get(sock, opt, on); +} + + +apr_status_t apr_gethostname(char *buf, apr_int32_t len, apr_pool_t *cont) +{ + if (gethostname(buf, len) == -1) { + buf[0] = '\0'; + return errno; + } + else if (!memchr(buf, '\0', len)) { /* buffer too small */ + /* note... most platforms just truncate in this condition + * linux+glibc return an error + */ + buf[0] = '\0'; + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} + +#if APR_HAS_SO_ACCEPTFILTER +apr_status_t apr_socket_accept_filter(apr_socket_t *sock, char *name, + char *args) +{ + struct accept_filter_arg af; + strncpy(af.af_name, name, 16); + strncpy(af.af_arg, args, 256 - 16); + + if ((setsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER, + &af, sizeof(af))) < 0) { + return errno; + } + return APR_SUCCESS; +} +#endif diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.lo b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.lo new file mode 100644 index 00000000..e61510cc --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.lo @@ -0,0 +1,12 @@ +# sockopt.lo - a libtool object file +# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/sockopt.o' + +# Name of the non-PIC object. +non_pic_object='sockopt.o' + diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.o b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.o Binary files differnew file mode 100644 index 00000000..cc6db787 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/unix/sockopt.o diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sendrecv.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sendrecv.c new file mode 100644 index 00000000..99470c82 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sendrecv.c @@ -0,0 +1,460 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_network_io.h" +#include "apr_lib.h" +#include "apr_arch_file_io.h" +#if APR_HAVE_TIME_H +#include <time.h> +#endif + +/* MAX_SEGMENT_SIZE is the maximum amount of data that will be sent to a client + * in one call of TransmitFile. This number must be small enough to give the + * slowest client time to receive the data before the socket timeout triggers. + * The same problem can exist with apr_socket_send(). In that case, we rely on + * the application to adjust socket timeouts and max send segment + * sizes appropriately. + * For example, Apache will in most cases call apr_socket_send() with less + * than 8193 bytes. + */ +#define MAX_SEGMENT_SIZE 65536 +#define WSABUF_ON_STACK 50 + +APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + WSABUF wsaData; + int lasterror; + DWORD dwBytes = 0; + + wsaData.len = *len; + wsaData.buf = (char*) buf; + +#ifndef _WIN32_WCE + rv = WSASend(sock->socketdes, &wsaData, 1, &dwBytes, 0, NULL, NULL); +#else + rv = send(sock->socketdes, wsaData.buf, wsaData.len, 0); + dwBytes = rv; +#endif + if (rv == SOCKET_ERROR) { + lasterror = apr_get_netos_error(); + *len = 0; + return lasterror; + } + + *len = dwBytes; + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + WSABUF wsaData; + int lasterror; + DWORD dwBytes = 0; + DWORD flags = 0; + + wsaData.len = *len; + wsaData.buf = (char*) buf; + +#ifndef _WIN32_WCE + rv = WSARecv(sock->socketdes, &wsaData, 1, &dwBytes, &flags, NULL, NULL); +#else + rv = recv(sock->socketdes, wsaData.buf, wsaData.len, 0); + dwBytes = rv; +#endif + if (rv == SOCKET_ERROR) { + lasterror = apr_get_netos_error(); + *len = 0; + return lasterror; + } + + *len = dwBytes; + return dwBytes == 0 ? APR_EOF : APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *nbytes) +{ + apr_status_t rc = APR_SUCCESS; + apr_ssize_t rv; + int i; + DWORD dwBytes = 0; + WSABUF *pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec)) + : malloc(sizeof(WSABUF) * (nvec)); + + if (!pWsaBuf) + return APR_ENOMEM; + + for (i = 0; i < nvec; i++) { + pWsaBuf[i].buf = vec[i].iov_base; + pWsaBuf[i].len = vec[i].iov_len; + } +#ifndef _WIN32_WCE + rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0, NULL, NULL); + if (rv == SOCKET_ERROR) { + rc = apr_get_netos_error(); + } +#else + for (i = 0; i < nvec; i++) { + rv = send(sock->socketdes, pWsaBuf[i].buf, pWsaBuf[i].len, 0); + if (rv == SOCKET_ERROR) { + rc = apr_get_netos_error(); + break; + } + dwBytes += rv; + } +#endif + if (nvec > WSABUF_ON_STACK) + free(pWsaBuf); + + *nbytes = dwBytes; + return rc; +} + + +APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + if (rv == SOCKET_ERROR) { + *len = 0; + return apr_get_netos_error(); + } + + *len = rv; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, + char *buf, apr_size_t *len) +{ + apr_ssize_t rv; + + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + if (rv == SOCKET_ERROR) { + (*len) = 0; + return apr_get_netos_error(); + } + (*len) = rv; + if (rv == 0 && sock->type == SOCK_STREAM) + return APR_EOF; + + return APR_SUCCESS; +} + + +static apr_status_t collapse_iovec(char **off, apr_size_t *len, + struct iovec *iovec, int numvec, + char *buf, apr_size_t buflen) +{ + if (numvec == 1) { + *off = iovec[0].iov_base; + *len = iovec[0].iov_len; + } + else { + int i; + for (i = 0; i < numvec; i++) { + *len += iovec[i].iov_len; + } + + if (*len > buflen) { + *len = 0; + return APR_INCOMPLETE; + } + + *off = buf; + + for (i = 0; i < numvec; i++) { + memcpy(buf, iovec[i].iov_base, iovec[i].iov_len); + buf += iovec[i].iov_len; + } + } + return APR_SUCCESS; +} + + +#if APR_HAS_SENDFILE +/* + * apr_status_t apr_socket_sendfile(apr_socket_t *, apr_file_t *, apr_hdtr_t *, + * apr_off_t *, apr_size_t *, apr_int32_t flags) + * Send a file from an open file descriptor to a socket, along with + * optional headers and trailers + * arg 1) The socket to which we're writing + * arg 2) The open file from which to read + * arg 3) A structure containing the headers and trailers to send + * arg 4) Offset into the file where we should begin writing + * arg 5) Number of bytes to send out of the file + * arg 6) APR flags that are mapped to OS specific flags + */ +APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, + apr_file_t *file, + apr_hdtr_t *hdtr, + apr_off_t *offset, + apr_size_t *len, + apr_int32_t flags) +{ + apr_status_t status = APR_SUCCESS; + apr_ssize_t rv; + apr_off_t curoff = *offset; + DWORD dwFlags = 0; + DWORD nbytes; + TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL; + int ptr = 0; + int bytes_to_send; /* Bytes to send out of the file (not including headers) */ + int disconnected = 0; + int sendv_trailers = 0; + char hdtrbuf[4096]; + + if (apr_os_level < APR_WIN_NT) { + return APR_ENOTIMPL; + } + + /* Use len to keep track of number of total bytes sent (including headers) */ + bytes_to_send = *len; + *len = 0; + + /* Handle the goofy case of sending headers/trailers and a zero byte file */ + if (!bytes_to_send && hdtr) { + if (hdtr->numheaders) { + rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, + &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + } + if (hdtr->numtrailers) { + rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, + &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + } + return APR_SUCCESS; + } + + memset(&tfb, '\0', sizeof (tfb)); + /* Collapse the headers into a single buffer */ + if (hdtr && hdtr->numheaders) { + ptfb = &tfb; + nbytes = 0; + rv = collapse_iovec((char **)&ptfb->Head, &ptfb->HeadLength, + hdtr->headers, hdtr->numheaders, + hdtrbuf, sizeof(hdtrbuf)); + /* If not enough buffer, punt to sendv */ + if (rv == APR_INCOMPLETE) { + rv = apr_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + ptfb = NULL; + } + } + + /* Initialize the overlapped structure used on TransmitFile + */ + if (!sock->overlapped) { + sock->overlapped = apr_pcalloc(sock->cntxt, sizeof(OVERLAPPED)); + sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + } + while (bytes_to_send) { + if (bytes_to_send > MAX_SEGMENT_SIZE) { + nbytes = MAX_SEGMENT_SIZE; + } + else { + /* Last call to TransmitFile() */ + nbytes = bytes_to_send; + /* Collapse the trailers into a single buffer */ + if (hdtr && hdtr->numtrailers) { + ptfb = &tfb; + rv = collapse_iovec((char**) &ptfb->Tail, &ptfb->TailLength, + hdtr->trailers, hdtr->numtrailers, + hdtrbuf + ptfb->HeadLength, + sizeof(hdtrbuf) - ptfb->HeadLength); + if (rv == APR_INCOMPLETE) { + /* If not enough buffer, punt to sendv, later */ + sendv_trailers = 1; + } + } + /* Disconnect the socket after last send */ + if ((flags & APR_SENDFILE_DISCONNECT_SOCKET) + && !sendv_trailers) { + dwFlags |= TF_REUSE_SOCKET; + dwFlags |= TF_DISCONNECT; + disconnected = 1; + } + } + + sock->overlapped->Offset = (DWORD)(curoff); +#if APR_HAS_LARGE_FILES + sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32); +#endif + /* XXX BoundsChecker claims dwFlags must not be zero. */ + rv = TransmitFile(sock->socketdes, /* socket */ + file->filehand, /* open file descriptor of the file to be sent */ + nbytes, /* number of bytes to send. 0=send all */ + 0, /* Number of bytes per send. 0=use default */ + sock->overlapped, /* OVERLAPPED structure */ + ptfb, /* header and trailer buffers */ + dwFlags); /* flags to control various aspects of TransmitFile */ + if (!rv) { + status = apr_get_netos_error(); + if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) || + (status == APR_FROM_OS_ERROR(WSA_IO_PENDING))) + { + rv = WaitForSingleObject(sock->overlapped->hEvent, + (DWORD)(sock->timeout >= 0 + ? sock->timeout_ms : INFINITE)); + if (rv == WAIT_OBJECT_0) { + status = APR_SUCCESS; + if (!disconnected) { + if (!WSAGetOverlappedResult(sock->socketdes, + sock->overlapped, + &nbytes, + FALSE, + &dwFlags)) { + status = apr_get_netos_error(); + } + + /* Ugly code alert: WSAGetOverlappedResult returns + * a count of all bytes sent. This loop only + * tracks bytes sent out of the file. + */ + else if (ptfb) { + nbytes -= (ptfb->HeadLength + ptfb->TailLength); + } + } + } + else if (rv == WAIT_TIMEOUT) { + status = APR_FROM_OS_ERROR(WAIT_TIMEOUT); + } + else if (rv == WAIT_ABANDONED) { + /* Hummm... WAIT_ABANDONDED is not an error code. It is + * a return specific to the Win32 WAIT functions that + * indicates that a thread exited while holding a + * mutex. Should consider triggering an assert + * to detect the condition... + */ + status = APR_FROM_OS_ERROR(WAIT_TIMEOUT); + } + else + status = apr_get_os_error(); + } + } + if (status != APR_SUCCESS) + break; + + bytes_to_send -= nbytes; + curoff += nbytes; + *len += nbytes; + /* Adjust len for any headers/trailers sent */ + if (ptfb) { + *len += (ptfb->HeadLength + ptfb->TailLength); + memset(&tfb, '\0', sizeof (tfb)); + ptfb = NULL; + } + } + + if (status == APR_SUCCESS) { + if (sendv_trailers) { + rv = apr_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + } + + + /* Mark the socket as disconnected, but do not close it. + * Note: The application must have stored the socket prior to making + * the call to apr_socket_sendfile in order to either reuse it + * or close it. + */ + if (disconnected) { + sock->disconnected = 1; + sock->socketdes = INVALID_SOCKET; + } + } + + return status; +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, + apr_size_t *len, apr_int32_t flags) +{ + return apr_socket_sendfile(sock, file, hdtr, offset, len, flags); +} + +#endif + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + return apr_socket_send(sock, buf, len); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *nbytes) +{ + return apr_socket_sendv(sock, vec, nvec, nbytes); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + return apr_socket_sendto(sock, where, flags, buf, len); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, + char *buf, apr_size_t *len) +{ + return apr_socket_recvfrom(from, sock, flags, buf, len); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + return apr_socket_recv(sock, buf, len); +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sockets.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sockets.c new file mode 100644 index 00000000..fc2bcb73 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sockets.c @@ -0,0 +1,532 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" +#include "apr_strings.h" +#include <string.h> +#include "apr_arch_inherit.h" +#include "apr_arch_misc.h" + +static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ + +static apr_status_t socket_cleanup(void *sock) +{ + apr_socket_t *thesocket = sock; + + if (thesocket->socketdes != INVALID_SOCKET) { + if (closesocket(thesocket->socketdes) == SOCKET_ERROR) { + return apr_get_netos_error(); + } + thesocket->socketdes = INVALID_SOCKET; + } +#if APR_HAS_SENDFILE + if (thesocket->overlapped) { + CloseHandle(thesocket->overlapped->hEvent); + thesocket->overlapped = NULL; + } +#endif + return APR_SUCCESS; +} + +static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) +{ + sock->type = type; + sock->protocol = protocol; + apr_sockaddr_vars_set(sock->local_addr, family, 0); + apr_sockaddr_vars_set(sock->remote_addr, family, 0); +} +static void alloc_socket(apr_socket_t **new, apr_pool_t *p) +{ + *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); + (*new)->cntxt = p; + (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->local_addr->pool = p; + (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->remote_addr->pool = p; +} + +APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, + int *protocol) +{ + *protocol = sock->protocol; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_create_ex(apr_socket_t **new, int family, + int type, int protocol, + apr_pool_t *cont) +{ + int downgrade = (family == AF_UNSPEC); + + if (family == AF_UNSPEC) { +#if APR_HAVE_IPV6 + family = AF_INET6; +#else + family = AF_INET; +#endif + } + + alloc_socket(new, cont); + + /* For right now, we are not using socket groups. We may later. + * No flags to use when creating a socket, so use 0 for that parameter as well. + */ + (*new)->socketdes = socket(family, type, protocol); +#if APR_HAVE_IPV6 + if ((*new)->socketdes == INVALID_SOCKET && downgrade) { + family = AF_INET; + (*new)->socketdes = socket(family, type, protocol); + } +#endif + + if ((*new)->socketdes == INVALID_SOCKET) { + return apr_get_netos_error(); + } + +#ifdef WIN32 + /* Socket handles are never truly inheritable, there are too many + * bugs associated. WSADuplicateSocket will copy them, but for our + * purposes, always transform the socket() created as a non-inherited + * handle + */ +#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE) + IF_WIN_OS_IS_UNICODE { + /* A different approach. Many users report errors such as + * (32538)An operation was attempted on something that is not + * a socket. : Parent: WSADuplicateSocket failed... + * + * This appears that the duplicated handle is no longer recognized + * as a socket handle. SetHandleInformation should overcome that + * problem by not altering the handle identifier. But this won't + * work on 9x - it's unsupported. + */ + SetHandleInformation((HANDLE) (*new)->socketdes, + HANDLE_FLAG_INHERIT, 0); + } +#endif +#if APR_HAS_ANSI_FS || defined(_WIN32_WCE) + ELSE_WIN_OS_IS_ANSI { + HANDLE hProcess = GetCurrentProcess(); + HANDLE dup; + if (DuplicateHandle(hProcess, (HANDLE) (*new)->socketdes, hProcess, + &dup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { + closesocket((*new)->socketdes); + (*new)->socketdes = (SOCKET) dup; + } + } +#endif + +#endif /* def WIN32 */ + + set_socket_vars(*new, family, type, protocol); + + (*new)->timeout = -1; + (*new)->disconnected = 0; + + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family, + int type, apr_pool_t *cont) +{ + return apr_socket_create_ex(new, family, type, 0, cont); +} + +APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + int winhow = 0; + +#ifdef SD_RECEIVE + switch (how) { + case APR_SHUTDOWN_READ: { + winhow = SD_RECEIVE; + break; + } + case APR_SHUTDOWN_WRITE: { + winhow = SD_SEND; + break; + } + case APR_SHUTDOWN_READWRITE: { + winhow = SD_BOTH; + break; + } + default: + return APR_BADARG; + } +#endif + if (shutdown(thesocket->socketdes, winhow) == 0) { + return APR_SUCCESS; + } + else { + return apr_get_netos_error(); + } +} + +APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket) +{ + apr_pool_cleanup_kill(thesocket->cntxt, thesocket, socket_cleanup); + return socket_cleanup(thesocket); +} + +APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + if (bind(sock->socketdes, + (struct sockaddr *)&sa->sa, + sa->salen) == -1) { + return apr_get_netos_error(); + } + else { + sock->local_addr = sa; + if (sock->local_addr->sa.sin.sin_port == 0) { + sock->local_port_unknown = 1; /* ephemeral port */ + } + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, + apr_int32_t backlog) +{ + if (listen(sock->socketdes, backlog) == SOCKET_ERROR) + return apr_get_netos_error(); + else + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, + apr_socket_t *sock, apr_pool_t *p) +{ + SOCKET s; + struct sockaddr sa; + int salen = sizeof(sock->remote_addr->sa); + + /* Don't allocate the memory until after we call accept. This allows + us to work with nonblocking sockets. */ + s = accept(sock->socketdes, (struct sockaddr *)&sa, &salen); + if (s == INVALID_SOCKET) { + return apr_get_netos_error(); + } + + alloc_socket(new, p); + set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, + sock->protocol); + + (*new)->timeout = -1; + (*new)->disconnected = 0; + + (*new)->socketdes = s; + /* XXX next line looks bogus w.r.t. AF_INET6 support */ + (*new)->remote_addr->salen = sizeof((*new)->remote_addr->sa); + memcpy (&(*new)->remote_addr->sa, &sa, salen); + *(*new)->local_addr = *sock->local_addr; + + /* The above assignment just overwrote the pool entry. Setting the local_addr + pool for the accepted socket back to what it should be. Otherwise all + allocations for this socket will come from a server pool that is not + freed until the process goes down.*/ + (*new)->local_addr->pool = p; + + /* fix up any pointers which are no longer valid */ + if (sock->local_addr->sa.sin.sin_family == AF_INET) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; + } +#if APR_HAVE_IPV6 + else if (sock->local_addr->sa.sin.sin_family == AF_INET6) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; + } +#endif + (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); + if (sock->local_port_unknown) { + /* not likely for a listening socket, but theoretically possible :) */ + (*new)->local_port_unknown = 1; + } + +#if APR_TCP_NODELAY_INHERITED + if (apr_is_option_set(sock->netmask, APR_TCP_NODELAY) == 1) { + apr_set_option(&(*new)->netmask, APR_TCP_NODELAY, 1); + } +#endif /* TCP_NODELAY_INHERITED */ +#if APR_O_NONBLOCK_INHERITED + if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) == 1) { + apr_set_option(&(*new)->netmask, APR_SO_NONBLOCK, 1); + } +#endif /* APR_O_NONBLOCK_INHERITED */ + + if (sock->local_interface_unknown || + !memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* If the interface address inside the listening socket's local_addr wasn't + * up-to-date, we don't know local interface of the connected socket either. + * + * If the listening socket was not bound to a specific interface, we + * don't know the local_addr of the connected socket. + */ + (*new)->local_interface_unknown = 1; + } + + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + apr_status_t rv; + + if ((sock->socketdes == INVALID_SOCKET) || (!sock->local_addr)) { + return APR_ENOTSOCK; + } + + if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin, + sa->salen) == SOCKET_ERROR) { + int rc; + struct timeval tv, *tvptr; + fd_set wfdset, efdset; + + rv = apr_get_netos_error(); + if (rv != APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) { + return rv; + } + + if (sock->timeout == 0) { + /* Tell the app that the connect is in progress... + * Gotta play some games here. connect on Unix will return + * EINPROGRESS under the same circumstances that Windows + * returns WSAEWOULDBLOCK. Do some adhoc canonicalization... + */ + return APR_FROM_OS_ERROR(WSAEINPROGRESS); + } + + /* wait for the connect to complete or timeout */ + FD_ZERO(&wfdset); + FD_SET(sock->socketdes, &wfdset); + FD_ZERO(&efdset); + FD_SET(sock->socketdes, &efdset); + + if (sock->timeout < 0) { + tvptr = NULL; + } + else { + /* casts for winsock/timeval definition */ + tv.tv_sec = (long)apr_time_sec(sock->timeout); + tv.tv_usec = (int)apr_time_usec(sock->timeout); + tvptr = &tv; + } + rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr); + if (rc == SOCKET_ERROR) { + return apr_get_netos_error(); + } + else if (!rc) { + return APR_FROM_OS_ERROR(WSAETIMEDOUT); + } + /* Evaluate the efdset */ + if (FD_ISSET(sock->socketdes, &efdset)) { + /* The connect failed. */ + int rclen = sizeof(rc); + if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) { + return apr_get_netos_error(); + } + return APR_FROM_OS_ERROR(rc); + } + } + /* connect was OK .. amazing */ + sock->remote_addr = sa; + if (sock->local_addr->sa.sin.sin_port == 0) { + sock->local_port_unknown = 1; + } + if (!memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* not bound to specific local interface; connect() had to assign + * one for the socket + */ + sock->local_interface_unknown = 1; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key, + apr_socket_t *sock) +{ + sock_userdata_t *cur = sock->userdata; + + *data = NULL; + + while (cur) { + if (!strcmp(cur->key, key)) { + *data = cur->data; + break; + } + cur = cur->next; + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, + const char *key, + apr_status_t (*cleanup)(void *)) +{ + sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t)); + + new->key = apr_pstrdup(sock->cntxt, key); + new->data = data; + new->next = sock->userdata; + sock->userdata = new; + + if (cleanup) { + apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, + apr_socket_t *sock) +{ + *thesock = sock->socketdes; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont) +{ + alloc_socket(apr_sock, cont); +#ifdef APR_ENABLE_FOR_1_0 /* no protocol field yet */ + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); +#else + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, 0); +#endif + (*apr_sock)->timeout = -1; + (*apr_sock)->disconnected = 0; + (*apr_sock)->socketdes = *os_sock_info->os_sock; + if (os_sock_info->local) { + memcpy(&(*apr_sock)->local_addr->sa.sin, + os_sock_info->local, + (*apr_sock)->local_addr->salen); + (*apr_sock)->local_addr->pool = cont; + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; + } + if (os_sock_info->remote) { + memcpy(&(*apr_sock)->remote_addr->sa.sin, + os_sock_info->remote, + (*apr_sock)->remote_addr->salen); + (*apr_sock)->remote_addr->pool = cont; + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->remote_addr_unknown = 1; + } + + apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock), + socket_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, + apr_os_sock_t *thesock, + apr_pool_t *cont) +{ + if ((*sock) == NULL) { + alloc_socket(sock, cont); + /* XXX figure out the actual socket type here */ + /* *or* just decide that apr_os_sock_put() has to be told the family and type */ + set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0); + (*sock)->timeout = -1; + (*sock)->disconnected = 0; + } + (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; + (*sock)->remote_addr_unknown = 1; + (*sock)->socketdes = *thesock; + return APR_SUCCESS; +} + + +/* Sockets cannot be inherited through the standard sockets + * inheritence. WSADuplicateSocket must be used. + * This is not trivial to implement. + */ + +APR_DECLARE(apr_status_t) apr_socket_inherit_set(apr_socket_t *socket) +{ + return APR_ENOTIMPL; +} +/* Deprecated */ +APR_DECLARE(void) apr_socket_set_inherit(apr_socket_t *socket) +{ + apr_socket_inherit_set(socket); +} + +APR_DECLARE(apr_status_t) apr_socket_inherit_unset(apr_socket_t *socket) +{ + return APR_ENOTIMPL; +} +/* Deprecated */ +APR_DECLARE(void) apr_socket_unset_inherit(apr_socket_t *socket) +{ + apr_socket_inherit_unset(socket); +} +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + return apr_socket_shutdown(thesocket, how); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + return apr_socket_bind(sock, sa); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_listen(apr_socket_t *sock, apr_int32_t backlog) +{ + return apr_socket_listen(sock, backlog); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_accept(apr_socket_t **new, apr_socket_t *sock, + apr_pool_t *p) +{ + return apr_socket_accept(new, sock, p); +} + +/* Deprecated */ +APR_DECLARE(apr_status_t) apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + return apr_socket_connect(sock, sa); +} diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sockopt.c b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sockopt.c new file mode 100644 index 00000000..ab5dafd1 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/network_io/win32/sockopt.c @@ -0,0 +1,280 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include <string.h> + +apr_status_t soblock(SOCKET sd) +{ + u_long zero = 0; + + if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) { + return apr_get_netos_error(); + } + return APR_SUCCESS; +} + +apr_status_t sononblock(SOCKET sd) +{ + u_long one = 1; + + if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) { + return apr_get_netos_error(); + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t) +{ + apr_status_t stat; + + if (t == 0) { + /* Set the socket non-blocking if it was previously blocking */ + if (sock->timeout != 0) { + if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + } + else if (t > 0) { + /* Set the socket to blocking if it was previously non-blocking */ + if (sock->timeout == 0) { + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + /* Reset socket timeouts if the new timeout differs from the old timeout */ + if (sock->timeout != t) + { + /* Win32 timeouts are in msec, represented as int */ + sock->timeout_ms = (int)apr_time_as_msec(t); + setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, + (char *) &sock->timeout_ms, + sizeof(sock->timeout_ms)); + setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, + (char *) &sock->timeout_ms, + sizeof(sock->timeout_ms)); + } + } + else if (t < 0) { + int zero = 0; + /* Set the socket to blocking with infinite timeouts */ + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) + return stat; + setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, + (char *) &zero, sizeof(zero)); + setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, + (char *) &zero, sizeof(zero)); + } + sock->timeout = t; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + int one; + apr_status_t stat; + + one = on ? 1 : 0; + + switch (opt) { + case APR_SO_TIMEOUT: + { + /* XXX: To be deprecated */ + return apr_socket_timeout_set(sock, on); + } + case APR_SO_KEEPALIVE: + if (on != apr_is_option_set(sock->netmask, APR_SO_KEEPALIVE)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, + (void *)&one, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(&sock->netmask,APR_SO_KEEPALIVE, on); + } + break; + case APR_SO_DEBUG: + if (on != apr_is_option_set(sock->netmask, APR_SO_DEBUG)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, + (void *)&one, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(&sock->netmask, APR_SO_DEBUG, on); + } + break; + case APR_SO_SNDBUF: + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, + (void *)&on, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + break; + case APR_SO_RCVBUF: + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF, + (void *)&on, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + break; + case APR_SO_REUSEADDR: + if (on != apr_is_option_set(sock->netmask, APR_SO_REUSEADDR)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, + (void *)&one, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(&sock->netmask, APR_SO_REUSEADDR, on); + } + break; + case APR_SO_NONBLOCK: + if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) != on) { + if (on) { + if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + else { + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + apr_set_option(&sock->netmask, APR_SO_NONBLOCK, on); + } + break; + case APR_SO_LINGER: + { + if (apr_is_option_set(sock->netmask, APR_SO_LINGER) != on) { + struct linger li; + li.l_onoff = on; + li.l_linger = APR_MAX_SECS_TO_LINGER; + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, + (char *) &li, sizeof(struct linger)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(&sock->netmask, APR_SO_LINGER, on); + } + break; + } + case APR_TCP_NODELAY: + if (apr_is_option_set(sock->netmask, APR_TCP_NODELAY) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_NODELAY; + +#if APR_HAVE_SCTP + if (sock->protocol == IPPROTO_SCTP) { + optlevel = IPPROTO_SCTP; + optname = SCTP_NODELAY; + } +#endif + if (setsockopt(sock->socketdes, optlevel, optname, + (void *)&on, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(&sock->netmask, APR_TCP_NODELAY, on); + } + break; + case APR_IPV6_V6ONLY: +#if APR_HAVE_IPV6 && defined(IPV6_V6ONLY) + /* we don't know the initial setting of this option, + * so don't check sock->netmask since that optimization + * won't work + */ + if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(&sock->netmask, APR_IPV6_V6ONLY, on); +#else + return APR_ENOTIMPL; +#endif + break; + default: + return APR_EINVAL; + break; + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t) +{ + *t = sock->timeout; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + switch (opt) { + case APR_SO_TIMEOUT: + /* XXX: to be deprecated */ + *on = (apr_int32_t)sock->timeout; + break; + case APR_SO_DISCONNECTED: + *on = sock->disconnected; + break; + case APR_SO_KEEPALIVE: + case APR_SO_DEBUG: + case APR_SO_REUSEADDR: + case APR_SO_NONBLOCK: + case APR_SO_LINGER: + default: + *on = apr_is_option_set(sock->netmask, opt); + } + return APR_SUCCESS; +} + + +/* deprecated */ +APR_DECLARE(apr_status_t) apr_setsocketopt(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + return apr_socket_opt_set(sock, opt, on); +} + +APR_DECLARE(apr_status_t) apr_getsocketopt(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + return apr_socket_opt_get(sock, opt, on); +} + + +APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark) +{ + u_long oobmark; + + if (ioctlsocket(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0) + return apr_get_netos_error(); + + *atmark = (oobmark != 0); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len, + apr_pool_t *cont) +{ + if (gethostname(buf, len) == -1) { + buf[0] = '\0'; + return apr_get_netos_error(); + } + else if (!memchr(buf, '\0', len)) { /* buffer too small */ + buf[0] = '\0'; + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} + |