Windows: pass test-delayed-accept

This commit is contained in:
Bert Belder 2011-05-04 00:37:04 +02:00
parent 270078adef
commit 2b07bc34ce

132
oio-win.c
View File

@ -373,16 +373,20 @@ static oio_req* oio_overlapped_to_req(OVERLAPPED* overlapped) {
}
static int oio_set_socket_options(SOCKET socket) {
static int oio_tcp_init_socket(oio_handle* handle, oio_close_cb close_cb,
void* data, SOCKET socket) {
DWORD yes = 1;
/* Set the SO_REUSEADDR option on the socket */
/* If it fails, soit. */
0&&setsockopt(socket,
SOL_SOCKET,
SO_REUSEADDR,
(char*)&yes,
sizeof(int));
handle->socket = socket;
handle->close_cb = close_cb;
handle->data = data;
handle->type = OIO_TCP;
handle->flags = 0;
handle->reqs_pending = 0;
handle->error = oio_ok_;
handle->accept_socket = INVALID_SOCKET;
oio_req_init(&(handle->read_accept_req), handle, NULL);
/* Set the socket to nonblocking mode */
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
@ -390,7 +394,6 @@ static int oio_set_socket_options(SOCKET socket) {
return -1;
}
/* Make the socket non-inheritable */
if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
oio_set_sys_error(GetLastError());
@ -407,61 +410,27 @@ static int oio_set_socket_options(SOCKET socket) {
return -1;
}
oio_refs_++;
return 0;
}
int oio_tcp_init(oio_handle* handle, oio_close_cb close_cb,
void* data) {
handle->close_cb = close_cb;
handle->data = data;
handle->type = OIO_TCP;
handle->flags = 0;
handle->reqs_pending = 0;
handle->error = oio_ok_;
handle->accept_socket = INVALID_SOCKET;
SOCKET sock;
oio_req_init(&(handle->read_accept_req), handle, NULL);
handle->socket = socket(AF_INET, SOCK_STREAM, 0);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (handle->socket == INVALID_SOCKET) {
oio_set_sys_error(WSAGetLastError());
return -1;
}
if (oio_set_socket_options(handle->socket) != 0) {
closesocket(handle->socket);
if (oio_tcp_init_socket(handle, close_cb, data, sock) == -1) {
closesocket(sock);
return -1;
}
oio_refs_++;
return 0;
}
int oio_accept(oio_handle* server, oio_handle* client,
oio_close_cb close_cb, void* data) {
if (server->accept_socket == INVALID_SOCKET) {
oio_set_sys_error(WSAENOTCONN);
return -1;
}
client->close_cb = close_cb;
client->data = data;
client->type = OIO_TCP;
client->socket = server->accept_socket;
client->flags = 0;
client->reqs_pending = 0;
client->error = oio_ok_;
client->accept_socket = INVALID_SOCKET;
oio_req_init(&(client->read_accept_req), client, NULL);
oio_refs_++;
server->accept_socket = INVALID_SOCKET;
return 0;
}
@ -588,12 +557,6 @@ static void oio_queue_accept(oio_handle* handle) {
return;
}
if (oio_set_socket_options(accept_socket) != 0) {
closesocket(accept_socket);
oio_close_error(handle, oio_last_error_);
return;
}
/* Prepare the oio_req and OVERLAPPED structures. */
req = &handle->read_accept_req;
assert(!(req->flags & OIO_REQ_PENDING));
@ -690,6 +653,31 @@ int oio_listen(oio_handle* handle, int backlog, oio_accept_cb cb) {
}
int oio_accept(oio_handle* server, oio_handle* client,
oio_close_cb close_cb, void* data) {
int rv = 0;
if (server->accept_socket == INVALID_SOCKET) {
oio_set_sys_error(WSAENOTCONN);
return -1;
}
if (oio_tcp_init_socket(client, close_cb, data, server->accept_socket) == -1) {
oio_fatal_error(oio_last_error_.sys_errno_, "init");
closesocket(server->accept_socket);
rv = -1;
}
server->accept_socket = INVALID_SOCKET;
if (!(server->flags & OIO_HANDLE_CLOSING)) {
oio_queue_accept(server);
}
return rv;
}
int oio_read_start(oio_handle* handle, oio_read_cb cb) {
if (handle->flags & OIO_HANDLE_LISTENING ||
handle->flags & OIO_HANDLE_READING) {
@ -976,29 +964,23 @@ static void oio_poll() {
assert(handle->accept_socket != INVALID_SOCKET);
success = GetOverlappedResult(handle->handle, overlapped, &bytes, FALSE);
success = success && (setsockopt(handle->accept_socket,
SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT,
(char*)&handle->socket,
sizeof(handle->socket)) == 0);
if (success) {
if (setsockopt(handle->accept_socket,
SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT,
(char*)&handle->socket,
sizeof(handle->socket)) == 0) {
if (handle->accept_cb) {
((oio_accept_cb)handle->accept_cb)(handle);
}
if (handle->accept_cb) {
((oio_accept_cb)handle->accept_cb)(handle);
}
} else {
/* Errorneous accept is ignored if the listen socket is still healthy. */
closesocket(handle->accept_socket);
if (!(handle->flags & OIO_HANDLE_CLOSING)) {
oio_queue_accept(handle);
}
}
/* accept_cb should call oio_accept which sets handle->accept_socket */
/* to INVALID_SOCKET. */
/* Errorneous accept is ignored if the listen socket is still healthy. */
if (handle->accept_socket != INVALID_SOCKET) {
closesocket(handle->accept_socket);
handle->accept_socket = INVALID_SOCKET;
}
/* Queue another accept */
if (!(handle->flags & OIO_HANDLE_CLOSING))
oio_queue_accept(handle);
break;
case OIO_CONNECT: