This commit is contained in:
Manoj Ampalam 2016-03-02 13:47:39 -08:00
parent b59cb84398
commit bc0a24539d
10 changed files with 200 additions and 118 deletions

View File

@ -77,12 +77,21 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\win32posix\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<OutDir>$(SolutionDir)bin\unittests\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)\win32posix\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<OutDir>$(SolutionDir)bin\unittests\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)\win32posix\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<OutDir>$(SolutionDir)bin\unittests\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -112,6 +121,8 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Ws2_32.lib;win32posix.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\lib\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -129,6 +140,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>Ws2_32.lib;win32posix.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\lib\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -146,6 +159,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>Ws2_32.lib;win32posix.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\lib\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
#include "..\w32posix.h"

View File

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

View File

@ -3,6 +3,7 @@
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#include <assert.h>
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++;

View File

@ -4,16 +4,21 @@
#include <stdio.h>
#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*);

View File

@ -73,7 +73,15 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)bin\lib\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)bin\int\$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
<IntDir>$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)bin\lib\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)bin\lib\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -145,6 +153,7 @@
<ItemGroup>
<ClInclude Include="debug.h" />
<ClInclude Include="defs.h" />
<ClInclude Include="inc\fcntl.h" />
<ClInclude Include="inc\sys\socket.h" />
<ClInclude Include="inc\sys\stat.h" />
<ClInclude Include="inc\unistd.h" />

View File

@ -59,5 +59,8 @@
<ClInclude Include="inc\sys\stat.h">
<Filter>inc\sys</Filter>
</ClInclude>
<ClInclude Include="inc\fcntl.h">
<Filter>inc</Filter>
</ClInclude>
</ItemGroup>
</Project>