This commit is contained in:
manojampalam 2016-03-03 21:34:13 -08:00
parent bc122a7472
commit 18bd5676ce
9 changed files with 422 additions and 345 deletions

View File

@ -1,3 +1,8 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Redefined and missing POSIX macros
*/
#pragma once #pragma once
#include <memory.h> #include <memory.h>

View File

@ -1,3 +1,8 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* POSIX header and needed function definitions
*/
#include "w32posix.h" #include "w32posix.h"
#define fcntl w32_fcntl #define fcntl w32_fcntl

View File

@ -1,3 +1,8 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* POSIX header and needed function definitions
*/
#include "..\w32posix.h" #include "..\w32posix.h"
#define select w32_select #define select w32_select

View File

@ -1,3 +1,9 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* POSIX header and needed function definitions
*/
#include "..\w32posix.h" #include "..\w32posix.h"
#define socket w32_socket #define socket w32_socket

View File

@ -1,3 +1,9 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* POSIX header and needed function definitions
*/
#include "..\w32posix.h" #include "..\w32posix.h"
#define fstat w32_fstat #define fstat w32_fstat

View File

@ -1,3 +1,9 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* POSIX header and needed function definitions
*/
#include "w32posix.h" #include "w32posix.h"
#define pipe w32_pipe #define pipe w32_pipe

View File

@ -1,3 +1,8 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Win32 renamed POSIX APIs
*/
#pragma once #pragma once
#include <WinSock2.h> #include <WinSock2.h>

View File

