stoddard 99/10/20 13:56:04
Modified: src/os/win32 iol_socket.c Log: Win32: Continuing Manoj's work updating iol_socket to return ap_status_t Revision Changes Path 1.6 +104 -441 apache-2.0/src/os/win32/iol_socket.c Index: iol_socket.c =================================================================== RCS file: /home/cvs/apache-2.0/src/os/win32/iol_socket.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- iol_socket.c 1999/10/08 19:07:11 1.5 +++ iol_socket.c 1999/10/20 20:56:03 1.6 @@ -60,11 +60,6 @@ #include "ap_iol.h" #include "iol_socket.h" -#define FD_NONBLOCKING_SET (1) -//#define IOL_SOCK_POSIX // This works except for writev -#define IOL_SOCK_WIN32 -//#define IOL_SOCK_ASYNC - typedef struct { ap_iol iol; int fd; @@ -72,7 +67,7 @@ int timeout; } iol_socket; -static int win32_setopt(ap_iol *viol, ap_iol_option opt, const void *value) +static ap_status_t win32_setopt(ap_iol *viol, ap_iol_option opt, const void *value) { iol_socket *iol = (iol_socket *)viol; @@ -81,13 +76,12 @@ iol->timeout = *(const int *)value; break; default: - WSASetLastError(WSAEINVAL); - return -1; + return APR_EINVAL; } - return 0; + return APR_SUCCESS; } -static int win32_getopt(ap_iol *viol, ap_iol_option opt, void *value) +static ap_status_t win32_getopt(ap_iol *viol, ap_iol_option opt, void *value) { iol_socket *iol = (iol_socket *)viol; @@ -96,412 +90,131 @@ *(int *)value = iol->timeout; break; default: - WSASetLastError(WSAEINVAL); - return -1; + return APR_EINVAL; } - return 0; + return APR_SUCCESS; } -static int set_nonblock(int fd) +static ap_status_t set_nonblock(int fd) { int iostate = 1; ioctlsocket(fd, FIONBIO, &iostate); - return 0; + return APR_SUCCESS; } -static int win32_close(ap_iol *viol) +static ap_status_t win32_close(ap_iol *viol) { iol_socket *iol = (iol_socket *)viol; int rv; rv = closesocket(iol->fd); - -// free(iol); - - return rv; -} -#ifdef IOL_SOCK_POSIX -/* the timeout code is a separate routine because it requires - a stack frame... and we don't want to pay that setup cost - on every call */ - -/* this macro expands into the four basic i/o methods */ - -#define method(name, args, syscall, selread, selwrite) \ - static int win32_##name##_timeout args \ - { \ - iol_socket *iol = (iol_socket *)viol; \ - fd_set fdset; \ - struct timeval tv; \ - int rv; \ - int lasterror; \ - \ - FD_ZERO(&fdset); \ - FD_SET(iol->fd, &fdset); \ - tv.tv_sec = iol->timeout; \ - tv.tv_usec = 0; \ - do { \ - rv = select(iol->fd + 1, selread, selwrite, NULL, iol->timeout < 0 ? NULL : &tv); \ - if (rv == SOCKET_ERROR) { \ - lasterror = WSAGetLastError(); \ - } \ - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); \ - if (!FD_ISSET(iol->fd, &fdset)) { \ - WSASetLastError(WSAETIMEDOUT); \ - return -1; \ - } \ - do { \ - rv = syscall(iol->fd, arg1, arg2, 0); \ - if (rv == SOCKET_ERROR) { \ - lasterror = WSAGetLastError(); \ - } \ - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); \ - return rv; \ - } \ - \ - static int win32_##name args \ - { \ - iol_socket *iol = (iol_socket *)viol; \ - int rv; \ - int lasterror; \ - \ - if (!(iol->flags & FD_NONBLOCKING_SET)) { \ - if (iol->timeout < 0) { \ - return syscall(iol->fd, arg1, arg2, 0); \ - } \ - /* must shift descriptor to blocking mode now */ \ - if (set_nonblock(iol->fd)) { \ - return -1; \ - } \ - iol->flags |= FD_NONBLOCKING_SET; \ - } \ - \ - /* try writing, ignoring EINTR, the upper layer has to handle \ - partial read/writes anyhow, so we can return early */ \ - do { \ - rv = syscall(iol->fd, arg1, arg2, 0); \ - if (rv == SOCKET_ERROR) { \ - lasterror = WSAGetLastError(); \ - } \ - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); \ - if (rv >= 0) { \ - return rv; \ - } \ - if (lasterror == WSAEWOULDBLOCK && iol->timeout != 0) { \ - return win32_##name##_timeout(viol, arg1, arg2); \ - } \ - return -1; \ - } \ - -method(send, (ap_iol *viol, const char *arg1, int arg2), send, NULL, &fdset) -//method(writev, (ap_iol *viol, const struct iovec *arg1, int arg2), writev, NULL, &fdset) -method(recv, (ap_iol *viol, char *arg1, int arg2), recv, &fdset, NULL) - - -static const ap_iol_methods socket_methods = { - win32_close, - win32_send, -// win32_writev, - win32_recv, - win32_setopt, - win32_getopt -}; - -#elif defined(IOL_SOCK_WIN32) -/* -static int win32_send(ap_iol *viol, const char *buf, int len) -{ - int rv; - int lasterror; - iol_socket *iol = (iol_socket *)viol; - WSABUF wsaData; - - wsaData.len = len; - wsaData.buf = (const char*) buf; - - if (set_nonblock(iol->fd)) { - return -1; - } - - do { - rv = WSASend(iol->fd, &wsaData, 1, &len, 0, NULL, NULL); - if (rv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - - if (rv == SOCKET_ERROR && lasterror == WSAEWOULDBLOCK && iol->timeout > 0) { - struct timeval tv; - fd_set fdset; - int srv; - - do { - FD_ZERO(&fdset); - FD_SET(iol->fd, &fdset); - tv.tv_sec = iol->timeout; - tv.tv_usec = 0; - - srv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv); - if (srv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - } while (srv == SOCKET_ERROR && errno == WSAEINTR); - - if (srv == 0) { - return -1; - } - if (srv < 0) { - return -1; - } - else { - do { - rv = WSASend(iol->fd, &wsaData, 1, &len, 0, NULL, NULL); - if (rv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - } - } - else if (rv == SOCKET_ERROR) { - len = -1; - } - - return len; -} -static int win32_recv( ap_iol *viol, const char *buf, int len) -{ - int rv; - int lasterror; - iol_socket *iol = (iol_socket *)viol; - WSABUF wsaData; - DWORD dwBytesRecv; - DWORD flags = 0; - - wsaData.len = len; - wsaData.buf = buf; - if (set_nonblock(iol->fd)) { - return -1; + if (rv == SOCKET_ERROR) { + //free(iol); + return WSAGetLastError(); } - - do { - rv = WSARecv(iol->fd, &wsaData, 1, &dwBytesRecv, &flags, NULL, NULL); - if (rv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - else - len = dwBytesRecv; - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - - if (rv == SOCKET_ERROR && lasterror == WSAEWOULDBLOCK && iol->timeout > 0) { - struct timeval tv; - fd_set fdset; - int srv; - - do { - FD_ZERO(&fdset); - FD_SET(iol->fd, &fdset); - tv.tv_sec = iol->timeout; - tv.tv_usec = 0; - - srv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv); - if (srv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - } while (srv == SOCKET_ERROR && errno == WSAEINTR); - - if (srv == 0) { - return -1; - } - else if (srv < 0) { - return -1; - } - else { - do { - rv = WSARecv(iol->fd, &wsaData, 1, &dwBytesRecv, &flags, NULL, NULL); - if (rv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - else - len = dwBytesRecv; - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - } - } - else if (rv == SOCKET_ERROR) { - len = -1; - } - - return len; + //free(iol); + return APR_SUCCESS; } -static int win32_writev(ap_iol *viol, const struct iovec *vec, int num) +static ap_status_t win32_write(ap_iol *viol, const char *buf, ap_size_t len, ap_ssize_t *nbytes) { - int i; int rv; - int lasterror; - int len = 0; - LPWSABUF pWsaData = malloc(sizeof(WSABUF) * num); - - iol_socket *iol = (iol_socket *)viol; - - if (!pWsaData) - return -1; - - for (i = 0; i < num; i++) { - pWsaData[i].buf = vec[i].iov_base; - pWsaData[i].len = vec[i].iov_len; - } - - if (set_nonblock(iol->fd)) { - free(pWsaData); - return -1; - } - - do { - rv = WSASend(iol->fd, pWsaData, num, &len, 0, NULL, NULL); - if (rv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - - if (rv == SOCKET_ERROR && lasterror == WSAEWOULDBLOCK && iol->timeout > 0) { - struct timeval tv; - fd_set fdset; - int srv; - - do { - FD_ZERO(&fdset); - FD_SET(iol->fd, &fdset); - tv.tv_sec = iol->timeout; - tv.tv_usec = 0; - - srv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv); - if (srv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - } while (srv == SOCKET_ERROR && errno == WSAEINTR); - - if (srv == 0) { - free(pWsaData); - return -1; - } - if (srv < 0) { - free(pWsaData); - return -1; - } - else { - do { - rv = WSASend(iol->fd, pWsaData, num, &len, 0, NULL, NULL); - if (rv == SOCKET_ERROR) { - lasterror = WSAGetLastError(); - } - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - } - } - else if (rv == SOCKET_ERROR) { - len = -1; - } - - free(pWsaData); - return len; -} -*/ -static int win32_send(ap_iol *viol, const char *buf, int len) -{ - int rv; int lasterror; int timeout; - iol_socket *iol = (iol_socket *)viol; WSABUF wsaData; + DWORD dwBytesSent = 0; + iol_socket *iol = (iol_socket *)viol; wsaData.len = len; - wsaData.buf = (const char*) buf; + wsaData.buf = (char*) buf; timeout = iol->timeout * 1000; /* setsockopt requires timeout in milliseconds */ - rv = setsockopt(iol->fd, SOL_SOCKET, SO_SNDTIMEO, - (char*) &timeout, sizeof(timeout)); - if (rv != NO_ERROR) { - printf("win32send: setsockopt failed.\n"); - return -1; - } - do { - rv = WSASend(iol->fd, &wsaData, 1, &len, 0, NULL, NULL); - if (rv != SOCKET_ERROR) { - return len; - } - else { - lasterror = WSAGetLastError(); - } - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - - /* TEST CODE - * If lasterror ==WSATIMEDOUT, then the connection timed out - */ - if (rv == SOCKET_ERROR && lasterror == WSAETIMEDOUT) { - printf("wsasend: Connection timed out\n"); - } else { - printf("Connection failed. lasterror = %d\n", lasterror); + rv = setsockopt(iol->fd, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, + sizeof(timeout)); + if (rv == SOCKET_ERROR) { + return WSAGetLastError(); + } + + rv = WSASend(iol->fd, &wsaData, 1, &dwBytesSent, 0, NULL, NULL); + if (rv == SOCKET_ERROR) { + /* Note: + * Windows function calls do not normally fail with EINTR. If they do, + * consider it an unrecoverable error and do not 'try-again' + * Future: + * This code will need modification when we begin supporting overlapped + * I/O (when WSA_IO_PENDING could be received). + */ + *nbytes = 0; + lasterror = WSAGetLastError(); + if (lasterror == WSAETIMEDOUT) + printf("wsasend: Connection timed out\n"); + else + printf("wsasend: connection failed. lasterror = %d\n", lasterror); + return lasterror; } - return -1; + *nbytes = dwBytesSent; + + return APR_SUCCESS; } -static int win32_recv( ap_iol *viol, const char *buf, int len) +static ap_status_t win32_recv( ap_iol *viol, const char *buf, ap_size_t len, ap_ssize_t *nbytes) { int rv; int lasterror; int timeout; - iol_socket *iol = (iol_socket *)viol; - WSABUF wsaData; DWORD dwBytesRecv; DWORD flags = 0; + iol_socket *iol = (iol_socket *)viol; wsaData.len = len; - wsaData.buf = buf; + wsaData.buf = (char*) buf; timeout = iol->timeout * 1000; /* setsockopt requires timeout in milliseconds */ - rv = setsockopt(iol->fd, SOL_SOCKET, SO_RCVTIMEO, - (char*) &timeout, sizeof(timeout)); - if (rv != NO_ERROR) { - printf("win32recv: setsockopt failed. errno = %d\n", WSAGetLastError()); - return -1; - } - do { - rv = WSARecv(iol->fd, &wsaData, 1, &dwBytesRecv, &flags, NULL, NULL); - if (rv != SOCKET_ERROR) { - return (int) dwBytesRecv; - } - else { - lasterror = WSAGetLastError(); - } - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - - /* TEST CODE - * If lasterror ==WSATIMEDOUT, then the connection timed out - */ - if (rv == SOCKET_ERROR && lasterror == WSAETIMEDOUT) { - printf("wsarecv: Connection timed out\n"); - } else { - printf("Connection failed. lasterror = %d\n", lasterror); + rv = setsockopt(iol->fd, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, + sizeof(timeout)); + if (rv == SOCKET_ERROR) { + return WSAGetLastError(); + } + + rv = WSARecv(iol->fd, &wsaData, 1, &dwBytesRecv, &flags, NULL, NULL); + if (rv == SOCKET_ERROR) { + /* Note: + * Windows function calls do not normally fail with EINTR. If they do, + * consider it an unrecoverable error and do not 'try-again' + * Future: + * This code will need modification when we begin supporting overlapped + * I/O (when WSA_IO_PENDING could be received). + */ + *nbytes = 0; + lasterror = WSAGetLastError(); + if (lasterror == WSAETIMEDOUT) + printf("wsarecv: Connection timed out\n"); + else + printf("wsarecv: connection failed. lasterror = %d\n", lasterror); + return lasterror; } - return -1; + *nbytes = dwBytesRecv; + + return APR_SUCCESS; } -static int win32_writev(ap_iol *viol, const struct iovec *vec, int num) +static ap_status_t win32_writev(ap_iol *viol, const struct iovec *vec, int num, ap_ssize_t *nbytes) { int i; int rv; int lasterror; - int len = 0; int timeout; + DWORD dwBytesSent = 0; iol_socket *iol = (iol_socket *)viol; - LPWSABUF pWsaData = malloc(sizeof(WSABUF) * num); + if (!pWsaData) - return -1; + return APR_ENOMEM; for (i = 0; i < num; i++) { pWsaData[i].buf = vec[i].iov_base; @@ -510,98 +223,48 @@ timeout = iol->timeout * 1000; /* setsockopt requires timeout in milliseconds */ - rv = setsockopt(iol->fd, SOL_SOCKET, SO_SNDTIMEO, - (char*) &timeout, sizeof(timeout)); - if (rv != NO_ERROR) { - printf("win32recv: setsockopt failed. errno = %d\n", WSAGetLastError()); - return -1; - } + rv = setsockopt(iol->fd, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, + sizeof(timeout)); + if (rv == SOCKET_ERROR) { + lasterror = WSAGetLastError(); + printf("win32_writev: setsockopt failed. errno = %d\n", lasterror); + return lasterror; + } + + rv = WSASend(iol->fd, pWsaData, num, &dwBytesSent, 0, NULL, NULL); + if (rv == SOCKET_ERROR) { + /* Note: + * Windows function calls do not normally fail with EINTR. If they do, + * consider it an unrecoverable error and do not 'try-again' + * Future: + * This code will need modification when we begin supporting overlapped + * I/O (when WSA_IO_PENDING could be received). + */ + *nbytes = 0; + lasterror = WSAGetLastError(); + if (lasterror == WSAETIMEDOUT) + printf("wsasend: Connection timed out\n"); + else + printf("wsasend: connection failed. lasterror = %d\n", lasterror); - do { - rv = WSASend(iol->fd, pWsaData, num, &len, 0, NULL, NULL); - if (rv != SOCKET_ERROR) { - free(pWsaData); - return len; - } - else { - lasterror = WSAGetLastError(); - } - } while (rv == SOCKET_ERROR && lasterror == WSAEINTR); - - /* TEST CODE - * If lasterror ==WSATIMEDOUT, then the connection timed out - */ - if (rv == SOCKET_ERROR && lasterror == WSAETIMEDOUT) { - printf("wsarecv: Connection timed out\n"); - } else { - printf("Connection failed. lasterror = %d\n", lasterror); + free(pWsaData); + return lasterror; } - free(pWsaData); - return -1; -} -static const ap_iol_methods socket_methods = { - win32_close, - win32_send, - win32_writev, - win32_recv, - win32_setopt, - win32_getopt -}; -#elif defined(IOL_SOCK_ASYNC) + free(pWsaData); -static int win32_read(ap_iol *viol, const char *buf, int bufSize) -{ - int rc; - iol_socket *iol = (iol_socket *) viol; + *nbytes = dwBytesSent; - DWORD BytesRecvd; - DWORD flags; - WSAOVERLAPPED Overlapped; - WSABUF wsaBuf; - - wsaBuf.u_longlen = bufSize; - wsaBuf.buf = buf; - - Overlapped.Internal = ; - Overlapped.InternalHigh = ; - Overlapped.Offset = ; - Overlapped.OffsetHigh = ; - Overlapped.hEvent = CreateEvent(...); - - rc = WSARecv(iol->fd, - &wsaBuf, - (DWORD) 1, - &BytesRecvd, - &flags, - &Overlapped, - NULL); - if (rc == SOCKET_ERROR) { - if (WSAGetLastError() == WSA_IO_PENDING) { - rc = WSAWaitForMultipleEvents(1, // wait for 1 event - &Overlapped.hEvent, - TRUE, // wait for all events to be satisfied - (DWORD) iol->timeout, // timeout in milliseconds - FALSE); - if (rc == WSA_WAIT_FAILED) - } - else { - } - if (timeout - } - + return APR_SUCCESS; } - static const ap_iol_methods socket_methods = { win32_close, - win32_send, + win32_write, win32_writev, win32_recv, win32_setopt, win32_getopt }; - -#endif ap_iol *win32_attach_socket(ap_context_t *p, int fd) {