rktio: fix network problems

This commit is contained in:
Matthew Flatt 2017-06-11 14:51:38 -06:00
parent 3065773b31
commit 6e1d519711
10 changed files with 295 additions and 106 deletions

View File

@ -796,7 +796,7 @@ struct mz_addrinfo *scheme_get_host_address(const char *address, int id, int *er
ok = MZ_GETADDRINFO(address, service, &hints, &r);
*err = ok;
if (!ok)
return r;
else

View File

@ -16,8 +16,11 @@ OBJS = rktio_filesystem.o \
all: $(OBJS)
demo: $(OBJS) main.o demo_fifo
$(CC) -o demo $(CFLAGS) $(LDFLAGS) main.o $(OBJS)
demo: rktio_demo
./rktio_demo
rktio_demo: $(OBJS) demo.o demo_fifo
$(CC) -o rktio_demo $(CFLAGS) $(LDFLAGS) demo.o $(OBJS)
demo_fifo:
mkfifo demo_fifo
@ -43,5 +46,5 @@ rktio_error.o: $(srcdir)/rktio_error.c $(RKTIO_HEADERS)
rktio_main.o: $(srcdir)/rktio_main.c $(RKTIO_HEADERS)
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_main.o -c $(srcdir)/rktio_main.c
main.o: $(srcdir)/main.c $(RKTIO_HEADERS)
$(CC) $(CFLAGS) -I$(srcdir) -I. -o main.o -c $(srcdir)/main.c
demo.o: $(srcdir)/demo.c $(RKTIO_HEADERS)
$(CC) $(CFLAGS) -I$(srcdir) -I. -o demo.o -c $(srcdir)/demo.c

View File

@ -3104,6 +3104,52 @@ case "$host_os" in
*mingw*)
use_flag_pthread=no
skip_iconv_check=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lwinpthread" >&5
$as_echo_n "checking for pthread_create in -lwinpthread... " >&6; }
if ${ac_cv_lib_winpthread_pthread_create+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lwinpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char pthread_create ();
int
main ()
{
return pthread_create ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_winpthread_pthread_create=yes
else
ac_cv_lib_winpthread_pthread_create=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_winpthread_pthread_create" >&5
$as_echo "$ac_cv_lib_winpthread_pthread_create" >&6; }
if test "x$ac_cv_lib_winpthread_pthread_create" = xyes; then :
has_winpthread=yes
else
has_winpthread=no
fi
if test "${has_winpthread}" = "yes" ; then
LIBS="${LIBS} -Wl,-Bstatic -lwinpthread"
fi
;;
cygwin*)
;;
@ -3111,6 +3157,7 @@ case "$host_os" in
;;
darwin*)
PREFLAGS="$PREFLAGS -DOS_X -D_DARWIN_UNLIMITED_SELECT"
enable_pthread_by_default=yes
try_kqueue_syscall=yes
# Although select() generally works as well as poll() on OS X,
@ -3886,6 +3933,27 @@ if test "${LFS_CFLAGS}" != "" && test "${LFS_CFLAGS}" != "undefined"; then
CFLAGS="${CFLAGS} ${LFS_CFLAGS}"
fi
############### pthread ###################
if test "${enable_pthread}" = "" ; then
if test "${enable_pthread_by_default}" = "yes" ; then
enable_pthread=yes
fi
fi
if test "${enable_pthread}" = "yes" ; then
if test "${use_flag_pthread}" = "yes" ; then
PREFLAGS="$PREFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
fi
if test "${use_flag_posix_pthread}" = "yes" ; then
PREFLAGS="$PREFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT"
fi
$as_echo "#define RKTIO_USE_PTHREADS 1" >>confdefs.h
fi
############## final output ################

View File

