afd: separate out afd_poll implementation
This commit is contained in:
parent
d6cbb73f4e
commit
d7d3a80bdd
89
src/afd.c
Normal file
89
src/afd.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include "afd.h"
|
||||
#include "error.h"
|
||||
#include "win.h"
|
||||
|
||||
int afd_poll(SOCKET socket, AFD_POLL_INFO* info, OVERLAPPED* overlapped) {
|
||||
IO_STATUS_BLOCK iosb;
|
||||
IO_STATUS_BLOCK* iosb_ptr;
|
||||
HANDLE event = NULL;
|
||||
void* apc_context;
|
||||
NTSTATUS status;
|
||||
DWORD error;
|
||||
|
||||
if (overlapped != NULL) {
|
||||
/* Overlapped operation. */
|
||||
iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal;
|
||||
event = overlapped->hEvent;
|
||||
|
||||
/* Do not report iocp completion if hEvent is tagged. */
|
||||
if ((uintptr_t) event & 1) {
|
||||
event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1);
|
||||
apc_context = NULL;
|
||||
} else {
|
||||
apc_context = overlapped;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Blocking operation. */
|
||||
iosb_ptr = &iosb;
|
||||
event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
if (event == NULL) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
apc_context = NULL;
|
||||
}
|
||||
|
||||
iosb_ptr->Status = STATUS_PENDING;
|
||||
status = NtDeviceIoControlFile((HANDLE) socket,
|
||||
event,
|
||||
NULL,
|
||||
apc_context,
|
||||
iosb_ptr,
|
||||
IOCTL_AFD_POLL,
|
||||
info,
|
||||
sizeof *info,
|
||||
info,
|
||||
sizeof *info);
|
||||
|
||||
if (overlapped == NULL) {
|
||||
/* If this is a blocking operation, wait for the event to become
|
||||
* signaled, and then grab the real status from the io status block.
|
||||
*/
|
||||
if (status == STATUS_PENDING) {
|
||||
DWORD r = WaitForSingleObject(event, INFINITE);
|
||||
|
||||
if (r == WAIT_FAILED) {
|
||||
DWORD saved_error = GetLastError();
|
||||
CloseHandle(event);
|
||||
WSASetLastError(saved_error);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
status = iosb_ptr->Status;
|
||||
}
|
||||
|
||||
CloseHandle(event);
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case STATUS_SUCCESS:
|
||||
error = ERROR_SUCCESS;
|
||||
break;
|
||||
|
||||
case STATUS_PENDING:
|
||||
error = WSA_IO_PENDING;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = we_map_ntstatus_to_winsock_error(status);
|
||||
break;
|
||||
}
|
||||
|
||||
WSASetLastError(error);
|
||||
|
||||
if (error == ERROR_SUCCESS) {
|
||||
return 0;
|
||||
} else {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
@ -4,10 +4,6 @@
|
||||
#include "nt.h"
|
||||
#include "win.h"
|
||||
|
||||
#ifndef SIO_BASE_HANDLE
|
||||
#define SIO_BASE_HANDLE 0x48000022
|
||||
#endif
|
||||
|
||||
#ifndef FILE_DEVICE_NETWORK
|
||||
#define FILE_DEVICE_NETWORK 0x00000012
|
||||
#endif
|
||||
@ -86,4 +82,6 @@ static const GUID AFD_PROVIDER_IDS[] = {
|
||||
0x43e4,
|
||||
{0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}}};
|
||||
|
||||
int afd_poll(SOCKET socket, AFD_POLL_INFO* info, OVERLAPPED* overlapped);
|
||||
|
||||
#endif /* EPOLL_AFD_H_ */
|
||||
|
||||
99
src/epoll.c
99
src/epoll.c
@ -10,6 +10,10 @@
|
||||
#include "tree.h"
|
||||
#include "win.h"
|
||||
|
||||
#ifndef SIO_BASE_HANDLE
|
||||
#define SIO_BASE_HANDLE 0x48000022
|
||||
#endif
|
||||
|
||||
#ifndef _SSIZE_T_DEFINED
|
||||
#define SSIZE_T_DEFINED
|
||||
typedef intptr_t ssize_t;
|
||||
@ -46,9 +50,6 @@ static int epoll__compare_sock_data(epoll_sock_data_t* a,
|
||||
epoll_sock_data_t* b);
|
||||
static int epoll__submit_poll_req(epoll_port_data_t* port_data,
|
||||
epoll_sock_data_t* sock_data);
|
||||
static int epoll__afd_poll(SOCKET socket,
|
||||
AFD_POLL_INFO* info,
|
||||
OVERLAPPED* overlapped);
|
||||
|
||||
static int epoll__initialized = 0;
|
||||
|
||||
@ -686,8 +687,8 @@ int epoll__submit_poll_req(epoll_port_data_t* port_data,
|
||||
io_req->poll_info.Handles[0].Status = 0;
|
||||
io_req->poll_info.Handles[0].Events = afd_events;
|
||||
|
||||
result = epoll__afd_poll(
|
||||
sock_data->peer_sock, &io_req->poll_info, &io_req->overlapped);
|
||||
result =
|
||||
afd_poll(sock_data->peer_sock, &io_req->poll_info, &io_req->overlapped);
|
||||
if (result != 0) {
|
||||
DWORD error = WSAGetLastError();
|
||||
if (error != WSA_IO_PENDING) {
|
||||
@ -705,91 +706,3 @@ int epoll__submit_poll_req(epoll_port_data_t* port_data,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epoll__afd_poll(SOCKET socket,
|
||||
AFD_POLL_INFO* info,
|
||||
OVERLAPPED* overlapped) {
|
||||
IO_STATUS_BLOCK iosb;
|
||||
IO_STATUS_BLOCK* iosb_ptr;
|
||||
HANDLE event = NULL;
|
||||
void* apc_context;
|
||||
NTSTATUS status;
|
||||
DWORD error;
|
||||
|
||||
if (overlapped != NULL) {
|
||||
/* Overlapped operation. */
|
||||
iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal;
|
||||
event = overlapped->hEvent;
|
||||
|
||||
/* Do not report iocp completion if hEvent is tagged. */
|
||||
if ((uintptr_t) event & 1) {
|
||||
event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1);
|
||||
apc_context = NULL;
|
||||
} else {
|
||||
apc_context = overlapped;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Blocking operation. */
|
||||
iosb_ptr = &iosb;
|
||||
event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
if (event == NULL) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
apc_context = NULL;
|
||||
}
|
||||
|
||||
iosb_ptr->Status = STATUS_PENDING;
|
||||
status = NtDeviceIoControlFile((HANDLE) socket,
|
||||
event,
|
||||
NULL,
|
||||
apc_context,
|
||||
iosb_ptr,
|
||||
IOCTL_AFD_POLL,
|
||||
info,
|
||||
sizeof *info,
|
||||
info,
|
||||
sizeof *info);
|
||||
|
||||
if (overlapped == NULL) {
|
||||
/* If this is a blocking operation, wait for the event to become
|
||||
* signaled, and then grab the real status from the io status block.
|
||||
*/
|
||||
if (status == STATUS_PENDING) {
|
||||
DWORD r = WaitForSingleObject(event, INFINITE);
|
||||
|
||||
if (r == WAIT_FAILED) {
|
||||
DWORD saved_error = GetLastError();
|
||||
CloseHandle(event);
|
||||
WSASetLastError(saved_error);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
status = iosb_ptr->Status;
|
||||
}
|
||||
|
||||
CloseHandle(event);
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case STATUS_SUCCESS:
|
||||
error = ERROR_SUCCESS;
|
||||
break;
|
||||
|
||||
case STATUS_PENDING:
|
||||
error = WSA_IO_PENDING;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = we_map_ntstatus_to_winsock_error(status);
|
||||
break;
|
||||
}
|
||||
|
||||
WSASetLastError(error);
|
||||
|
||||
if (error == ERROR_SUCCESS) {
|
||||
return 0;
|
||||
} else {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user