diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c index 4be7a84..b9b578a 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c @@ -1,5 +1,8 @@ -#include "w32fd.h" +#include +#include +#include #include +#include "w32fd.h" static int getWSAErrno() @@ -24,14 +27,22 @@ static int getWSAErrno() return wsaerrno; } +static int set_errno_on_error(int ret) +{ + if (ret == SOCKET_ERROR) { + errno = getWSAErrno(); + } + return ret; +} + int socketio_initialize() { WSADATA wsaData = { 0 }; - int iResult = 0; - iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) { - wprintf(L"WSAStartup failed: %d\n", iResult); - return iResult; - } + return WSAStartup(MAKEWORD(2, 2), &wsaData); +} + +int socketio_done() { + WSACleanup(); + return 0; } struct w32_io* socketio_socket(int domain, int type, int protocol) { @@ -76,39 +87,122 @@ struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* a int socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen) { - return setsockopt(pio->sock, level, optname, optval, optlen); + return set_errno_on_error(setsockopt(pio->sock, level, optname, optval, optlen)); } int socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen) { - return getsockopt(pio->sock, level, optname, optval, optlen); + return set_errno_on_error(getsockopt(pio->sock, level, optname, optval, optlen)); } int socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen) { - return getsockname(pio->sock, name, namelen); + return set_errno_on_error(getsockname(pio->sock, name, namelen)); } int socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen) { - return 0; + return set_errno_on_error(getpeername(pio->sock, name, namelen)); } int socketio_listen(struct w32_io* pio, int backlog) { - return listen(pio->sock, backlog); + pio->type = LISTEN_FD; + return set_errno_on_error(listen(pio->sock, backlog)); } int socketio_bind(struct w32_io* pio, const struct sockaddr *name, int namelen) { - return bind(pio->sock, name, namelen); + return set_errno_on_error(bind(pio->sock, name, namelen)); } int socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen) { - return connect(pio->sock, name, namelen); + return set_errno_on_error(connect(pio->sock, name, namelen)); } int socketio_shutdown(struct w32_io* pio, int how) { - return shutdown(pio->sock, how); + return set_errno_on_error(shutdown(pio->sock, how)); } int socketio_close(struct w32_io* pio) { closesocket(pio->sock); //todo- wait for pending io to abort free(pio); + return 0; +} + +struct acceptEx_context { + char lpOutputBuf[1024]; + SOCKET accept_socket; + LPFN_ACCEPTEX lpfnAcceptEx; + DWORD bytes_received; +}; + +int socketio_start_asyncio(struct w32_io* pio, BOOL read) { + if (pio->type == LISTEN_FD) { + if (!pio->read_details.pending) { + struct acceptEx_context *context; + + if (pio->context == NULL) { + GUID GuidAcceptEx = WSAID_ACCEPTEX; + DWORD dwBytes; + + context = (struct acceptEx_context*)malloc(sizeof(struct acceptEx_context)); + if (context == NULL) { + errno = ENOMEM; + return -1; + } + + if (SOCKET_ERROR == WSAIoctl(pio->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, + &GuidAcceptEx, sizeof (GuidAcceptEx), + &context->lpfnAcceptEx, sizeof (context->lpfnAcceptEx), + &dwBytes, NULL, NULL)) + { + free(context); + errno = getWSAErrno(); + return -1; + } + + context->accept_socket = INVALID_SOCKET; + pio->context = context; + } + else + context = (struct acceptEx_context *)pio->context; + + //init overlapped event + if (pio->read_overlapped.hEvent == NULL) { + if ((pio->read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { + errno = ENOMEM; + return -1; + } + } + ResetEvent(pio->read_overlapped.hEvent); + + //create accepting socket + //todo - get socket parameters from listening socket + context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (context->accept_socket == INVALID_SOCKET) { + errno = getWSAErrno(); + return -1; + } + + if (FALSE == context->lpfnAcceptEx(pio->sock, + context->accept_socket, + context->lpOutputBuf, + 0, + sizeof(struct sockaddr_in) + 16, + sizeof(struct sockaddr_in) + 16, + &context->bytes_received, + &pio->read_overlapped)) + { + + errno = getWSAErrno(); + return -1; + } + + pio->read_details.pending = TRUE; + return 0; + } + else //io is already pending + return 0; + + } + else { //type == SOCK_FD + return -1; + } } \ No newline at end of file diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c index ba35ed8..ba61e0c 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c @@ -1,5 +1,6 @@ #include "w32posix.h" #include "w32fd.h" +#include struct w32fd_table { w32_fd_set occupied; @@ -56,6 +57,10 @@ void w32posix_initialize() { socketio_initialize(); } +void w32posix_done() { + socketio_done(); +} + BOOL w32_io_is_blocking(struct w32_io* pio) { return (pio->fd_status_flags & O_NONBLOCK) ? TRUE : FALSE; @@ -142,3 +147,22 @@ int w32_close(int fd) { return -1; } +int w32_fcntl(int fd, int cmd, ... /* arg */) { + va_list valist; + va_start(valist, cmd); + + switch (cmd){ + case F_GETFL: + return fd_table.w32_ios[fd]->fd_status_flags; + case F_SETFL: + fd_table.w32_ios[fd]->fd_status_flags = va_arg(valist, int); + return 0; + case F_GETFD: + return fd_table.w32_ios[fd]->fd_flags; + break; + case F_SETFD: + fd_table.w32_ios[fd]->fd_flags = va_arg(valist, int); + return 0; + } +} + diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h index 411d0b4..81aecce 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h @@ -47,6 +47,7 @@ int fd_table_add(struct w32_io*); int fd_table_delete(struct w32_io*); int socketio_initialize(); +int socketio_done(); struct w32_io* socketio_socket(int domain, int type, int protocol); struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen); int socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen); diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32posix.h b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32posix.h index 4b6fc7f..e3f5630 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32posix.h +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32posix.h @@ -6,9 +6,7 @@ #include //File Descriptor definitions -#if !defined(MAX_FDS) #define MAX_FDS 128 //a 2^n number -#endif typedef struct w32_fd_set_ { unsigned char bitmap[MAX_FDS >> 3]; @@ -43,6 +41,7 @@ typedef struct w32_fd_set_ { #define socket w32_socket void w32posix_initialize(); +void w32posix_done(); /*network i/o*/ #define socket w32_socket