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)
{