From bc0a24539dbe74f8970e2216e5f1dbf02da61f7b Mon Sep 17 00:00:00 2001 From: Manoj Ampalam Date: Wed, 2 Mar 2016 13:47:39 -0800 Subject: [PATCH] 3-2 C1 --- .../win32posix/UnitTests/UnitTests.vcxproj | 15 ++ .../win32posix/UnitTests/socket_tests.c | 32 ++-- .../win32posix/UnitTests/test_helper.c | 8 +- .../win32posix/win32posix/debug.c | 4 +- .../win32posix/win32posix/inc/fcntl.h | 1 + .../win32posix/win32posix/socketio.c | 149 +++++++++--------- .../win32posix/win32posix/w32fd.c | 65 ++++++-- .../win32posix/win32posix/w32fd.h | 30 ++-- .../win32posix/win32posix/win32posix.vcxproj | 11 +- .../win32posix/win32posix.vcxproj.filters | 3 + 10 files changed, 200 insertions(+), 118 deletions(-) create mode 100644 contrib/win32/w32-posix-prototype/win32posix/win32posix/inc/fcntl.h diff --git a/contrib/win32/w32-posix-prototype/win32posix/UnitTests/UnitTests.vcxproj b/contrib/win32/w32-posix-prototype/win32posix/UnitTests/UnitTests.vcxproj index 14c2746..6c1195f 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/UnitTests/UnitTests.vcxproj +++ b/contrib/win32/w32-posix-prototype/win32posix/UnitTests/UnitTests.vcxproj @@ -77,12 +77,21 @@ true + $(SolutionDir)\win32posix\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)bin\unittests\$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ false + $(SolutionDir)\win32posix\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)bin\unittests\$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ false + $(SolutionDir)\win32posix\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)bin\unittests\$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ @@ -112,6 +121,8 @@ Console true + Ws2_32.lib;win32posix.lib;%(AdditionalDependencies) + $(SolutionDir)bin\lib\$(Platform)\$(Configuration)\ @@ -129,6 +140,8 @@ true true true + Ws2_32.lib;win32posix.lib;%(AdditionalDependencies) + $(SolutionDir)bin\lib\$(Platform)\$(Configuration)\ @@ -146,6 +159,8 @@ true true true + Ws2_32.lib;win32posix.lib;%(AdditionalDependencies) + $(SolutionDir)bin\lib\$(Platform)\$(Configuration)\ diff --git a/contrib/win32/w32-posix-prototype/win32posix/UnitTests/socket_tests.c b/contrib/win32/w32-posix-prototype/win32posix/UnitTests/socket_tests.c index f29bbc2..1f5dc83 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/UnitTests/socket_tests.c +++ b/contrib/win32/w32-posix-prototype/win32posix/UnitTests/socket_tests.c @@ -8,11 +8,14 @@ #define BACKLOG 2 #define SMALL_RECV_BUF_SIZE 128 +#pragma warning(disable:4267) + int listen_fd, accept_fd, connect_fd, ret; struct addrinfo hints, *servinfo; fd_set read_set, write_set, except_set; struct timeval time_val; struct sockaddr_storage their_addr; +int their_addr_len = sizeof(their_addr); char *send_buf, *recv_buf; int @@ -121,7 +124,7 @@ void socket_fd_tests() ASSERT_INT_EQ(errno, EBADF); ASSERT_INT_EQ(isatty(12), -1); ASSERT_INT_EQ(errno, EBADF); - ASSERT_INT_EQ(fdopen(13, NULL), -1); + ASSERT_PTR_EQ(fdopen(13, NULL), NULL); ASSERT_INT_EQ(errno, EBADF); ASSERT_INT_EQ(close(14), -1); ASSERT_INT_EQ(errno, EBADF); @@ -141,6 +144,16 @@ void socket_fd_tests() ASSERT_INT_EQ(errno, EBADF); TEST_DONE(); + TEST_START("socket failures"); + ASSERT_INT_EQ(setsockopt(0, 0, SO_RCVTIMEO, NULL, 0), -1); + ASSERT_INT_EQ(errno, ENOTSOCK); + connect_fd = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + ASSERT_INT_NE(connect_fd, -1); + ASSERT_INT_EQ(setsockopt(connect_fd, 0, SO_RCVTIMEO, NULL, 0), -1); + ASSERT_INT_EQ(errno, ENOTSUP); + close(connect_fd); + TEST_DONE(); + TEST_START("min fd allocation"); connect_fd = socket(AF_INET, SOCK_STREAM, 0); ASSERT_INT_EQ(connect_fd, 3); @@ -177,7 +190,8 @@ void socket_blocking_io_tests() ret = connect(connect_fd, servinfo->ai_addr, servinfo->ai_addrlen); ASSERT_INT_EQ(ret, 0); //call connect again?? - accept_fd = accept(listen_fd, (struct sockaddr*)&their_addr, sizeof(their_addr)); + their_addr_len = sizeof(their_addr); + accept_fd = accept(listen_fd, (struct sockaddr*)&their_addr, &their_addr_len); ASSERT_INT_NE(accept_fd, -1); ret = close(listen_fd); ASSERT_INT_EQ(ret, 0); @@ -288,7 +302,7 @@ void socket_nonblocking_io_tests() TEST_START("non blocking accept and connect"); ret = set_nonblock(listen_fd); ASSERT_INT_EQ(ret, 0); - accept_fd = accept(listen_fd, (struct sockaddr*)&their_addr, sizeof(their_addr)); + accept_fd = accept(listen_fd, NULL, NULL); ASSERT_INT_EQ(accept_fd, -1); ASSERT_INT_EQ(errno, EAGAIN); ret = set_nonblock(connect_fd); @@ -300,7 +314,7 @@ void socket_nonblocking_io_tests() ASSERT_INT_EQ(ret, 0); ret = unset_nonblock(listen_fd); ASSERT_INT_EQ(ret, 0); - accept_fd = accept(listen_fd, (struct sockaddr*)&their_addr, sizeof(their_addr)); + accept_fd = accept(listen_fd, NULL, NULL); ASSERT_INT_NE(accept_fd, -1); ret = close(listen_fd); ASSERT_INT_EQ(ret, 0); @@ -357,7 +371,7 @@ void prep_input_buffer(char* buf, int size, int seed) } void socket_select_tests() { - int s, r, i; + int s, r; int num_bytes = 1024 * 700; //700KB int bytes_sent = 0; int bytes_received = 0; @@ -388,7 +402,7 @@ void socket_select_tests() { ret = select(listen_fd + 1, &read_set, NULL, NULL, &time_val); ASSERT_INT_NE(ret, -1); ASSERT_INT_EQ(FD_ISSET(listen_fd, &read_set), 1); - accept_fd = accept(listen_fd, (struct sockaddr*)&their_addr, sizeof(their_addr)); + accept_fd = accept(listen_fd, NULL, NULL); ASSERT_INT_NE(accept_fd, -1); ret = close(listen_fd); ASSERT_INT_EQ(ret, 0); @@ -456,7 +470,7 @@ void socket_select_tests() { } void socket_typical_ssh_payload_tests() { - int s, r, i; + int s, r; int max_bytes = 1024 * 700; //700KB int max_packetsize = 1024 * 5, bytes_sent = 0; int packets_sent = 0; @@ -479,7 +493,7 @@ void socket_typical_ssh_payload_tests() { ASSERT_INT_NE(connect_fd, -1); ret = connect(connect_fd, servinfo->ai_addr, servinfo->ai_addrlen); ASSERT_INT_EQ(ret, 0); - accept_fd = accept(listen_fd, (struct sockaddr*)&their_addr, sizeof(their_addr)); + accept_fd = accept(listen_fd, NULL, NULL); ASSERT_INT_NE(accept_fd, -1); ret = close(listen_fd); ASSERT_INT_EQ(ret, 0); @@ -514,7 +528,7 @@ void socket_typical_ssh_payload_tests() { ASSERT_INT_EQ(errno, EAGAIN); } else if (bytes_sent < max_bytes) { - send_packet_remaining = ((double)rand() / (RAND_MAX + 1)) * (max_packetsize - 100) + 100; + send_packet_remaining = (rand()*(max_packetsize - 100)/RAND_MAX) + 100; ret = send(s, &send_packet_remaining, 4, 0); if (ret == -1) { send_packet_remaining = 0; //we'll try again when io is ready diff --git a/contrib/win32/w32-posix-prototype/win32posix/UnitTests/test_helper.c b/contrib/win32/w32-posix-prototype/win32posix/UnitTests/test_helper.c index ebe3149..6d31019 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/UnitTests/test_helper.c +++ b/contrib/win32/w32-posix-prototype/win32posix/UnitTests/test_helper.c @@ -125,7 +125,7 @@ void debug3(const char *fmt,...) {/*stub*/} int main(int argc, char **argv) { - int ch; + //int ch; __progname = NULL; /* Handle systems without __progname */ if (__progname == NULL) { @@ -134,7 +134,7 @@ main(int argc, char **argv) __progname = argv[0]; else __progname++; - if ((__progname = strdup(__progname)) == NULL) { + if ((__progname = _strdup(__progname)) == NULL) { fprintf(stderr, "strdup failed\n"); exit(1); } @@ -215,7 +215,7 @@ void test_start(const char *n) { assert(active_test_name == NULL); - assert((active_test_name = strdup(n)) != NULL); + assert((active_test_name = _strdup(n)) != NULL); *subtest_info = '\0'; if (verbose_mode) printf("test %u - \"%s\": ", test_number, active_test_name); @@ -465,7 +465,7 @@ void assert_char(const char *file, int line, const char *a1, const char *a2, char aa1, char aa2, enum test_predicate pred) { - char buf[8]; + //char buf[8]; TEST_CHECK(aa1, aa2, pred); test_header(file, line, a1, a2, "CHAR", pred); diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.c index 12bc5b9..ca00879 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.c @@ -13,9 +13,9 @@ int debug_initialize() { len = GetModuleFileNameA(NULL, filename, MAX_PATH); GetLocalTime(&time); - sprintf(filename + len, "_%d_%d_%d.log", time.wHour, time.wMinute, time.wSecond); + sprintf_s(filename + len, MAX_PATH-len, "_%d_%d_%d.log", time.wHour, time.wMinute, time.wSecond); //sprintf(filename, "%s", "e:\\tmp.log"); - log = fopen(filename, "w"); + fopen_s(&log, filename, "w"); return 0; } diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/inc/fcntl.h b/contrib/win32/w32-posix-prototype/win32posix/win32posix/inc/fcntl.h new file mode 100644 index 0000000..149332c --- /dev/null +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/inc/fcntl.h @@ -0,0 +1 @@ +#include "..\w32posix.h" \ No newline at end of file diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c index 973fb94..8ffa760 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c @@ -48,7 +48,8 @@ struct acceptEx_context { int socketio_acceptEx(struct w32_io* pio) { struct acceptEx_context *context; - if (pio->context == NULL) { + debug2("io:%p", pio); + if (pio->internal.context == NULL) { GUID GuidAcceptEx = WSAID_ACCEPTEX; DWORD dwBytes; @@ -58,7 +59,7 @@ int socketio_acceptEx(struct w32_io* pio) { debug("ERROR:%d, io:%p", errno, pio); return -1; } - + memset(context, 0, sizeof(struct acceptEx_context)); if (SOCKET_ERROR == WSAIoctl(pio->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof(GuidAcceptEx), &context->lpfnAcceptEx, sizeof(context->lpfnAcceptEx), @@ -71,10 +72,10 @@ int socketio_acceptEx(struct w32_io* pio) { } context->accept_socket = INVALID_SOCKET; - pio->context = context; + pio->internal.context = context; } else - context = (struct acceptEx_context *)pio->context; + context = (struct acceptEx_context *)pio->internal.context; //init overlapped event if (pio->read_overlapped.hEvent == NULL) { @@ -87,7 +88,6 @@ int socketio_acceptEx(struct w32_io* pio) { ResetEvent(pio->read_overlapped.hEvent); //create accepting socket - //todo - get socket parameters from listening socket context->accept_socket = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); if (context->accept_socket == INVALID_SOCKET) { errno = errno_from_WSALastError(); @@ -143,6 +143,7 @@ int socketio_WSARecv(struct w32_io* pio, BOOL* completed) { WSABUF wsabuf; DWORD recv_flags = 0; + debug2("pio: %p", pio); if (completed) *completed = FALSE; @@ -184,7 +185,7 @@ int socketio_WSARecv(struct w32_io* pio, BOOL* completed) { } else { //failed errno = errno_from_WSALastError(); - debug("ERROR: io:%p %d", pio, errno); + debug("ERROR: io:%p %d", pio, errno); return -1; } } @@ -209,7 +210,7 @@ struct w32_io* socketio_socket(int domain, int type, int protocol) { return NULL; } - pio->type = SOCK_FD; + pio->internal.state = SOCK_INITIALIZED; return pio; } @@ -223,8 +224,13 @@ struct w32_io* socketio_socket(int domain, int type, int protocol) { } while (0) int socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen) { - //TODO: unsupport SO_RCVTIMEO - SET_ERRNO_ON_ERROR(setsockopt(pio->sock, level, optname, optval, optlen)); + if ( (optname == SO_KEEPALIVE) || (optname == SO_REUSEADDR) || (optname == TCP_NODELAY) || (optname == IPV6_V6ONLY) ) + SET_ERRNO_ON_ERROR(setsockopt(pio->sock, level, optname, optval, optlen)); + else { + debug("ERROR: unsupported optname:%d io:%p", optname, pio); + errno = ENOTSUP; + return -1; + } } int socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen) { @@ -240,12 +246,17 @@ int socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen } int socketio_listen(struct w32_io* pio, int backlog) { - pio->type = LISTEN_FD; - SET_ERRNO_ON_ERROR(listen(pio->sock, backlog)); + if (SOCKET_ERROR == listen(pio->sock, backlog)) { + errno = errno_from_WSALastError(); + debug("ERROR:%d io:%p", errno, pio); + return -1; + } + pio->internal.state = SOCK_LISTENING; + return 0; } int socketio_bind(struct w32_io* pio, const struct sockaddr *name, int namelen) { - SET_ERRNO_ON_ERROR(bind(pio->sock, name, namelen)); + SET_ERRNO_ON_ERROR(bind(pio->sock, name, namelen)); } int socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) { @@ -268,7 +279,7 @@ int socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) { //if io is already pending if (pio->read_details.pending) { //if recv is now in blocking mode, wait for data to be available - if (w32_io_is_blocking(pio)) { + if (w32_io_is_blocking(pio)) { debug2("socket was previously non-blocing but now in blocking mode, waiting for io"); while (socketio_is_io_available(pio, TRUE) == FALSE) { if (0 != wait_for_any_event(NULL, 0, INFINITE)) @@ -285,7 +296,7 @@ int socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) { //if we have some buffer copy it and return #bytes copied if (pio->read_details.remaining) { - int num_bytes_copied = min(len, pio->read_details.remaining); + int num_bytes_copied = min((int)len, pio->read_details.remaining); memcpy(buf, pio->read_details.buf + pio->read_details.completed, num_bytes_copied); pio->read_details.remaining -= num_bytes_copied; pio->read_details.completed += num_bytes_copied; @@ -358,7 +369,7 @@ int socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) { } if (pio->read_details.remaining) { - int num_bytes_copied = min(len, pio->read_details.remaining); + int num_bytes_copied = min((int)len, pio->read_details.remaining); memcpy(buf, pio->read_details.buf, num_bytes_copied); pio->read_details.remaining -= num_bytes_copied; pio->read_details.completed = num_bytes_copied; @@ -453,7 +464,7 @@ int socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) { wsabuf.buf = pio->write_details.buf; } - wsabuf.len = min(wsabuf.len, len); + wsabuf.len = min(wsabuf.len, (int)len); memcpy(wsabuf.buf, buf, wsabuf.len); //implement flags support if needed @@ -514,22 +525,22 @@ int socketio_close(struct w32_io* pio) { SleepEx(0, TRUE); if (pio->read_details.pending || pio->write_details.pending) debug2("IO is still pending on closed socket. read:%d, write:%d, io:%p", pio->read_details.pending, pio->write_details.pending, pio); - if (pio->type == LISTEN_FD) { + if (pio->internal.state == SOCK_LISTENING) { if (pio->read_overlapped.hEvent) CloseHandle(pio->read_overlapped.hEvent); - if (pio->context) + if (pio->internal.context) { - struct acceptEx_context *ctx = (struct acceptEx_context*)pio->context; + struct acceptEx_context *ctx = (struct acceptEx_context*)pio->internal.context; if (ctx->accept_socket != INVALID_SOCKET) closesocket(ctx->accept_socket); if (ctx->lpOutputBuf) free(ctx->lpOutputBuf); - //TODO: Fix this. Freeing this is crashing - //free(pio->context); + //TODO: check why this is crashing + //free(pio->internal.context); } - + } - else if (pio->type == CONNECT_FD) { + else if (pio->internal.state == SOCK_CONNECTING) { if (pio->write_overlapped.hEvent) CloseHandle(pio->write_overlapped.hEvent); } @@ -578,7 +589,7 @@ struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* a } - context = (struct acceptEx_context*)pio->context; + context = (struct acceptEx_context*)pio->internal.context; pio->read_details.pending = FALSE; ResetEvent(pio->read_overlapped.hEvent); @@ -606,7 +617,7 @@ struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* a memset(accept_io, 0, sizeof(struct w32_io)); accept_io->sock = context->accept_socket; - accept_io->type = SOCK_FD; + accept_io->internal.state = SOCK_ACCEPTED; context->accept_socket = INVALID_SOCKET; debug2("accept io:%p", accept_io); @@ -632,27 +643,27 @@ int socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int name GUID connectex_guid = WSAID_CONNECTEX; LPFN_CONNECTEX ConnectEx; - if (name->sa_family == AF_INET6) { + if (name->sa_family == AF_INET6) { ZeroMemory(&tmp_addr6, sizeof(tmp_addr6)); tmp_addr6.sin6_family = AF_INET6; tmp_addr6.sin6_port = 0; tmp_addr = (SOCKADDR*)&tmp_addr6; tmp_addr_len = sizeof(tmp_addr6); - } - else if (name->sa_family == AF_INET) { + } + else if (name->sa_family == AF_INET) { ZeroMemory(&tmp_addr4, sizeof(tmp_addr4)); tmp_addr4.sin_family = AF_INET; tmp_addr4.sin_port = 0; tmp_addr = (SOCKADDR*)&tmp_addr4; tmp_addr_len = sizeof(tmp_addr4); } - else { + else { errno = ENOTSUP; debug("ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio); return -1; } - - if (SOCKET_ERROR == bind(pio->sock, tmp_addr, tmp_addr_len)) + + if (SOCKET_ERROR == bind(pio->sock, tmp_addr, (int)tmp_addr_len)) { errno = errno_from_WSALastError(); debug("ERROR: bind failed :%d, io:%p", errno, pio); @@ -669,15 +680,16 @@ int socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int name return -1; } - if ((pio->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { + if ((!pio->write_overlapped.hEvent) && ((pio->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)) { errno = ENOMEM; debug("ERROR:%d, io:%p", errno, pio); return -1; } + ResetEvent(pio->write_overlapped.hEvent); if (TRUE == ConnectEx(pio->sock, name, namelen, NULL, 0, NULL, &pio->write_overlapped)) { - //set completion event + //set completion event that indicates to other routines that async connect has completed SetEvent(pio->write_overlapped.hEvent); } else @@ -693,12 +705,11 @@ int socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int name } pio->write_details.pending = TRUE; - pio->type = CONNECT_FD; + pio->internal.state = SOCK_CONNECTING; return 0; } int socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen) { - //SET_ERRNO_ON_ERROR(connect(pio->sock, name, namelen)); if (pio->write_details.pending == FALSE) { @@ -726,9 +737,6 @@ int socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namele } - //close event handle - CloseHandle(pio->write_overlapped.hEvent); - if (pio->write_details.error) { errno = errno_from_WSAError(pio->write_details.error); debug("ERROR: async io completed with error: %d, io:%p", errno, pio); @@ -743,26 +751,28 @@ int socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namele } //Reset any state used during connect + //close event handle + CloseHandle(pio->write_overlapped.hEvent); ZeroMemory(&pio->write_details, sizeof(pio->write_details)); - pio->type = SOCK_FD; + pio->internal.state = SOCK_CONNECTED; return 0; } BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd) { - struct acceptEx_context* context = (struct acceptEx_context*)pio->context; - if ((pio->type == LISTEN_FD) || (pio->type == CONNECT_FD)) { + if ((pio->internal.state == SOCK_LISTENING) || (pio->internal.state == SOCK_CONNECTING)) { DWORD numBytes = 0; DWORD flags; - OVERLAPPED *overlapped = (pio->type == LISTEN_FD) ? &pio->read_overlapped : &pio->write_overlapped; - BOOL pending = (pio->type == LISTEN_FD) ? pio->read_details.pending : pio->write_details.pending; + BOOL sock_listening = (pio->internal.state == SOCK_LISTENING); + OVERLAPPED *overlapped = sock_listening ? &pio->read_overlapped : &pio->write_overlapped; + BOOL pending = sock_listening ? pio->read_details.pending : pio->write_details.pending; if (pending && WSAGetOverlappedResult(pio->sock, overlapped, &numBytes, FALSE, &flags)) { return TRUE; } else { if (pending && WSAGetLastError() != WSA_IO_INCOMPLETE) { - if (pio->type == LISTEN_FD) + if (sock_listening) pio->read_details.error = WSAGetLastError(); else pio->write_details.error = WSAGetLastError(); @@ -782,40 +792,27 @@ BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd) { } } - +/*start async io (if needed) for accept and recv*/ int socketio_on_select(struct w32_io* pio, BOOL rd) { + enum w32_io_sock_state sock_state = pio->internal.state; + debug2("io:%p type:%d rd:%d", pio, pio->type, rd); + + //nothing to do for writes (that includes connect) + if (!rd) + return 0; + + //listening socket - acceptEx if needed + if ((sock_state == SOCK_LISTENING) + && (!pio->read_details.pending) + && (socketio_acceptEx(pio) != 0)) + return -1; + //connected socket - WSARecv if needed + else if ((!pio->read_details.pending) + && (!socketio_is_io_available(pio, rd)) + && (socketio_WSARecv(pio, NULL) != 0)) + return -1; - //return if io is already available - if (socketio_is_io_available(pio, rd)) - return 0; - - //return if io is pending - if (rd && pio->read_details.pending) - return 0; - - if (!rd && pio->write_details.pending) - return 0; - - //TODO - do this on rd = TRUE - if (pio->type == LISTEN_FD) { - if (socketio_acceptEx(pio) != 0) - return -1; - return 0; - } - //TODO - do this only on rd = FALSE - else if (pio->type == CONNECT_FD) { - //nothing to do for connect - return 0; - } - else if (rd) { - if (socketio_WSARecv(pio, NULL) != 0) - return -1; - return 0; - } - else { - //nothing to start for write - return 0; - } + return 0; } \ 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 5f9b04f..ef95a03 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c @@ -3,6 +3,7 @@ #include #include #include +#include struct w32fd_table { w32_fd_set occupied; @@ -13,16 +14,20 @@ struct w32fd_table fd_table; struct w32_io w32_io_stdin, w32_io_stdout, w32_io_stderr; void fd_table_set(struct w32_io* pio, int index); +#pragma warning(disable:4312) int fd_table_initialize() { memset(&fd_table, 0, sizeof(fd_table)); memset(&w32_io_stdin, 0, sizeof(w32_io_stdin)); w32_io_stdin.handle = (HANDLE)STD_INPUT_HANDLE; + w32_io_stdin.type = STD_IO_FD; fd_table_set(&w32_io_stdin, STDIN_FILENO); memset(&w32_io_stdout, 0, sizeof(w32_io_stdout)); w32_io_stdout.handle = (HANDLE)STD_OUTPUT_HANDLE; + w32_io_stdout.type = STD_IO_FD; fd_table_set(&w32_io_stdout, STDOUT_FILENO); memset(&w32_io_stderr, 0, sizeof(w32_io_stderr)); w32_io_stderr.handle = (HANDLE)STD_ERROR_HANDLE; + w32_io_stderr.type = STD_IO_FD; fd_table_set(&w32_io_stderr, STDERR_FILENO); return 0; } @@ -57,6 +62,7 @@ static int fd_table_get_min_index() { static void fd_table_set(struct w32_io* pio, int index) { fd_table.w32_ios[index] = pio; pio->table_index = index; + assert(pio->type != UNKNOWN_FD); FD_SET(index, &(fd_table.occupied)); } @@ -85,7 +91,7 @@ BOOL w32_io_is_blocking(struct w32_io* pio) } BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd) { - if (pio->type <= SOCK_FD) { + if (pio->type == SOCK_FD) { return socketio_is_io_available(pio, rd); } else { @@ -96,7 +102,7 @@ BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd) { int w32_io_on_select(struct w32_io* pio, BOOL rd) { - if ((pio->type <= SOCK_FD)) { + if ((pio->type == SOCK_FD)) { return socketio_on_select(pio, rd); } else { @@ -109,11 +115,19 @@ int w32_io_on_select(struct w32_io* pio, BOOL rd) errno = 0; \ if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { \ errno = EBADF; \ - debug("bad fd: %d", fd); \ + debug("ERROR: bad fd: %d", fd); \ return -1; \ } \ } while (0) +#define CHECK_SOCK_IO(pio) do { \ + errno = 0; \ + if (pio->type != SOCK_FD) { \ + errno = ENOTSOCK; \ + debug("ERROR: non sock fd type:%d", pio->type); \ + return -1; \ + } \ +} while (0) int w32_socket(int domain, int type, int protocol) { int min_index = fd_table_get_min_index(); @@ -128,6 +142,7 @@ int w32_socket(int domain, int type, int protocol) { return -1; } + pio->type = SOCK_FD; fd_table_set(pio, min_index); debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index); return min_index; @@ -137,6 +152,7 @@ int w32_accept(int fd, struct sockaddr* addr, int* addrlen) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); int min_index = fd_table_get_min_index(); struct w32_io* pio = NULL; @@ -148,6 +164,7 @@ int w32_accept(int fd, struct sockaddr* addr, int* addrlen) return -1; } + pio->type = SOCK_FD; fd_table_set(pio, min_index); debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index); return min_index; @@ -156,54 +173,63 @@ int w32_accept(int fd, struct sockaddr* addr, int* addrlen) int w32_setsockopt(int fd, int level, int optname, const char* optval, int optlen) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_setsockopt(fd_table.w32_ios[fd], level, optname, optval, optlen); } int w32_getsockopt(int fd, int level, int optname, char* optval, int* optlen) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_getsockopt(fd_table.w32_ios[fd], level, optname, optval, optlen); } int w32_getsockname(int fd, struct sockaddr* name, int* namelen) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_getsockname(fd_table.w32_ios[fd], name, namelen); } int w32_getpeername(int fd, struct sockaddr* name, int* namelen) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_getpeername(fd_table.w32_ios[fd], name, namelen); } int w32_listen(int fd, int backlog) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_listen(fd_table.w32_ios[fd], backlog); } int w32_bind(int fd, const struct sockaddr *name, int namelen) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_bind(fd_table.w32_ios[fd], name, namelen); } int w32_connect(int fd, const struct sockaddr* name, int namelen) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_connect(fd_table.w32_ios[fd], name, namelen); } int w32_recv(int fd, void *buf, size_t len, int flags) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_recv(fd_table.w32_ios[fd], buf, len, flags); } int w32_send(int fd, const void *buf, size_t len, int flags) { debug3("fd:%d", fd); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_send(fd_table.w32_ios[fd], buf, len, flags); } @@ -211,6 +237,7 @@ int w32_send(int fd, const void *buf, size_t len, int flags) { int w32_shutdown(int fd, int how) { debug3("fd:%d how:%d", fd, how); CHECK_FD(fd); + CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_shutdown(fd_table.w32_ios[fd], how); } @@ -235,6 +262,8 @@ int w32_pipe(int *pfds){ if (-1 == fileio_pipe(pio)) return -1; + pio[0]->type = PIPE_FD; + pio[1]->type = PIPE_FD; fd_table_set(pio[0], read_index); fd_table_set(pio[1], write_index); pfds[0] = read_index; @@ -256,6 +285,7 @@ int w32_open(const char *pathname, int flags, ...) { if (pio == NULL) return -1; + pio->type = FILE_FD; fd_table_set(pio, min_index); debug("handle:%p, io:%p, fd:%d", pio->handle, pio, min_index); return min_index; @@ -286,7 +316,12 @@ int w32_isatty(int fd) { } FILE* w32_fdopen(int fd, const char *mode) { - CHECK_FD(fd); + errno = 0; + if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { + errno = EBADF; + debug("bad fd: %d", fd); + return NULL; + } return fileio_fdopen(fd_table.w32_ios[fd], mode); } @@ -300,7 +335,7 @@ int w32_close(int fd) { debug("io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd, pio->table_index); fd_table_clear(pio->table_index); - if ((pio->type == LISTEN_FD) || (pio->type == CONNECT_FD) || (pio->type == SOCK_FD)) { + if ((pio->type == SOCK_FD)) { return socketio_close(pio); } else @@ -333,7 +368,7 @@ int w32_fcntl(int fd, int cmd, ... /* arg */) { } int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval *timeout) { - int in_ready_fds = 0, out_ready_fds = 0, i; + int in_set_fds = 0, out_ready_fds = 0, i; fd_set read_ready_fds, write_ready_fds; HANDLE events[32]; int num_events = 0; @@ -366,7 +401,7 @@ int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, co for (i = 0; i < fds; i++) if (FD_ISSET(i, readfds)) { CHECK_FD(i); - in_ready_fds++; + in_set_fds++; } } @@ -374,25 +409,25 @@ int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, co for (i = 0; i < fds; i++) if (FD_ISSET(i, writefds)) { CHECK_FD(i); - in_ready_fds; + in_set_fds++; } } //if none of input fds are set return error - if (in_ready_fds == 0) { + if (in_set_fds == 0) { errno = EINVAL; debug("ERROR: empty fd_sets"); return -1; } - + debug2("Total in fds:%d", in_set_fds); //start async io on selected fds if needed and pick up any events that select needs to listen on for (int i = 0; i < fds; i++) { if (readfds && FD_ISSET(i, readfds)) { if (w32_io_on_select(fd_table.w32_ios[i], TRUE) == -1) return -1; - if (fd_table.w32_ios[i]->type == LISTEN_FD) { + if ((fd_table.w32_ios[i]->type == SOCK_FD) && (fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) { events[num_events++] = fd_table.w32_ios[i]->read_overlapped.hEvent; } } @@ -400,7 +435,7 @@ int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, co if (writefds && FD_ISSET(i, writefds)) { if (w32_io_on_select(fd_table.w32_ios[i], FALSE) == -1) return -1; - if (fd_table.w32_ios[i]->type == CONNECT_FD) { + if ((fd_table.w32_ios[i]->type == SOCK_FD) && (fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) { events[num_events++] = fd_table.w32_ios[i]->write_overlapped.hEvent; } } @@ -448,7 +483,7 @@ int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, co return -1; } - if (0 != wait_for_any_event(events, num_events, time_milliseconds - (ticks_now - ticks_start))) { + if (0 != wait_for_any_event(events, num_events, time_milliseconds - ((ticks_now - ticks_start) & 0xffffffff))) { return -1; } @@ -457,7 +492,7 @@ int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, co for (int i = 0; i < fds; i++) { if (readfds && FD_ISSET(i, readfds)) { - in_ready_fds++; + in_set_fds++; if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) { FD_SET(i, &read_ready_fds); out_ready_fds++; @@ -465,7 +500,7 @@ int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, co } if (writefds && FD_ISSET(i, writefds)) { - in_ready_fds++; + in_set_fds++; if (w32_io_is_io_available(fd_table.w32_ios[i], FALSE)) { FD_SET(i, &write_ready_fds); out_ready_fds++; diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h index 7e8bfb2..653dbf1 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h @@ -4,16 +4,21 @@ #include #include "debug.h" - -//order to be maintained enum w32_io_type { - UNKOWN_FD = 0, - LISTEN_FD = 1, - CONNECT_FD = 2, - SOCK_FD = 3, - FILE_FD = 4, - PIPE_FD = 5, - CONSOLE_FD = 6 + UNKNOWN_FD = 0, + SOCK_FD = 1, + FILE_FD = 2, + PIPE_FD = 3, + CONSOLE_FD = 4, + STD_IO_FD = 5 +}; + +enum w32_io_sock_state { + SOCK_INITIALIZED = 0, + SOCK_LISTENING = 1, + SOCK_ACCEPTED = 2, + SOCK_CONNECTING = 3, + SOCK_CONNECTED = 4 }; struct w32_io { @@ -55,8 +60,11 @@ struct w32_io { HANDLE handle; }; - //handle specific context - void* context; + //handle specific internal state context, currently used by sockets + struct { + enum w32_io_sock_state state; + void* context; + }internal; }; BOOL w32_io_is_blocking(struct w32_io*); diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj b/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj index aede6bc..cf0659e 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj @@ -73,7 +73,15 @@ $(SolutionDir)bin\lib\$(Platform)\$(Configuration)\ - $(SolutionDir)bin\int\$(Platform)\$(Configuration)\$(TargetName)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(SolutionDir)bin\lib\$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(SolutionDir)bin\lib\$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ @@ -145,6 +153,7 @@ + diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj.filters b/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj.filters index acb38f4..36c313e 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj.filters +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/win32posix.vcxproj.filters @@ -59,5 +59,8 @@ inc\sys + + inc + \ No newline at end of file