diff options
author | Ivan Zhakov <ivan@apache.org> | 2022-01-20 12:40:37 +0000 |
---|---|---|
committer | Ivan Zhakov <ivan@apache.org> | 2022-01-20 12:40:37 +0000 |
commit | a484479e9e36e50fd870eb223c5043fa90211ea4 (patch) | |
tree | 1a7eddfa889135959b68f6077a44cdee3bd07abd | |
parent | 9ab53c7804e74e3302efafd35182e1f670967d7f (diff) | |
download | apr-a484479e9e36e50fd870eb223c5043fa90211ea4.tar.gz |
On 'win32-pollset-wakeup-no-file-socket-emulation' branch:
Windows: Use term `socket_pipe` instead for `file_socket_pipe` for internal
poll wakeup socket API. Move implementation to network_io/win32/socket_pipe.c
from file_io/win32/pipe.c.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/win32-pollset-wakeup-no-file-socket-emulation@1897246 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | file_io/win32/pipe.c | 178 | ||||
-rw-r--r-- | include/arch/win32/apr_arch_file_io.h | 8 | ||||
-rw-r--r-- | include/arch/win32/apr_arch_networkio.h | 8 | ||||
-rw-r--r-- | network_io/win32/socket_pipe.c | 195 | ||||
-rw-r--r-- | poll/unix/wakeup.c | 6 |
6 files changed, 207 insertions, 189 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fee043dd..adee368af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,6 +351,7 @@ SET(APR_SOURCES network_io/unix/sockaddr.c network_io/unix/socket_util.c network_io/win32/sendrecv.c + network_io/win32/socket_pipe.c network_io/win32/sockets.c network_io/win32/sockopt.c passwd/apr_getpass.c diff --git a/file_io/win32/pipe.c b/file_io/win32/pipe.c index a28fdb843..3da361cb2 100644 --- a/file_io/win32/pipe.c +++ b/file_io/win32/pipe.c @@ -15,7 +15,6 @@ */ #include "apr_arch_file_io.h" -#include "apr_arch_networkio.h" #include "apr_file_io.h" #include "apr_general.h" #include "apr_strings.h" @@ -275,180 +274,3 @@ APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file, { return apr_os_pipe_put_ex(file, thefile, 0, pool); } - -static apr_status_t create_socket_pipe(SOCKET *rd, SOCKET *wr) -{ - FD_SET rs; - SOCKET ls; - struct timeval socktm; - struct sockaddr_in pa; - struct sockaddr_in la; - struct sockaddr_in ca; - int nrd; - apr_status_t rv; - int ll = sizeof(la); - int lc = sizeof(ca); - unsigned long bm = 1; - char uid[8]; - char iid[8]; - - *rd = INVALID_SOCKET; - *wr = INVALID_SOCKET; - - /* Create the unique socket identifier - * so that we know the connection originated - * from us. - */ - rv = apr_generate_random_bytes(uid, sizeof(uid)); - if (rv != APR_SUCCESS) { - return rv; - } - - if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { - return apr_get_netos_error(); - } - - pa.sin_family = AF_INET; - pa.sin_port = 0; - pa.sin_addr.s_addr = inet_addr("127.0.0.1"); - - if (bind(ls, (SOCKADDR *)&pa, sizeof(pa)) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (getsockname(ls, (SOCKADDR *)&la, &ll) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (listen(ls, 1) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if ((*wr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (connect(*wr, (SOCKADDR *)&la, sizeof(la)) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (send(*wr, uid, sizeof(uid), 0) != sizeof(uid)) { - if ((rv = apr_get_netos_error()) == 0) { - rv = APR_EINVAL; - } - goto cleanup; - } - if (ioctlsocket(ls, FIONBIO, &bm) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - for (;;) { - int ns; - int nc = 0; - /* Listening socket is nonblocking by now. - * The accept should create the socket - * immediatelly because we are connected already. - * However on buys systems this can take a while - * until winsock gets a chance to handle the events. - */ - FD_ZERO(&rs); - FD_SET(ls, &rs); - - socktm.tv_sec = 1; - socktm.tv_usec = 0; - if ((ns = select(0, &rs, NULL, NULL, &socktm)) == SOCKET_ERROR) { - /* Accept still not signaled */ - Sleep(100); - continue; - } - if (ns == 0) { - /* No connections in the last second */ - continue; - } - if ((*rd = accept(ls, (SOCKADDR *)&ca, &lc)) == INVALID_SOCKET) { - rv = apr_get_netos_error(); - goto cleanup; - } - /* Verify the connection by reading/waiting for the identification */ - bm = 0; - if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - nrd = recv(*rd, iid, sizeof(iid), 0); - if (nrd == SOCKET_ERROR) { - rv = apr_get_netos_error(); - goto cleanup; - } - if (nrd == (int)sizeof(uid) && memcmp(iid, uid, sizeof(uid)) == 0) { - /* Got the right identifier, return. */ - break; - } - closesocket(*rd); - } - /* We don't need the listening socket any more */ - closesocket(ls); - return 0; - -cleanup: - /* Don't leak resources */ - closesocket(ls); - if (*rd != INVALID_SOCKET) - closesocket(*rd); - if (*wr != INVALID_SOCKET) - closesocket(*wr); - - *rd = INVALID_SOCKET; - *wr = INVALID_SOCKET; - return rv; -} - -static apr_status_t socket_pipe_cleanup(void *thefile) -{ - apr_socket_t *file = thefile; - if (file->socketdes != INVALID_SOCKET) { - shutdown(file->socketdes, SD_BOTH); - closesocket(file->socketdes); - file->socketdes = INVALID_SOCKET; - } - return APR_SUCCESS; -} - -apr_status_t apr_file_socket_pipe_create(apr_socket_t **in, - apr_socket_t **out, - apr_pool_t *p) -{ - apr_status_t rv; - SOCKET rd; - SOCKET wr; - - *in = NULL; - *out = NULL; - - if ((rv = create_socket_pipe(&rd, &wr)) != APR_SUCCESS) { - return rv; - } - apr_os_sock_put(in, &rd, p); - apr_os_sock_put(out, &wr, p); - - /* read end of the pipe is non-blocking */ - apr_socket_timeout_set(*in, 0); - - apr_pool_cleanup_register(p, (void *)(*in), socket_pipe_cleanup, - apr_pool_cleanup_null); - apr_pool_cleanup_register(p, (void *)(*out), socket_pipe_cleanup, - apr_pool_cleanup_null); - - return rv; -} - -apr_status_t apr_file_socket_pipe_close(apr_socket_t *socket) -{ - apr_status_t stat; - if ((stat = socket_pipe_cleanup(socket)) == APR_SUCCESS) { - apr_pool_cleanup_kill(socket->pool, socket, socket_pipe_cleanup); - - return APR_SUCCESS; - } - return stat; -} diff --git a/include/arch/win32/apr_arch_file_io.h b/include/arch/win32/apr_arch_file_io.h index f5d20514b..2bee5abc1 100644 --- a/include/arch/win32/apr_arch_file_io.h +++ b/include/arch/win32/apr_arch_file_io.h @@ -250,12 +250,4 @@ apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p); apr_status_t file_cleanup(void *); -extern apr_status_t -apr_file_socket_pipe_create(apr_socket_t **in, - apr_socket_t **out, - apr_pool_t *p); - -extern apr_status_t -apr_file_socket_pipe_close(apr_socket_t *socket); - #endif /* ! FILE_IO_H */ diff --git a/include/arch/win32/apr_arch_networkio.h b/include/arch/win32/apr_arch_networkio.h index a2d0879c1..d02a765be 100644 --- a/include/arch/win32/apr_arch_networkio.h +++ b/include/arch/win32/apr_arch_networkio.h @@ -77,5 +77,13 @@ void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t); (skt)->options &= ~(option); \ } while (0) +extern apr_status_t +apr_socket_pipe_create(apr_socket_t **in, + apr_socket_t **out, + apr_pool_t *p); + +extern apr_status_t +apr_socket_pipe_close(apr_socket_t *socket); + #endif /* ! NETWORK_IO_H */ diff --git a/network_io/win32/socket_pipe.c b/network_io/win32/socket_pipe.c new file mode 100644 index 000000000..d9cac504b --- /dev/null +++ b/network_io/win32/socket_pipe.c @@ -0,0 +1,195 @@ +/* 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_portable.h" + +static apr_status_t create_socket_pipe(SOCKET *rd, SOCKET *wr) +{ + FD_SET rs; + SOCKET ls; + struct timeval socktm; + struct sockaddr_in pa; + struct sockaddr_in la; + struct sockaddr_in ca; + int nrd; + apr_status_t rv; + int ll = sizeof(la); + int lc = sizeof(ca); + unsigned long bm = 1; + char uid[8]; + char iid[8]; + + *rd = INVALID_SOCKET; + *wr = INVALID_SOCKET; + + /* Create the unique socket identifier + * so that we know the connection originated + * from us. + */ + rv = apr_generate_random_bytes(uid, sizeof(uid)); + if (rv != APR_SUCCESS) { + return rv; + } + + if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + return apr_get_netos_error(); + } + + pa.sin_family = AF_INET; + pa.sin_port = 0; + pa.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (bind(ls, (SOCKADDR *)&pa, sizeof(pa)) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (getsockname(ls, (SOCKADDR *)&la, &ll) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (listen(ls, 1) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if ((*wr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (connect(*wr, (SOCKADDR *)&la, sizeof(la)) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (send(*wr, uid, sizeof(uid), 0) != sizeof(uid)) { + if ((rv = apr_get_netos_error()) == 0) { + rv = APR_EINVAL; + } + goto cleanup; + } + if (ioctlsocket(ls, FIONBIO, &bm) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + for (;;) { + int ns; + int nc = 0; + /* Listening socket is nonblocking by now. + * The accept should create the socket + * immediatelly because we are connected already. + * However on buys systems this can take a while + * until winsock gets a chance to handle the events. + */ + FD_ZERO(&rs); + FD_SET(ls, &rs); + + socktm.tv_sec = 1; + socktm.tv_usec = 0; + if ((ns = select(0, &rs, NULL, NULL, &socktm)) == SOCKET_ERROR) { + /* Accept still not signaled */ + Sleep(100); + continue; + } + if (ns == 0) { + /* No connections in the last second */ + continue; + } + if ((*rd = accept(ls, (SOCKADDR *)&ca, &lc)) == INVALID_SOCKET) { + rv = apr_get_netos_error(); + goto cleanup; + } + /* Verify the connection by reading/waiting for the identification */ + bm = 0; + if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + nrd = recv(*rd, iid, sizeof(iid), 0); + if (nrd == SOCKET_ERROR) { + rv = apr_get_netos_error(); + goto cleanup; + } + if (nrd == (int)sizeof(uid) && memcmp(iid, uid, sizeof(uid)) == 0) { + /* Got the right identifier, return. */ + break; + } + closesocket(*rd); + } + /* We don't need the listening socket any more */ + closesocket(ls); + return 0; + +cleanup: + /* Don't leak resources */ + closesocket(ls); + if (*rd != INVALID_SOCKET) + closesocket(*rd); + if (*wr != INVALID_SOCKET) + closesocket(*wr); + + *rd = INVALID_SOCKET; + *wr = INVALID_SOCKET; + return rv; +} + +static apr_status_t socket_pipe_cleanup(void *thefile) +{ + apr_socket_t *file = thefile; + if (file->socketdes != INVALID_SOCKET) { + shutdown(file->socketdes, SD_BOTH); + closesocket(file->socketdes); + file->socketdes = INVALID_SOCKET; + } + return APR_SUCCESS; +} + +apr_status_t apr_socket_pipe_create(apr_socket_t **in, + apr_socket_t **out, + apr_pool_t *p) +{ + apr_status_t rv; + SOCKET rd; + SOCKET wr; + + *in = NULL; + *out = NULL; + + if ((rv = create_socket_pipe(&rd, &wr)) != APR_SUCCESS) { + return rv; + } + apr_os_sock_put(in, &rd, p); + apr_os_sock_put(out, &wr, p); + + /* read end of the pipe is non-blocking */ + apr_socket_timeout_set(*in, 0); + + apr_pool_cleanup_register(p, (void *)(*in), socket_pipe_cleanup, + apr_pool_cleanup_null); + apr_pool_cleanup_register(p, (void *)(*out), socket_pipe_cleanup, + apr_pool_cleanup_null); + + return rv; +} + +apr_status_t apr_socket_pipe_close(apr_socket_t *socket) +{ + apr_status_t stat; + if ((stat = socket_pipe_cleanup(socket)) == APR_SUCCESS) { + apr_pool_cleanup_kill(socket->pool, socket, socket_pipe_cleanup); + + return APR_SUCCESS; + } + return stat; +} diff --git a/poll/unix/wakeup.c b/poll/unix/wakeup.c index e2deea172..bb0356444 100644 --- a/poll/unix/wakeup.c +++ b/poll/unix/wakeup.c @@ -33,7 +33,7 @@ apr_status_t apr_poll_create_wakeup_socket(apr_pool_t *pool, apr_pollfd_t *pfd, { apr_status_t rv; - if ((rv = apr_file_socket_pipe_create(&wakeup_socket[0], &wakeup_socket[1], + if ((rv = apr_socket_pipe_create(&wakeup_socket[0], &wakeup_socket[1], pool)) != APR_SUCCESS) return rv; @@ -50,11 +50,11 @@ apr_status_t apr_poll_close_wakeup_socket(apr_socket_t **wakeup_socket) /* Close both sides of the wakeup pipe */ if (wakeup_socket[0]) { - rv0 = apr_file_socket_pipe_close(wakeup_socket[0]); + rv0 = apr_socket_pipe_close(wakeup_socket[0]); wakeup_socket[0] = NULL; } if (wakeup_socket[1]) { - rv1 = apr_file_socket_pipe_close(wakeup_socket[1]); + rv1 = apr_socket_pipe_close(wakeup_socket[1]); wakeup_socket[1] = NULL; } return rv0 ? rv0 : rv1; |