Windows: pass test-delayed-accept
This commit is contained in:
parent
270078adef
commit
2b07bc34ce
120
oio-win.c
120
oio-win.c
@ -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;
|
DWORD yes = 1;
|
||||||
|
|
||||||
/* Set the SO_REUSEADDR option on the socket */
|
handle->socket = socket;
|
||||||
/* If it fails, soit. */
|
handle->close_cb = close_cb;
|
||||||
0&&setsockopt(socket,
|
handle->data = data;
|
||||||
SOL_SOCKET,
|
handle->type = OIO_TCP;
|
||||||
SO_REUSEADDR,
|
handle->flags = 0;
|
||||||
(char*)&yes,
|
handle->reqs_pending = 0;
|
||||||
sizeof(int));
|
handle->error = oio_ok_;
|
||||||
|
handle->accept_socket = INVALID_SOCKET;
|
||||||
|
|
||||||
|
oio_req_init(&(handle->read_accept_req), handle, NULL);
|
||||||
|
|
||||||
/* Set the socket to nonblocking mode */
|
/* Set the socket to nonblocking mode */
|
||||||
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
|
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
|
||||||
@ -390,7 +394,6 @@ static int oio_set_socket_options(SOCKET socket) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Make the socket non-inheritable */
|
/* Make the socket non-inheritable */
|
||||||
if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
|
if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
|
||||||
oio_set_sys_error(GetLastError());
|
oio_set_sys_error(GetLastError());
|
||||||
@ -407,61 +410,27 @@ static int oio_set_socket_options(SOCKET socket) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oio_refs_++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int oio_tcp_init(oio_handle* handle, oio_close_cb close_cb,
|
int oio_tcp_init(oio_handle* handle, oio_close_cb close_cb,
|
||||||
void* data) {
|
void* data) {
|
||||||
handle->close_cb = close_cb;
|
SOCKET sock;
|
||||||
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);
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
handle->socket = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (handle->socket == INVALID_SOCKET) {
|
if (handle->socket == INVALID_SOCKET) {
|
||||||
oio_set_sys_error(WSAGetLastError());
|
oio_set_sys_error(WSAGetLastError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oio_set_socket_options(handle->socket) != 0) {
|
if (oio_tcp_init_socket(handle, close_cb, data, sock) == -1) {
|
||||||
closesocket(handle->socket);
|
closesocket(sock);
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,12 +557,6 @@ static void oio_queue_accept(oio_handle* handle) {
|
|||||||
return;
|
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. */
|
/* Prepare the oio_req and OVERLAPPED structures. */
|
||||||
req = &handle->read_accept_req;
|
req = &handle->read_accept_req;
|
||||||
assert(!(req->flags & OIO_REQ_PENDING));
|
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) {
|
int oio_read_start(oio_handle* handle, oio_read_cb cb) {
|
||||||
if (handle->flags & OIO_HANDLE_LISTENING ||
|
if (handle->flags & OIO_HANDLE_LISTENING ||
|
||||||
handle->flags & OIO_HANDLE_READING) {
|
handle->flags & OIO_HANDLE_READING) {
|
||||||
@ -976,29 +964,23 @@ static void oio_poll() {
|
|||||||
assert(handle->accept_socket != INVALID_SOCKET);
|
assert(handle->accept_socket != INVALID_SOCKET);
|
||||||
|
|
||||||
success = GetOverlappedResult(handle->handle, overlapped, &bytes, FALSE);
|
success = GetOverlappedResult(handle->handle, overlapped, &bytes, FALSE);
|
||||||
if (success) {
|
success = success && (setsockopt(handle->accept_socket,
|
||||||
if (setsockopt(handle->accept_socket,
|
|
||||||
SOL_SOCKET,
|
SOL_SOCKET,
|
||||||
SO_UPDATE_ACCEPT_CONTEXT,
|
SO_UPDATE_ACCEPT_CONTEXT,
|
||||||
(char*)&handle->socket,
|
(char*)&handle->socket,
|
||||||
sizeof(handle->socket)) == 0) {
|
sizeof(handle->socket)) == 0);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
if (handle->accept_cb) {
|
if (handle->accept_cb) {
|
||||||
((oio_accept_cb)handle->accept_cb)(handle);
|
((oio_accept_cb)handle->accept_cb)(handle);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
/* 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. */
|
/* Errorneous accept is ignored if the listen socket is still healthy. */
|
||||||
if (handle->accept_socket != INVALID_SOCKET) {
|
|
||||||
closesocket(handle->accept_socket);
|
closesocket(handle->accept_socket);
|
||||||
handle->accept_socket = INVALID_SOCKET;
|
if (!(handle->flags & OIO_HANDLE_CLOSING)) {
|
||||||
}
|
|
||||||
|
|
||||||
/* Queue another accept */
|
|
||||||
if (!(handle->flags & OIO_HANDLE_CLOSING))
|
|
||||||
oio_queue_accept(handle);
|
oio_queue_accept(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OIO_CONNECT:
|
case OIO_CONNECT:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user