afd: separate out afd_poll implementation

This commit is contained in:
Bert Belder 2017-09-03 20:54:30 +02:00
parent d6cbb73f4e
commit d7d3a80bdd
3 changed files with 97 additions and 97 deletions

89
src/afd.c Normal file
View 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;
}
}

View File

@ -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_ */

View File

@ -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;
}
}