@ -59,6 +59,11 @@ case "$host_os" in
*mingw*)
use_flag_pthread=no
skip_iconv_check=yes
AC_CHECK_LIB(winpthread, pthread_create, has_winpthread=yes, has_winpthread=no)
if test "${has_winpthread}" = "yes" ; then
LIBS="${LIBS} -Wl,-Bstatic -lwinpthread"
fi
;;
cygwin*)
;;
@ -66,6 +71,7 @@ case "$host_os" in
;;
darwin*)
PREFLAGS="$PREFLAGS -DOS_X -D_DARWIN_UNLIMITED_SELECT"
enable_pthread_by_default=yes
try_kqueue_syscall=yes
# Although select() generally works as well as poll() on OS X,
@ -245,6 +251,25 @@ if test "${LFS_CFLAGS}" != "" && test "${LFS_CFLAGS}" != "undefined"; then
CFLAGS="${CFLAGS} ${LFS_CFLAGS}"
fi
############### pthread ###################
if test "${enable_pthread}" = "" ; then
if test "${enable_pthread_by_default}" = "yes" ; then
enable_pthread=yes
fi
fi
if test "${enable_pthread}" = "yes" ; then
if test "${use_flag_pthread}" = "yes" ; then
PREFLAGS="$PREFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
fi
if test "${use_flag_posix_pthread}" = "yes" ; then
PREFLAGS="$PREFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT"
fi
AC_DEFINE(RKTIO_USE_PTHREADS, 1, [Pthread enabled])
fi
############## final output ################
AC_SUBST(CC)

View File

