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