@ -1,3 +1,8 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Implementation of POSIX APIs
*/
#include "inc\w32posix.h" #include "inc\w32posix.h"
#include "w32fd.h" #include "w32fd.h"
#include <stdarg.h> #include <stdarg.h>
@ -5,404 +10,430 @@
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
/* internal table that stores the fd to w32_io mapping*/
struct w32fd_table { struct w32fd_table {
w32_fd_set occupied; w32_fd_set occupied; /*bit map for tracking occipied table entries*/
struct w32_io* w32_ios[MAX_FDS]; struct w32_io* w32_ios[MAX_FDS];/*array of references to mapped w32_io objects*/
}; };
struct w32fd_table fd_table; /* mapping table*/
struct w32_io w32_io_stdin, w32_io_stdout, w32_io_stderr; static struct w32fd_table fd_table;
/* static table entries representing std in, out and error*/
static struct w32_io w32_io_stdin, w32_io_stdout, w32_io_stderr;
/* maps pio to fd (specified by index)*/
void fd_table_set(struct w32_io* pio, int index); void fd_table_set(struct w32_io* pio, int index);
#pragma warning(disable:4312) #pragma warning(disable:4312)
int fd_table_initialize() { /* initializes mapping table*/
memset(&fd_table, 0, sizeof(fd_table)); static int
memset(&w32_io_stdin, 0, sizeof(w32_io_stdin)); fd_table_initialize() {
w32_io_stdin.handle = (HANDLE)STD_INPUT_HANDLE; memset(&fd_table, 0, sizeof(fd_table));
w32_io_stdin.type = STD_IO_FD; memset(&w32_io_stdin, 0, sizeof(w32_io_stdin));
fd_table_set(&w32_io_stdin, STDIN_FILENO); w32_io_stdin.handle = (HANDLE)STD_INPUT_HANDLE;
memset(&w32_io_stdout, 0, sizeof(w32_io_stdout)); w32_io_stdin.type = STD_IO_FD;
w32_io_stdout.handle = (HANDLE)STD_OUTPUT_HANDLE; fd_table_set(&w32_io_stdin, STDIN_FILENO);
w32_io_stdout.type = STD_IO_FD; memset(&w32_io_stdout, 0, sizeof(w32_io_stdout));
fd_table_set(&w32_io_stdout, STDOUT_FILENO); w32_io_stdout.handle = (HANDLE)STD_OUTPUT_HANDLE;
memset(&w32_io_stderr, 0, sizeof(w32_io_stderr)); w32_io_stdout.type = STD_IO_FD;
w32_io_stderr.handle = (HANDLE)STD_ERROR_HANDLE; fd_table_set(&w32_io_stdout, STDOUT_FILENO);
w32_io_stderr.type = STD_IO_FD; memset(&w32_io_stderr, 0, sizeof(w32_io_stderr));
fd_table_set(&w32_io_stderr, STDERR_FILENO); w32_io_stderr.handle = (HANDLE)STD_ERROR_HANDLE;
return 0; w32_io_stderr.type = STD_IO_FD;
fd_table_set(&w32_io_stderr, STDERR_FILENO);
return 0;
} }
static int fd_table_get_min_index() { /* get a free slot in mapping table with least index*/
int min_index = 0; static int
unsigned char* bitmap = fd_table.occupied.bitmap; fd_table_get_min_index() {
unsigned char tmp; int min_index = 0;
unsigned char* bitmap = fd_table.occupied.bitmap;
unsigned char tmp;
while (*bitmap == 0xff) while (*bitmap == 0xff) {
{ bitmap++;
bitmap++; min_index += 8;
min_index += 8; if (min_index >= MAX_FDS) {
if (min_index >= MAX_FDS) { errno = EMFILE;
errno = EMFILE; debug("ERROR: MAX_FDS limit reached");
debug("ERROR: MAX_FDS limit reached"); return -1;
return -1; }
} }
}
tmp = *bitmap; tmp = *bitmap;
while (tmp & 0x80) while (tmp & 0x80)
{ {
tmp <<= 1; tmp <<= 1;
min_index++; min_index++;
} }
return min_index; return min_index;
} }
static void fd_table_set(struct w32_io* pio, int index) { static void
fd_table.w32_ios[index] = pio; fd_table_set(struct w32_io* pio, int index) {
pio->table_index = index; fd_table.w32_ios[index] = pio;
assert(pio->type != UNKNOWN_FD); pio->table_index = index;
FD_SET(index, &(fd_table.occupied)); assert(pio->type != UNKNOWN_FD);
FD_SET(index, &(fd_table.occupied));
} }
static void fd_table_clear(int index) static void
fd_table_clear(int index)
{ {
fd_table.w32_ios[index]->table_index = -1; fd_table.w32_ios[index]->table_index = -1;
fd_table.w32_ios[index] = NULL; fd_table.w32_ios[index] = NULL;
FD_CLR(index, &(fd_table.occupied)); FD_CLR(index, &(fd_table.occupied));
} }
void w32posix_initialize() { void
if ((debug_initialize() != 0) w32posix_initialize() {
|| (fd_table_initialize() != 0) if ((debug_initialize() != 0)
|| (socketio_initialize() != 0)) || (fd_table_initialize() != 0)
abort(); || (socketio_initialize() != 0))
abort();
} }
void w32posix_done() { void
debug_done(); w32posix_done() {
socketio_done(); debug_done();
socketio_done();
} }
BOOL w32_io_is_blocking(struct w32_io* pio) BOOL
w32_io_is_blocking(struct w32_io* pio)
{ {
return (pio->fd_status_flags & O_NONBLOCK) ? FALSE : TRUE; return (pio->fd_status_flags & O_NONBLOCK) ? FALSE : TRUE;
} }
BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd) { BOOL
if (pio->type == SOCK_FD) { w32_io_is_io_available(struct w32_io* pio, BOOL rd) {
return socketio_is_io_available(pio, rd); if (pio->type == SOCK_FD)
} return socketio_is_io_available(pio, rd);
else { else
return fileio_is_io_available(pio, rd); return fileio_is_io_available(pio, rd);
}
} }
int w32_io_on_select(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); return socketio_on_select(pio, rd);
} else
else { return fileio_on_select(pio, rd);
return fileio_on_select(pio, rd);
}
} }
#define CHECK_FD(fd) do { \ #define CHECK_FD(fd) do { \
errno = 0; \ errno = 0; \
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { \ if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { \
errno = EBADF; \ errno = EBADF; \
debug("ERROR: bad fd: %d", fd); \ debug("ERROR: bad fd: %d", fd); \
return -1; \ return -1; \
} \ } \
} while (0) } while (0)
#define CHECK_SOCK_IO(pio) do { \ #define CHECK_SOCK_IO(pio) do { \
errno = 0; \ errno = 0; \
if (pio->type != SOCK_FD) { \ if (pio->type != SOCK_FD) { \
errno = ENOTSOCK; \ errno = ENOTSOCK; \
debug("ERROR: non sock fd type:%d", pio->type); \ debug("ERROR: non sock fd type:%d", pio->type); \
return -1; \ return -1; \
} \ } \
} while (0) } while (0)
int w32_socket(int domain, int type, int protocol) { int
int min_index = fd_table_get_min_index(); w32_socket(int domain, int type, int protocol) {
struct w32_io* pio = NULL; int min_index = fd_table_get_min_index();
struct w32_io* pio = NULL;
errno = 0; errno = 0;
if (min_index == -1) if (min_index == -1)
return -1; return -1;
pio = socketio_socket(domain, type, protocol); pio = socketio_socket(domain, type, protocol);
if (!pio) { if (pio == NULL)
return -1; return -1;
}
pio->type = SOCK_FD; pio->type = SOCK_FD;
fd_table_set(pio, min_index); fd_table_set(pio, min_index);
debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index); debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
return min_index; return min_index;
} }
int w32_accept(int fd, struct sockaddr* addr, int* addrlen) int
w32_accept(int fd, struct sockaddr* addr, int* addrlen)
{ {
debug3("fd:%d", fd); debug3("fd:%d", fd);
CHECK_FD(fd); CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_SOCK_IO(fd_table.w32_ios[fd]);
int min_index = fd_table_get_min_index(); int min_index = fd_table_get_min_index();
struct w32_io* pio = NULL; struct w32_io* pio = NULL;
if (min_index == -1) if (min_index == -1)
return -1; return -1;
pio = socketio_accept(fd_table.w32_ios[fd], addr, addrlen); pio = socketio_accept(fd_table.w32_ios[fd], addr, addrlen);
if (!pio) { if (!pio)
return -1; return -1;
}
pio->type = SOCK_FD; pio->type = SOCK_FD;
fd_table_set(pio, min_index); fd_table_set(pio, min_index);
debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index); debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
return min_index; return min_index;
} }
int w32_setsockopt(int fd, int level, int optname, const char* optval, int optlen) { int
debug3("fd:%d", fd); w32_setsockopt(int fd, int level, int optname, const char* optval, int optlen) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_setsockopt(fd_table.w32_ios[fd], level, optname, optval, optlen); 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) { int
debug3("fd:%d", fd); w32_getsockopt(int fd, int level, int optname, char* optval, int* optlen) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_getsockopt(fd_table.w32_ios[fd], level, optname, optval, optlen); 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) { int
debug3("fd:%d", fd); w32_getsockname(int fd, struct sockaddr* name, int* namelen) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_getsockname(fd_table.w32_ios[fd], name, namelen); 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) { int
debug3("fd:%d", fd); w32_getpeername(int fd, struct sockaddr* name, int* namelen) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_getpeername(fd_table.w32_ios[fd], name, namelen); 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) { int
debug3("fd:%d", fd); w32_listen(int fd, int backlog) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_listen(fd_table.w32_ios[fd], backlog); 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) { int
debug3("fd:%d", fd); w32_bind(int fd, const struct sockaddr *name, int namelen) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_bind(fd_table.w32_ios[fd], name, namelen); 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) { int
debug3("fd:%d", fd); w32_connect(int fd, const struct sockaddr* name, int namelen) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_connect(fd_table.w32_ios[fd], name, namelen); 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) { int
debug3("fd:%d", fd); w32_recv(int fd, void *buf, size_t len, int flags) {
CHECK_FD(fd); debug3("fd:%d", fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_recv(fd_table.w32_ios[fd], buf, len, flags); 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) { int
debug3("fd:%d", fd); w32_send(int fd, const void *buf, size_t len, int flags) {
CHECK_FD(fd); debug3("fd:%d", fd);
return socketio_send(fd_table.w32_ios[fd], buf, len, flags); CHECK_FD(fd);
return socketio_send(fd_table.w32_ios[fd], buf, len, flags);
} }
int w32_shutdown(int fd, int how) { int
debug3("fd:%d how:%d", fd, how); w32_shutdown(int fd, int how) {
CHECK_FD(fd); debug3("fd:%d how:%d", fd, how);
CHECK_SOCK_IO(fd_table.w32_ios[fd]); CHECK_FD(fd);
return socketio_shutdown(fd_table.w32_ios[fd], how); CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_shutdown(fd_table.w32_ios[fd], how);
} }
//file io int
int w32_pipe(int *pfds){ w32_pipe(int *pfds){
int read_index, write_index; int read_index, write_index;
struct w32_io* pio[2]; struct w32_io* pio[2];
errno = 0; errno = 0;
read_index = fd_table_get_min_index(); read_index = fd_table_get_min_index();
if (read_index == -1) if (read_index == -1)
return -1; return -1;
//temporarily set occupied bit /*temporarily set occupied bit*/
FD_SET(read_index, &fd_table.occupied); FD_SET(read_index, &fd_table.occupied);
write_index = fd_table_get_min_index(); write_index = fd_table_get_min_index();
FD_CLR(read_index, &fd_table.occupied); FD_CLR(read_index, &fd_table.occupied);
if (write_index == -1) if (write_index == -1)
return -1; return -1;
if (-1 == fileio_pipe(pio)) if (-1 == fileio_pipe(pio))
return -1; return -1;
pio[0]->type = PIPE_FD; pio[0]->type = PIPE_FD;
pio[1]->type = PIPE_FD; pio[1]->type = PIPE_FD;
fd_table_set(pio[0], read_index); fd_table_set(pio[0], read_index);
fd_table_set(pio[1], write_index); fd_table_set(pio[1], write_index);
pfds[0] = read_index; pfds[0] = read_index;
pfds[1] = write_index; pfds[1] = write_index;
debug("read end: handle:%p, io:%p, fd:%d", pio[0]->handle, pio[0], read_index); debug("read end: handle:%p, io:%p, fd:%d", pio[0]->handle, pio[0], read_index);
debug("write end: handle:%p, io:%p, fd:%d", pio[1]->handle, pio[1], write_index); debug("write end: handle:%p, io:%p, fd:%d", pio[1]->handle, pio[1], write_index);
return 0; return 0;
} }
int w32_open(const char *pathname, int flags, ...) { int
int min_index = fd_table_get_min_index(); w32_open(const char *pathname, int flags, ...) {
struct w32_io* pio; int min_index = fd_table_get_min_index();
struct w32_io* pio;
errno = 0; errno = 0;
if (min_index == -1) if (min_index == -1)
return -1; return -1;
pio = fileio_open(pathname, flags, 0); pio = fileio_open(pathname, flags, 0);
if (pio == NULL) if (pio == NULL)
return -1; return -1;
pio->type = FILE_FD; pio->type = FILE_FD;
fd_table_set(pio, min_index); fd_table_set(pio, min_index);
debug("handle:%p, io:%p, fd:%d", pio->handle, pio, min_index); debug("handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
return min_index; return min_index;
} }
int w32_read(int fd, void *dst, unsigned int max) { int
CHECK_FD(fd); w32_read(int fd, void *dst, unsigned int max) {
if (fd_table.w32_ios[fd]->type == SOCK_FD) CHECK_FD(fd);
return socketio_recv(fd_table.w32_ios[fd], dst, max, 0); if (fd_table.w32_ios[fd]->type == SOCK_FD)
return fileio_read(fd_table.w32_ios[fd], dst, max); return socketio_recv(fd_table.w32_ios[fd], dst, max, 0);
return fileio_read(fd_table.w32_ios[fd], dst, max);
} }
int w32_write(int fd, const void *buf, unsigned int max) { int
CHECK_FD(fd); w32_write(int fd, const void *buf, unsigned int max) {
if (fd_table.w32_ios[fd]->type == SOCK_FD) CHECK_FD(fd);
return socketio_send(fd_table.w32_ios[fd], buf, max, 0); if (fd_table.w32_ios[fd]->type == SOCK_FD)
return fileio_write(fd_table.w32_ios[fd], buf, max); return socketio_send(fd_table.w32_ios[fd], buf, max, 0);
return fileio_write(fd_table.w32_ios[fd], buf, max);
} }
int w32_fstat(int fd, struct stat *buf) { int
CHECK_FD(fd); w32_fstat(int fd, struct stat *buf) {
return fileio_fstat(fd_table.w32_ios[fd], buf); CHECK_FD(fd);
return fileio_fstat(fd_table.w32_ios[fd], buf);
} }
int w32_isatty(int fd) { int
CHECK_FD(fd); w32_isatty(int fd) {
return fileio_isatty(fd_table.w32_ios[fd]); CHECK_FD(fd);
return fileio_isatty(fd_table.w32_ios[fd]);
} }
FILE* w32_fdopen(int fd, const char *mode) { FILE*
errno = 0; w32_fdopen(int fd, const char *mode) {
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { errno = 0;
errno = EBADF; if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
debug("bad fd: %d", fd); errno = EBADF;
return NULL; debug("bad fd: %d", fd);
} return NULL;
return fileio_fdopen(fd_table.w32_ios[fd], mode); }
return fileio_fdopen(fd_table.w32_ios[fd], mode);
} }
//Common IO int
int w32_close(int fd) { w32_close(int fd) {
struct w32_io* pio;
struct w32_io* pio; CHECK_FD(fd);
pio = fd_table.w32_ios[fd];
CHECK_FD(fd); debug("io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd, pio->table_index);
pio = fd_table.w32_ios[fd]; fd_table_clear(pio->table_index);
if ((pio->type == SOCK_FD))
debug("io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd, pio->table_index); return socketio_close(pio);
fd_table_clear(pio->table_index); else
if ((pio->type == SOCK_FD)) { return fileio_close(pio);
return socketio_close(pio);
}
else
return fileio_close(pio);
} }
int w32_fcntl(int fd, int cmd, ... /* arg */) { int
va_list valist; w32_fcntl(int fd, int cmd, ... /* arg */) {
va_start(valist, cmd); va_list valist;
va_start(valist, cmd);
CHECK_FD(fd); CHECK_FD(fd);
switch (cmd){ switch (cmd){
case F_GETFL: case F_GETFL:
return fd_table.w32_ios[fd]->fd_status_flags; return fd_table.w32_ios[fd]->fd_status_flags;
case F_SETFL: case F_SETFL:
fd_table.w32_ios[fd]->fd_status_flags = va_arg(valist, int); fd_table.w32_ios[fd]->fd_status_flags = va_arg(valist, int);
return 0; return 0;
case F_GETFD: case F_GETFD:
return fd_table.w32_ios[fd]->fd_flags; return fd_table.w32_ios[fd]->fd_flags;
return 0; return 0;
case F_SETFD: case F_SETFD:
fd_table.w32_ios[fd]->fd_flags = va_arg(valist, int); fd_table.w32_ios[fd]->fd_flags = va_arg(valist, int);
return 0; return 0;
default: default:
errno = EINVAL; errno = EINVAL;
debug("ERROR: cmd:%d", cmd); debug("ERROR: cmd:%d", cmd);
return -1; return -1;
} }
} }
int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval *timeout) { int
int in_set_fds = 0, out_ready_fds = 0, i; w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval *timeout) {
fd_set read_ready_fds, write_ready_fds; ULONGLONG ticks_start = GetTickCount64(), ticks_now;
HANDLE events[32]; fd_set read_ready_fds, write_ready_fds;
int num_events = 0; HANDLE events[32];
unsigned int time_milliseconds = timeout->tv_sec * 100 + timeout->tv_usec / 1000; int num_events = 0;
ULONGLONG ticks_start = GetTickCount64(), ticks_now; int in_set_fds = 0, out_ready_fds = 0, i;
unsigned int time_milliseconds = timeout->tv_sec * 100 + timeout->tv_usec / 1000;
errno = 0; errno = 0;
memset(&read_ready_fds, 0, sizeof(fd_set)); memset(&read_ready_fds, 0, sizeof(fd_set));
memset(&write_ready_fds, 0, sizeof(fd_set)); memset(&write_ready_fds, 0, sizeof(fd_set));
if (fds > MAX_FDS ) { if (fds > MAX_FDS ) {
errno = EINVAL; errno = EINVAL;
debug("ERROR: fds: %d", fds); debug("ERROR: fds: %d", fds);
return -1; return -1;
} }
if (!readfds && !writefds) { if (!readfds && !writefds) {
errno = EINVAL; errno = EINVAL;
debug("ERROR: null fd_sets"); debug("ERROR: null fd_sets");
return -1; return -1;
} }
if (exceptfds) { if (exceptfds) {
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
debug("ERROR: exceptfds not supported"); debug("ERROR: exceptfds not supported");
return -1; return -1;
} }
if (readfds) { if (readfds) {
for (i = 0; i < fds; i++) for (i = 0; i < fds; i++)
if (FD_ISSET(i, readfds)) { if (FD_ISSET(i, readfds)) {
CHECK_FD(i); CHECK_FD(i);
in_set_fds++; in_set_fds++;
} }
} }
if (writefds) { if (writefds) {
for (i = 0; i < fds; i++) for (i = 0; i < fds; i++)

View File

@ -1,3 +1,9 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Definitions for Win32 wrapper functions with POSIX like signatures
*/
#pragma once #pragma once
#include <Windows.h> #include <Windows.h>
@ -5,80 +11,82 @@
#include "debug.h" #include "debug.h"
enum w32_io_type { enum w32_io_type {
UNKNOWN_FD = 0, UNKNOWN_FD = 0,
SOCK_FD = 1, SOCK_FD = 1, /*maps a socket fd*/
FILE_FD = 2, FILE_FD = 2, /*maps a file fd*/
PIPE_FD = 3, PIPE_FD = 3, /*maps a pipe fd*/
CONSOLE_FD = 4, STD_IO_FD = 5 /*maps a std fd*/
STD_IO_FD = 5
}; };
enum w32_io_sock_state { enum w32_io_sock_state {
SOCK_INITIALIZED = 0, SOCK_INITIALIZED = 0,
SOCK_LISTENING = 1, SOCK_LISTENING = 1, /*listen called on socket*/
SOCK_ACCEPTED = 2, SOCK_ACCEPTED = 2, /*socket retruned from accept()*/
SOCK_CONNECTING = 3, SOCK_CONNECTING = 3, /*connect called on socket, connect is in progress*/
SOCK_CONNECTED = 4 SOCK_CONNECTED = 4 /*connect completed on socket*/
}; };
enum w32_io_pipe_state { enum w32_io_pipe_state {
PIPE_READ_END = 1, PIPE_READ_END = 1, /*read end of a pipe()*/
PIPE_WRITE_END = 2 PIPE_WRITE_END = 2 /*write end of a pipe()*/
}; };
/*
* This sturcture encapsulates the state info needed to map a File Descriptor to Win32 Handle
*/
struct w32_io { struct w32_io {
OVERLAPPED read_overlapped; OVERLAPPED read_overlapped;
OVERLAPPED write_overlapped; OVERLAPPED write_overlapped;
struct { struct {
//internal buffer details /*internal read buffer*/
char *buf; char *buf;
DWORD buf_size; DWORD buf_size;
DWORD remaining; /*bytes in internal buffer remaining to be read by application*/
DWORD completed; /*bytes in internal buffer already read by application*/
BOOL pending; /*waiting on a read operation to complete*/
DWORD error; /*error reported on async read or accept completion*/
}read_details;
struct {
/*internal write buffer*/
char *buf;
DWORD buf_size;
DWORD remaining; /*bytes in internal buffer remaining to be written to network*/
DWORD completed; /*bytes in internal buffer already written to network*/
BOOL pending; /*waiting on a write operation to complete*/
DWORD error; /*error reported on async write or connect completion*/
}write_details;
//async io details int table_index; /*index at which this object is stored in fd_table*/
DWORD error; //error reported on async read completion enum w32_io_type type; /*hanldle type*/
DWORD remaining; //bytes in internal buffer remaining to be read by application DWORD fd_flags; /*fd flags from POSIX*/
DWORD completed; //bytes in internal buffer already read by application DWORD fd_status_flags; /*fd status flags from POSIX*/
BOOL pending; //waiting on async io to complete
}read_details;
struct {
//internal buffer details
char* buf;
DWORD buf_size;
//async io details /*underlying w32 handle*/
DWORD error; //error reported on async write completion
DWORD remaining; //bytes in internal buffer that are not yet successfully written on i/o
DWORD completed; //bytes in internal buffer that have been successfully written on i/o
BOOL pending; //waiting on async io to complete
}write_details;
//-1 if not indexed
int table_index;
//handle type
enum w32_io_type type;
DWORD fd_flags;
DWORD fd_status_flags;
//underlying w32 handle
union { union {
SOCKET sock; SOCKET sock;
HANDLE handle; HANDLE handle;
}; };
//handle specific internal state context, currently used by sockets /*handle specific internal state context, used by sockets and pipes*/
struct { struct {
enum w32_io_sock_state state; enum w32_io_sock_state state;
void* context; void* context;
}internal; }internal;
}; };
/* Check if the corresponding fd is set blocking */
BOOL w32_io_is_blocking(struct w32_io*); BOOL w32_io_is_blocking(struct w32_io*);
/*
* Check if io is ready/available. This function is primarily used by select() as it decides on what fds can be set.
*/
BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd); BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd);
//signal /*
* Main wait routine used by all blocking calls. It wakes up on IO completions, timers, timeouts and signals.
*/
int wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds); int wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds);
//socket io /*POSIX mimic'ing socket API*/
int socketio_initialize(); int socketio_initialize();
int socketio_done(); int socketio_done();
BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd); BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd);
@ -98,7 +106,7 @@ int socketio_shutdown(struct w32_io* pio, int how);
int socketio_close(struct w32_io* pio); int socketio_close(struct w32_io* pio);
//fileio /*POSIX mimic'ing file API*/
BOOL fileio_is_io_available(struct w32_io* pio, BOOL rd); BOOL fileio_is_io_available(struct w32_io* pio, BOOL rd);
int fileio_on_select(struct w32_io* pio, BOOL rd); int fileio_on_select(struct w32_io* pio, BOOL rd);
int fileio_close(struct w32_io* pio); int fileio_close(struct w32_io* pio);