You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by st...@hyperreal.org on 1999/08/17 23:25:34 UTC
cvs commit: apache-2.0/mpm/src/os/win32 iol_socket.c
stoddard 99/08/17 14:25:32
Added: mpm/src/os/win32 iol_socket.c
Log:
WIN32 iol_socket.c.
Revision Changes Path
1.1 apache-2.0/mpm/src/os/win32/iol_socket.c
Index: iol_socket.c
===================================================================
/* ====================================================================
* Copyright (c) 1996-1999 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*
*/
#include "httpd.h"
#include "ap_iol.h"
#define FD_NONBLOCKING_SET (1)
//#define IOL_SOCK_POSIX // This works except for writev
#define IOL_SOCK_WIN32 // ANd this seems to be working as well, except for writev...
//#define IOL_SOCK_ASYNC
typedef struct {
ap_iol iol;
int fd;
int flags;
int timeout;
} iol_socket;
static int win32_setopt(ap_iol *viol, ap_iol_option opt, const void *value)
{
iol_socket *iol = (iol_socket *)viol;
switch (opt) {
case AP_IOL_TIMEOUT:
iol->timeout = *(const int *)value;
break;
default:
WSASetLastError(WSAEINVAL);
return -1;
}
return 0;
}
static int win32_getopt(ap_iol *viol, ap_iol_option opt, void *value)
{
iol_socket *iol = (iol_socket *)viol;
switch (opt) {
case AP_IOL_TIMEOUT:
*(int *)value = iol->timeout;
break;
default:
WSASetLastError(WSAEINVAL);
return -1;
}
return 0;
}
static int set_nonblock(int fd)
{
int iostate = 1;
ioctlsocket(fd, FIONBIO, &iostate);
return 0;
}
static int win32_close(ap_iol *viol)
{
iol_socket *iol = (iol_socket *)viol;
int rv;
rv = close(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)
#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 = 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;
}
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;
}
#elif defined(IOL_SOCK_ASYNC)
static int win32_read(ap_iol *viol, const char *buf, int bufSize)
{
int rc;
iol_socket *iol = (iol_socket *) viol;
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
}
}
#endif
static const ap_iol_methods socket_methods = {
win32_close,
win32_send,
NULL, //win32_writev,
win32_recv,
win32_setopt,
win32_getopt
};
ap_iol *win32_attach_socket(int fd)
{
iol_socket *iol;
iol = malloc(sizeof(iol_socket));
if (!iol)
return (ap_iol*) NULL;
iol->iol.methods = &socket_methods;
iol->fd = fd;
iol->timeout = -1;
iol->flags = 0;
return (ap_iol *)iol;
}