@ -274,6 +274,49 @@ static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd
check_valid(rktio_close(rktio, fd2));
}
void check_many_lookup(rktio_t *rktio)
{
# define LOOKUPS_N 10
int i, j;
rktio_addrinfo_lookup_t *lookup[LOOKUPS_N];
rktio_addrinfo_t *addr;
rktio_poll_set_t *ps;
for (i = 0; i < LOOKUPS_N; i++) {
if (i & 1)
lookup[i] = rktio_start_addrinfo_lookup(rktio, "localhost", 50+i, -1, 0, 1);
else
lookup[i] = rktio_start_addrinfo_lookup(rktio, "racket-lang.org", 50+i, -1, 0, 1);
check_valid(lookup[i]);
}
for (j = 0; j < LOOKUPS_N; j++) {
ps = rktio_make_poll_set(rktio);
check_valid(ps);
for (i = 0; i < LOOKUPS_N; i++) {
if (lookup[i])
rktio_poll_add_addrinfo_lookup(rktio, lookup[i], ps);
}
rktio_sleep(rktio, 0, ps, NULL);
rktio_poll_set_close(rktio, ps);
for (i = 0; i < LOOKUPS_N; i++) {
if (lookup[i] && (rktio_poll_addrinfo_lookup_ready(rktio, lookup[i]) == RKTIO_POLL_READY)) {
if ((i % 3) == 2)
rktio_addrinfo_lookup_stop(rktio, lookup[i]);
else {
addr = rktio_addrinfo_lookup_get(rktio, lookup[i]);
check_valid(addr);
rktio_free_addrinfo(rktio, addr);
}
lookup[i] = NULL;
break;
}
}
}
}
rktio_addrinfo_t *lookup_loop(rktio_t *rktio,
const char *hostname, int portno,
@ -288,7 +331,7 @@ rktio_addrinfo_t *lookup_loop(rktio_t *rktio,
lookup = rktio_start_addrinfo_lookup(rktio, hostname, portno, family, passive, tcp);
check_valid(lookup);
rktio_poll_add_addrinfo_lookup(rktio, lookup, ps);
rktio_sleep(rktio, 0, ps, NULL);
rktio_poll_set_close(rktio, ps);
@ -493,8 +536,10 @@ int main()
{
rktio_addrinfo_t *addr;
rktio_listener_t *lnr;
check_many_lookup(rktio);
addr = lookup_loop(rktio, "localhost", 4536, -1, 1, 1);
addr = lookup_loop(rktio, NULL, 4536, -1, 1, 1);
lnr = rktio_listen(rktio, addr, 5, 1);
check_valid(lnr);

View File

@ -14,8 +14,14 @@ typedef long intptr_t;
typedef unsigned long uintptr_t;
#endif
/* Whether pthread is available */
#undef RKTIO_USE_PTHREADS
/* When poll(), epoll(), kqueue(), etc. is available: */
#undef HAVE_POLL_SYSCALL
#undef HAVE_EPOLL_SYSCALL
#undef HAVE_INOTIFY_SYSCALL
#undef HAVE_KQUEUE_SYSCALL
/* Whether getaddrinfo() is available: */
#undef HAVE_GETADDRINFO

View File

@ -92,7 +92,7 @@ rktio_ltps_t *rktio_open_ltps(rktio_t *rktio)
#if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
lt->fd = -1;
#else
lt->fd_set = rktio_alloc_fdset_array(3);
lt->fd_set = rktio_make_poll_set(rktio);
#endif
lt->signaled = NULL;
@ -133,7 +133,7 @@ int rktio_ltps_close(rktio_t *rktio, rktio_ltps_t *lt)
}
free(lt);
#else
rktio_free_fdset_array(lt->fd_set, 3);
rktio_poll_set_close(rktio, lt->fd_set);
#endif
return 1;

View File

@ -41,6 +41,21 @@ typedef struct sockaddr_in rktio_unspec_address;
#define REGISTER_SOCKET(s) /**/
#define UNREGISTER_SOCKET(s) /**/
# if defined(__linux__) || defined(OS_X)
/* RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT uses IPV6_V6ONLY for IPv6
listeners when the same listener has an IPv4 address, which means
that the IpV6 listener accepts only IPv6 connections. This is used
with Linux, for example, because a port cannot have both an IPv4
and IPv6 listener if the IPv6 one doesn't use IPV6_V6ONLY. (The
two listeners might be for different interfaces, in which case
IPV6_V6ONLY is not necessary, but we must err on the side of being
too restrictive. If IPV6_V6ONLY is not #defined or if setting the
option doesn't work, then the IPv6 addresses are silently ignored
when creating the listener (but only where there is at least once
IPv4 address). */
# define RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT
# endif
#endif
#ifdef CANT_SET_SOCKET_BUFSIZE
@ -147,10 +162,6 @@ struct rktio_udp_t {
/* Host address lookup, including asynchronous-lookup support */
/*========================================================================*/
#if defined(OS_X) || defined(USE_PTHREAD_THREAD_TIMER)
# define PTHREADS_OK_FOR_GHBN
#endif
# ifdef PROTOENT_IS_INT
# define PROTO_P_PROTO PROTOENT_IS_INT
# else
@ -168,7 +179,11 @@ static struct protoent *proto;
#define RKTIO_SOCK_SVC_NAME_MAX_LEN 32
#if defined(HAVE_GETADDRINFO) || defined(__MINGW32__)
# define rktio_addrinfo_t addrinfo
struct rktio_addrinfo_t {
struct addrinfo ai;
};
# define RKTIO_AS_ADDRINFO(x) (&(x)->ai)
# define RKTIO_AS_ADDRINFO_PTR(xp) ((struct addrinfo **)(xp))
#else
struct rktio_addrinfo_t {
int ai_flags;
@ -179,6 +194,8 @@ struct rktio_addrinfo_t {
struct sockaddr *ai_addr;
struct rktio_addrinfo_t *ai_next;
};
# define RKTIO_AS_ADDRINFO(x) x
# define RKTIO_AS_ADDRINFO_PTR(x) x
#endif
#if defined(__MINGW32__) && !defined(HAVE_GETADDRINFO)
@ -192,7 +209,7 @@ struct rktio_addrinfo_t {
#ifdef HAVE_GETADDRINFO
# define rktio_AI_PASSIVE AI_PASSIVE
# define do_getaddrinfo getaddrinfo
# define do_getaddrinfo(n, s, h, res) getaddrinfo(n, s, RKTIO_AS_ADDRINFO(h), RKTIO_AS_ADDRINFO_PTR(res))
# define do_freeaddrinfo freeaddrinfo
# define do_gai_strerror gai_strerror
#else
@ -284,11 +301,13 @@ static void free_lookup(rktio_addrinfo_lookup_t *lookup)
{
#if defined(RKTIO_SYSTEM_WINDOWS) || defined(RKTIO_USE_PTHREADS)
if (lookup->result)
do_freeaddrinfo(lookup->result);
do_freeaddrinfo(RKTIO_AS_ADDRINFO(lookup->result));
#endif
free(lookup->name);
free(lookup->svc);
if (lookup->name)
free(lookup->name);
if (lookup->svc)
free(lookup->svc);
free(lookup->hints);
free(lookup);
}
@ -315,7 +334,7 @@ static void init_lookup(rktio_addrinfo_lookup_t *lookup)
#define GHBN_WAIT 1
#define GHBN_DONE 2
#define GHBN_ADBANDONED 3
#define GHBN_ABANDONED 3
# ifdef RKTIO_SYSTEM_WINDOWS
@ -350,27 +369,27 @@ static void ghbn_wait_exit(rktio_t *rktio)
static void ghbn_lock(rktio_t *rktio)
{
pthread_mutex_lock(rktio->ghbn_lock);
pthread_mutex_lock(&rktio->ghbn_lock);
}
static void ghbn_unlock(rktio_t *rktio)
{
pthread_mutex_lock(rktio->ghbn_unlock);
pthread_mutex_unlock(&rktio->ghbn_lock);
}
static void ghbn_wait(rktio_t *rktio)
{
pthread_cond_wait(rktio->ghbn_start, rktio->ghbn_lock);
pthread_cond_wait(&rktio->ghbn_start, &rktio->ghbn_lock);
}
static void ghbn_signal(rktio_t *rktio)
{
pthread_cond_signal(rktio->ghbn_start);
pthread_cond_signal(&rktio->ghbn_start);
}
static void ghbn_wait_exit(rktio_t *rktio)
{
pthread_join(rktio->th, NULL);
pthread_join(rktio->ghbn_th, NULL);
}
# endif
@ -386,17 +405,14 @@ static intptr_t getaddrinfo_in_thread(void *_data)
while (rktio->ghbn_run) {
lookup = rktio->ghbn_requests;
if (lookup) {
rktio->ghbn->requests = lookup->next;
rktio->ghbn_requests = lookup->next;
ghbn_unlock(rktio);
/* Handle one lookup request: */
err = do_getaddrinfo(lookup->name,
lookup->svc,
lookup->hints,
&result);
request->err = err;
err = do_getaddrinfo(lookup->name, lookup->svc, lookup->hints, &result);
lookup->err = err;
if (!err)
request->result = result;
lookup->result = result;
ghbn_lock(rktio);
@ -406,13 +422,13 @@ static intptr_t getaddrinfo_in_thread(void *_data)
{
long v = 1;
do {
cr = write(lookup->done_fd[1], &v, sizeof(v));
} while ((cr == -1) && (errno == EINTR));
err = write(lookup->done_fd[1], &v, sizeof(v));
} while ((err == -1) && (errno == EINTR));
reliably_close(lookup->done_fd[1]);
}
# endif
if (lookup->state == GHBN_ADBANDONED) {
if (lookup->mode == GHBN_ABANDONED) {
# ifdef RKTIO_SYSTEM_WINDOWS
CloseHandle(data->ready_sema);
# else
@ -472,7 +488,7 @@ static int ghbn_init(rktio_t *rktio)
get_posix_error();
return 0;
}
if (pthread_create(&rktio->th, NULL,
if (pthread_create(&rktio->ghbn_th, NULL,
(RKTIO_LPTHREAD_START_ROUTINE)getaddrinfo_in_thread,
rktio)) {
return 0;
@ -495,6 +511,8 @@ void rktio_free_ghbn(rktio_t *rktio)
static rktio_addrinfo_lookup_t *start_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup)
{
lookup->mode = GHBN_WAIT;
if (!rktio->ghbn_started) {
rktio->ghbn_run = 1;
if (!ghbn_init(rktio))
@ -503,40 +521,41 @@ static rktio_addrinfo_lookup_t *start_lookup(rktio_t *rktio, rktio_addrinfo_look
}
# ifdef RKTIO_SYSTEM_WINDOWS
{
HANDLE ready_sema;
unsigned int id;
intptr_t th;
{
HANDLE ready_sema;
unsigned int id;
intptr_t th;
lookup->done_sema = CreateSemaphore(NULL, 0, 1, NULL);
if (!lookup->done_sema) {
get_windows_error();
free_lookup(lookup);
return NULL;
}
}
# else
if (pipe(lookup->done_fd)) {
get_posix_error();
lookup->done_sema = CreateSemaphore(NULL, 0, 1, NULL);
if (!lookup->done_sema) {
get_windows_error();
free_lookup(lookup);
return NULL;
} else {
fcntl(lookup->done_fd[0], F_SETFL, RKTIO_NONBLOCKING);
}
}
# else
if (pipe(lookup->done_fd)) {
get_posix_error();
free_lookup(lookup);
return NULL;
} else {
fcntl(lookup->done_fd[0], F_SETFL, RKTIO_NONBLOCKING);
}
# endif
ghbn_lock(rktio);
lookup->next = rktio->ghbn_requests;
ghbn_requests = lookup;
ghbn_signal(rktio);
ghbn_unlock(rktio);
ghbn_lock(rktio);
lookup->next = rktio->ghbn_requests;
rktio->ghbn_requests = lookup;
ghbn_signal(rktio);
ghbn_unlock(rktio);
return lookup;
}
return lookup;
}
int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup)
{
int done = 0;
ghbn_lock(rktio);
if (lookup->mode == GHBN_DONE) {
@ -545,10 +564,10 @@ int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lo
}
# ifdef RKTIO_SYSTEM_WINDOWS
if (WaitForSingleObject(lookup->done_sema, 0) == WAIT_OBJECT_0)
if (WaitForSingleObject(lookup->done_sema, 0) == WAIT_OBJECT_0) {
CloseHandle(lookup->done_sema);
else
return 0;
done = 1;
}
# else
{
long v;
@ -558,19 +577,20 @@ int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lo
} while ((cr == -1) && (errno == EINTR));
if (cr > 0) {
reliably_close(lookup->done_fd[0]);
} else
return 0;
done = 1;
}
}
# endif
lookup->mode = GHBN_DONE;
if (done)
lookup->mode = GHBN_DONE;
ghbn_unlock(rktio);
return RKTIO_POLL_READY;
return (done ? RKTIO_POLL_READY : 0);
}
void rktio_poll_add_addr_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_t *fds)
void rktio_poll_add_addrinfo_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_t *fds)
{
ghbn_lock(rktio);
@ -586,12 +606,12 @@ void rktio_poll_add_addr_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup,
rktio_poll_set_add_handle(lookup->done_sema, fds, 1);
# else
{
void *fds2;
rktio_poll_set_t *fds2;
fds2 = RKTIO_GET_FDSET(fds, 2);
RKTIO_FD_SET(lookup->done_fd[0], (fd_set *)fds);
RKTIO_FD_SET(lookup->done_fd[0], (fd_set *)fds2);
RKTIO_FD_SET(lookup->done_fd[0], fds);
RKTIO_FD_SET(lookup->done_fd[0], fds2);
}
# endif
}
@ -600,7 +620,7 @@ void rktio_addrinfo_lookup_stop(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup)
{
ghbn_lock(rktio);
if (lookup->mode != GHBN_DONE) {
lookup->mode == GHBN_ABANDONED;
lookup->mode = GHBN_ABANDONED;
ghbn_unlock(rktio);
} else {
ghbn_unlock(rktio);
@ -666,7 +686,10 @@ rktio_addrinfo_t *rktio_addrinfo_lookup_get(rktio_t *rktio, rktio_addrinfo_looku
free_lookup(lookup);
return result;
if (err)
return NULL;
else
return result;
}
#endif
@ -698,25 +721,25 @@ rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio,
hints = malloc(sizeof(rktio_addrinfo_t));
memset(hints, 0, sizeof(struct rktio_addrinfo_t));
hints->ai_family = ((family < 0) ? PF_UNSPEC : family);
RKTIO_AS_ADDRINFO(hints)->ai_family = ((family < 0) ? PF_UNSPEC : family);
if (passive) {
hints->ai_flags |= rktio_AI_PASSIVE;
RKTIO_AS_ADDRINFO(hints)->ai_flags |= rktio_AI_PASSIVE;
}
if (tcp) {
hints->ai_socktype = SOCK_STREAM;
RKTIO_AS_ADDRINFO(hints)->ai_socktype = SOCK_STREAM;
# ifndef PROTOENT_IS_INT
if (!proto) {
proto = getprotobyname("tcp");
}
# endif
hints->ai_protocol= PROTO_P_PROTO;
RKTIO_AS_ADDRINFO(hints)->ai_protocol= PROTO_P_PROTO;
} else {
hints->ai_socktype = SOCK_DGRAM;
RKTIO_AS_ADDRINFO(hints)->ai_socktype = SOCK_DGRAM;
}
lookup = malloc(sizeof(rktio_addrinfo_lookup_t));
lookup->name = strdup(hostname);
lookup->svc = strdup(service);
lookup->name = (hostname ? strdup(hostname) : NULL);
lookup->svc = (service ? strdup(service) : NULL);
lookup->hints = hints;
init_lookup(lookup);
@ -725,7 +748,7 @@ rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio,
void rktio_free_addrinfo(rktio_t *rktio, rktio_addrinfo_t *a)
{
do_freeaddrinfo(a);
do_freeaddrinfo(RKTIO_AS_ADDRINFO(a));
}
const char *rktio_gai_strerror(int errnum)
@ -1042,11 +1065,13 @@ static rktio_connect_t *try_connect(rktio_t *rktio, rktio_connect_t *conn)
rktio_socket_t s;
addr = conn->addr;
s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
s = socket(RKTIO_AS_ADDRINFO(addr)->ai_family,
RKTIO_AS_ADDRINFO(addr)->ai_socktype,
RKTIO_AS_ADDRINFO(addr)->ai_protocol);
if (s != INVALID_SOCKET) {
int status, inprogress;
if (!conn->src
|| !bind(s, conn->src->ai_addr, conn->src->ai_addrlen)) {
|| !bind(s, RKTIO_AS_ADDRINFO(conn->src)->ai_addr, RKTIO_AS_ADDRINFO(conn->src)->ai_addrlen)) {
#ifdef RKTIO_SYSTEM_WINDOWS
unsigned long ioarg = 1;
ioctlsocket(s, FIONBIO, &ioarg);
@ -1055,7 +1080,7 @@ static rktio_connect_t *try_connect(rktio_t *rktio, rktio_connect_t *conn)
fcntl(s, F_SETFL, RKTIO_NONBLOCKING);
RKTIO_WHEN_SET_SOCKBUF_SIZE(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(int)));
#endif
status = connect(s, addr->ai_addr, addr->ai_addrlen);
status = connect(s, RKTIO_AS_ADDRINFO(addr)->ai_addr, RKTIO_AS_ADDRINFO(addr)->ai_addrlen);
#ifdef RKTIO_SYSTEM_UNIX
if (status)
status = errno;
@ -1128,9 +1153,9 @@ rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *conn)
if (errid) {
rktio_close(rktio, rfd);
if (conn->addr->ai_next) {
if (RKTIO_AS_ADDRINFO(conn->addr)->ai_next) {
/* try the next one */
conn->addr = conn->addr->ai_next;
conn->addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(conn->addr)->ai_next;
if (try_connect(rktio, conn)) {
set_racket_error(RKTIO_ERROR_CONNECT_TRYING_NEXT);
return NULL;
@ -1189,16 +1214,16 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo
int any_v4 = 0, any_v6 = 0;
#endif
for (addr = src; addr; addr = addr->ai_next) {
for (addr = src; addr; addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next) {
#ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT
if (addr->ai_family == RKTIO_PF_INET)
if (RKTIO_AS_ADDRINFO(addr)->ai_family == RKTIO_PF_INET)
any_v4 = 1;
else if (addr->ai_family == PF_INET6)
else if (RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6)
any_v6 = 1;
#endif
count++;
}
{
rktio_socket_t s;
#ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT
@ -1212,34 +1237,36 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo
for (addr = src; addr; ) {
#ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT
if ((v6_loop && (addr->ai_family != PF_INET6))
|| (skip_v6 && (addr->ai_family == PF_INET6))) {
addr = addr->ai_next;
if ((v6_loop && (RKTIO_AS_ADDRINFO(addr)->ai_family != PF_INET6))
|| (skip_v6 && (RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6))) {
addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next;
if (v6_loop && !addr) {
v6_loop = 0;
skip_v6 = 1;
addr = tcp_listen_addr;
addr = src;
}
continue;
}
#endif
s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
s = socket(RKTIO_AS_ADDRINFO(addr)->ai_family,
RKTIO_AS_ADDRINFO(addr)->ai_socktype,
RKTIO_AS_ADDRINFO(addr)->ai_protocol);
if (s != INVALID_SOCKET)
get_socket_error();
#ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT
if (s == INVALID_SOCKET) {
/* Maybe it failed because IPv6 is not available: */
if ((addr->ai_family == PF_INET6) && (errno == EAFNOSUPPORT)) {
if ((RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6) && (errno == EAFNOSUPPORT)) {
if (any_v4 && !pos) {
/* Let client known that maybe we can make it work with just IPv4. */
set_racket_option(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4);
set_racket_error(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4);
}
}
}
if (s != INVALID_SOCKET) {
if (any_v4 && (addr->ai_family == PF_INET6)) {
if (any_v4 && (RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6)) {
int ok;
# ifdef IPV6_V6ONLY
int on = 1;
@ -1250,7 +1277,7 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo
if (ok) {
if (!pos) {
/* IPV6_V6ONLY doesn't work */
set_racket_option(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4);
set_racket_error(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4);
s = INVALID_SOCKET;
} else {
get_socket_error();
@ -1275,11 +1302,11 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo
}
if (first_was_zero) {
((struct sockaddr_in *)addr->ai_addr)->sin_port = no_port;
((struct sockaddr_in *)RKTIO_AS_ADDRINFO(addr)->ai_addr)->sin_port = no_port;
}
if (!bind(s, addr->ai_addr, addr->ai_addrlen)) {
if (!bind(s, RKTIO_AS_ADDRINFO(addr)->ai_addr, RKTIO_AS_ADDRINFO(addr)->ai_addrlen)) {
if (first_time) {
if (((struct sockaddr_in *)addr->ai_addr)->sin_port == 0) {
if (((struct sockaddr_in *)RKTIO_AS_ADDRINFO(addr)->ai_addr)->sin_port == 0) {
no_port = get_no_portno(rktio, s);
first_was_zero = 1;
if (no_port < 0) {
@ -1327,7 +1354,7 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo
break;
}
addr = addr->ai_next;
addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next;
#ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT
if (!addr && v6_loop) {

View File

@ -733,7 +733,10 @@ void rktio_collapse_win_fd(rktio_poll_set_t *fds)
static rktio_poll_set_t *alloc_fdset_arrays()
{
void *p;
p = malloc((3 * sizeof(fd_set)) + sizeof(int));
*(int *)((char *)p + (3 * sizeof(fd_set))) = 0;
return p;
}
static void free_fdset_arrays(rktio_poll_set_t *fds)
@ -869,7 +872,13 @@ void rktio_free_global_poll_set(rktio_t *rktio) {
rktio_poll_set_t *rktio_make_poll_set(rktio_t *rktio)
{
return alloc_fdset_arrays();
rktio_poll_set_t *fds = alloc_fdset_arrays();
RKTIO_FD_ZERO(fds);
RKTIO_FD_ZERO(RKTIO_GET_FDSET(fds, 1));
RKTIO_FD_ZERO(RKTIO_GET_FDSET(fds, 2));
return fds;
}
void rktio_poll_set_close(rktio_t *rktio, rktio_poll_set_t *fds)

View File

@ -5,10 +5,16 @@
# define RKTIO_SYSTEM_UNIX
#endif
#if defined(__APPLE__) && defined(__MACH__) && !defined(OS_X)
# define OS_X
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
# include <windows.h>
#endif
#ifdef RKTIO_USE_PTHREADS
# include <pthread.h>
#endif
#if RKTIO_SYSTEM_WINDOWS
# define USE_FAR_RKTIO_FDCALLS
@ -47,14 +53,14 @@ struct rktio_t {
#if defined(RKTIO_SYSTEM_WINDOWS) || defined(RKTIO_USE_PTHREADS)
int ghbn_started, ghbn_run;
struct rktio_addr_lookup_t *ghbn_requests;
struct rktio_addrinfo_lookup_t *ghbn_requests;
# ifdef RKTIO_USE_PTHREADS
HANDLE ghbn_th;
pthread_t ghbn_th;
pthread_mutex_t ghbn_lock;
pthread_cond_t ghbn_start;
# endif
# ifdef RKTIO_SYSTEM_WINDOWS
pthread_t ghbn_th;
HANDLE ghbn_th;
HANDLE ghbn_lock;
HANDLE ghbn_start;
# endif