mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Porting continues. TCP works fine now.
git-svn-id: file:///svn/unbound/trunk@1128 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
fc3fc7a1f3
commit
ee5ee20071
7 changed files with 184 additions and 25 deletions
|
|
@ -1,3 +1,13 @@
|
||||||
|
23 June 2008: Wouter
|
||||||
|
- fixup minitpkg to cleanup on windows with its file locking troubles.
|
||||||
|
- minitpkg shows skipped tests in report.
|
||||||
|
- skip ipv6 tests on ipv4 only hosts (requires only ipv6 localhost not
|
||||||
|
ipv6 connectivity).
|
||||||
|
- winsock event handler keeps track of sticky TCP events, that have
|
||||||
|
not been fully handled yet. when interest in the event(s) resumes,
|
||||||
|
they are sent again. When WOULDBLOCK is returned events are cleared.
|
||||||
|
- skip tests that need signals when testing on mingw.
|
||||||
|
|
||||||
18 June 2008: Wouter
|
18 June 2008: Wouter
|
||||||
- open testbound replay files in binary mode, because fseek/ftell
|
- open testbound replay files in binary mode, because fseek/ftell
|
||||||
do not work in ascii-mode on windows. The b does nothing on unix.
|
do not work in ascii-mode on windows. The b does nothing on unix.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,22 @@ NEED_XXD='fwd_compress_c00c.tpkg'
|
||||||
NEED_NC='fwd_compress_c00c.tpkg'
|
NEED_NC='fwd_compress_c00c.tpkg'
|
||||||
NEED_CURL='06-ianaports.tpkg'
|
NEED_CURL='06-ianaports.tpkg'
|
||||||
NEED_WHOAMI='07-confroot.tpkg'
|
NEED_WHOAMI='07-confroot.tpkg'
|
||||||
|
NEED_IPV6='fwd_ancil.tpkg fwd_tcp_tc6.tpkg'
|
||||||
|
NEED_JOBCONTROL='tcp_sigpipe.tpkg'
|
||||||
|
|
||||||
|
# test if job control - and also signals - are available (not on mingw).
|
||||||
|
if wait %% 2>&1 | grep "job control not enabled" >/dev/null 2>&1; then
|
||||||
|
JOBCONTROL=no
|
||||||
|
else
|
||||||
|
JOBCONTROL=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
# test for ipv6, uses dig 9.4.2 peculiarity (test @ before -v).
|
||||||
|
if dig @::1 -v >/dev/null 2>&1; then
|
||||||
|
HAVE_IPV6=yes
|
||||||
|
else
|
||||||
|
HAVE_IPV6=no
|
||||||
|
fi
|
||||||
|
|
||||||
cd testdata;
|
cd testdata;
|
||||||
sh ../testcode/mini_tpkg.sh clean
|
sh ../testcode/mini_tpkg.sh clean
|
||||||
|
|
@ -48,6 +64,16 @@ for test in `ls *.tpkg`; do
|
||||||
SKIP=1;
|
SKIP=1;
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if echo $NEED_IPV6 | grep $test >/dev/null; then
|
||||||
|
if test "$HAVE_IPV6" = no; then
|
||||||
|
SKIP=1;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if echo $NEED_JOBCONTROL | grep $test >/dev/null; then
|
||||||
|
if test "$JOBCONTROL" = no; then
|
||||||
|
SKIP=1;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if test $SKIP -eq 0; then
|
if test $SKIP -eq 0; then
|
||||||
echo $test
|
echo $test
|
||||||
sh ../testcode/mini_tpkg.sh -a ../.. exe $test
|
sh ../testcode/mini_tpkg.sh -a ../.. exe $test
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,18 @@ if test "$1" = "fake"; then
|
||||||
fi
|
fi
|
||||||
if test "$1" = "report" || test "$2" = "report"; then
|
if test "$1" = "report" || test "$2" = "report"; then
|
||||||
echo "Minitpkg Report"
|
echo "Minitpkg Report"
|
||||||
for result in result.*; do
|
for result in *.tpkg; do
|
||||||
name=`echo $result | sed -e 's/result\.//'`
|
name=`basename $result .tpkg`
|
||||||
if test -f ".done-$name"; then
|
if test -f ".done-$name"; then
|
||||||
if test "$1" != "-q"; then
|
if test "$1" != "-q"; then
|
||||||
echo "** PASSED ** : $name"
|
echo "** PASSED ** : $name"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "!! FAILED !! : $name"
|
if test -f "result.$name"; then
|
||||||
|
echo "!! FAILED !! : $name"
|
||||||
|
else
|
||||||
|
echo ">> SKIPPED<< : $name"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
exit 0
|
exit 0
|
||||||
|
|
@ -113,3 +117,10 @@ fi
|
||||||
mv $result ..
|
mv $result ..
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
# compat for windows where deletion may not succeed initially (files locked
|
||||||
|
# by processes that still have to exit).
|
||||||
|
if test $? -eq 1; then
|
||||||
|
echo "minitpkg waiting for processes to terminate"
|
||||||
|
sleep 2 # some time to exit, and try again
|
||||||
|
rm -rf $dir
|
||||||
|
fi
|
||||||
|
|
|
||||||
BIN
testdata/stream_tcp.tpkg
vendored
BIN
testdata/stream_tcp.tpkg
vendored
Binary file not shown.
|
|
@ -574,9 +574,12 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
|
||||||
log_err("accept failed: %s", strerror(errno));
|
log_err("accept failed: %s", strerror(errno));
|
||||||
#else /* USE_WINSOCK */
|
#else /* USE_WINSOCK */
|
||||||
if(WSAGetLastError() == WSAEINPROGRESS ||
|
if(WSAGetLastError() == WSAEINPROGRESS ||
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK ||
|
|
||||||
WSAGetLastError() == WSAECONNRESET)
|
WSAGetLastError() == WSAECONNRESET)
|
||||||
return;
|
return;
|
||||||
|
if(WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||||
|
winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
log_err("accept failed: %s", wsa_strerror(WSAGetLastError()));
|
log_err("accept failed: %s", wsa_strerror(WSAGetLastError()));
|
||||||
#endif
|
#endif
|
||||||
log_addr(0, "remote address is", &c_hdl->repinfo.addr,
|
log_addr(0, "remote address is", &c_hdl->repinfo.addr,
|
||||||
|
|
@ -671,10 +674,14 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
|
||||||
#endif
|
#endif
|
||||||
log_err("read (in tcp s): %s", strerror(errno));
|
log_err("read (in tcp s): %s", strerror(errno));
|
||||||
#else /* USE_WINSOCK */
|
#else /* USE_WINSOCK */
|
||||||
if(WSAGetLastError() == WSAEINPROGRESS ||
|
if(WSAGetLastError() == WSAECONNRESET)
|
||||||
WSAGetLastError() == WSAECONNRESET ||
|
return 0;
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK)
|
if(WSAGetLastError() == WSAEINPROGRESS)
|
||||||
return 1;
|
return 1;
|
||||||
|
if(WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||||
|
winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
log_err("read (in tcp s): %s",
|
log_err("read (in tcp s): %s",
|
||||||
wsa_strerror(WSAGetLastError()));
|
wsa_strerror(WSAGetLastError()));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -712,10 +719,14 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
|
||||||
return 1;
|
return 1;
|
||||||
log_err("read (in tcp r): %s", strerror(errno));
|
log_err("read (in tcp r): %s", strerror(errno));
|
||||||
#else /* USE_WINSOCK */
|
#else /* USE_WINSOCK */
|
||||||
if(WSAGetLastError() == WSAEINPROGRESS ||
|
if(WSAGetLastError() == WSAECONNRESET)
|
||||||
WSAGetLastError() == WSAECONNRESET ||
|
return 0;
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK)
|
if(WSAGetLastError() == WSAEINPROGRESS)
|
||||||
return 1;
|
return 1;
|
||||||
|
if(WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||||
|
winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
log_err("read (in tcp r): %s",
|
log_err("read (in tcp r): %s",
|
||||||
wsa_strerror(WSAGetLastError()));
|
wsa_strerror(WSAGetLastError()));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -793,9 +804,12 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
|
||||||
return 1;
|
return 1;
|
||||||
log_err("tcp writev: %s", strerror(errno));
|
log_err("tcp writev: %s", strerror(errno));
|
||||||
#else
|
#else
|
||||||
if(WSAGetLastError() == WSAEINPROGRESS ||
|
if(WSAGetLastError() == WSAEINPROGRESS)
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
if(WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||||
|
winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
log_err("tcp send s: %s",
|
log_err("tcp send s: %s",
|
||||||
wsa_strerror(WSAGetLastError()));
|
wsa_strerror(WSAGetLastError()));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -822,9 +836,12 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
|
||||||
return 1;
|
return 1;
|
||||||
log_err("tcp send r: %s", strerror(errno));
|
log_err("tcp send r: %s", strerror(errno));
|
||||||
#else
|
#else
|
||||||
if(WSAGetLastError() == WSAEINPROGRESS ||
|
if(WSAGetLastError() == WSAEINPROGRESS)
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
if(WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||||
|
winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
log_err("tcp send r: %s",
|
log_err("tcp send r: %s",
|
||||||
wsa_strerror(WSAGetLastError()));
|
wsa_strerror(WSAGetLastError()));
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,8 @@ void *event_init(uint32_t* time_secs, struct timeval* time_tv)
|
||||||
event_base_free(base);
|
event_base_free(base);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
base->tcp_stickies = 0;
|
||||||
|
base->tcp_reinvigorated = 0;
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,12 +186,20 @@ static int handle_select(struct event_base* base, struct timeval* wait)
|
||||||
struct event* eventlist[WSK_MAX_ITEMS];
|
struct event* eventlist[WSK_MAX_ITEMS];
|
||||||
WSANETWORKEVENTS netev;
|
WSANETWORKEVENTS netev;
|
||||||
int i, numwait = 0, startidx = 0, was_timeout = 0;
|
int i, numwait = 0, startidx = 0, was_timeout = 0;
|
||||||
|
int newstickies = 0;
|
||||||
|
struct timeval nultm;
|
||||||
|
|
||||||
#ifndef S_SPLINT_S
|
#ifndef S_SPLINT_S
|
||||||
if(wait->tv_sec==(time_t)-1)
|
if(wait->tv_sec==(time_t)-1)
|
||||||
wait = NULL;
|
wait = NULL;
|
||||||
if(wait)
|
if(wait)
|
||||||
timeout = wait->tv_sec*1000 + wait->tv_usec/1000;
|
timeout = wait->tv_sec*1000 + wait->tv_usec/1000;
|
||||||
|
if(base->tcp_stickies) {
|
||||||
|
wait = &nultm;
|
||||||
|
nultm.tv_sec = 0;
|
||||||
|
nultm.tv_usec = 0;
|
||||||
|
timeout = 0; /* no waiting, we have sticky events */
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* prepare event array */
|
/* prepare event array */
|
||||||
|
|
@ -201,7 +211,6 @@ static int handle_select(struct event_base* base, struct timeval* wait)
|
||||||
}
|
}
|
||||||
log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
|
log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
|
||||||
|
|
||||||
|
|
||||||
/* do the wait */
|
/* do the wait */
|
||||||
if(numwait == 0) {
|
if(numwait == 0) {
|
||||||
/* WSAWaitFor.. doesn't like 0 event objects */
|
/* WSAWaitFor.. doesn't like 0 event objects */
|
||||||
|
|
@ -232,8 +241,8 @@ static int handle_select(struct event_base* base, struct timeval* wait)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* callbacks */
|
/* callbacks */
|
||||||
if(was_timeout)
|
if(base->tcp_stickies)
|
||||||
return 0;
|
startidx = 0; /* process all events, some are sticky */
|
||||||
|
|
||||||
for(i=startidx; i<numwait; i++) {
|
for(i=startidx; i<numwait; i++) {
|
||||||
short bits = 0;
|
short bits = 0;
|
||||||
|
|
@ -248,37 +257,55 @@ static int handle_select(struct event_base* base, struct timeval* wait)
|
||||||
}
|
}
|
||||||
if((netev.lNetworkEvents & FD_READ)) {
|
if((netev.lNetworkEvents & FD_READ)) {
|
||||||
if(netev.iErrorCode[FD_READ_BIT] != 0)
|
if(netev.iErrorCode[FD_READ_BIT] != 0)
|
||||||
log_err("FD_READ_BIT error: %s",
|
verbose(VERB_ALGO, "FD_READ_BIT error: %s",
|
||||||
wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
|
wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
|
||||||
bits |= EV_READ;
|
bits |= EV_READ;
|
||||||
}
|
}
|
||||||
if((netev.lNetworkEvents & FD_WRITE)) {
|
if((netev.lNetworkEvents & FD_WRITE)) {
|
||||||
if(netev.iErrorCode[FD_WRITE_BIT] != 0)
|
if(netev.iErrorCode[FD_WRITE_BIT] != 0)
|
||||||
log_err("FD_WRITE_BIT error: %s",
|
verbose(VERB_ALGO, "FD_WRITE_BIT error: %s",
|
||||||
wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
|
wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
|
||||||
bits |= EV_WRITE;
|
bits |= EV_WRITE;
|
||||||
}
|
}
|
||||||
if((netev.lNetworkEvents & FD_CONNECT)) {
|
if((netev.lNetworkEvents & FD_CONNECT)) {
|
||||||
if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
|
if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
|
||||||
log_err("FD_CONNECT_BIT error: %s",
|
verbose(VERB_ALGO, "FD_CONNECT_BIT error: %s",
|
||||||
wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
|
wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
|
||||||
bits |= EV_READ;
|
bits |= EV_READ;
|
||||||
bits |= EV_WRITE;
|
bits |= EV_WRITE;
|
||||||
}
|
}
|
||||||
if((netev.lNetworkEvents & FD_ACCEPT)) {
|
if((netev.lNetworkEvents & FD_ACCEPT)) {
|
||||||
if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
|
if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
|
||||||
log_err("FD_ACCEPT_BIT error: %s",
|
verbose(VERB_ALGO, "FD_ACCEPT_BIT error: %s",
|
||||||
wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
|
wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
|
||||||
bits |= EV_READ;
|
bits |= EV_READ;
|
||||||
}
|
}
|
||||||
if((netev.lNetworkEvents & FD_CLOSE)) {
|
if((netev.lNetworkEvents & FD_CLOSE)) {
|
||||||
if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
|
if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
|
||||||
log_err("FD_CLOSE_BIT error: %s",
|
verbose(VERB_ALGO, "FD_CLOSE_BIT error: %s",
|
||||||
wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
|
wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
|
||||||
bits |= EV_READ;
|
bits |= EV_READ;
|
||||||
bits |= EV_WRITE;
|
bits |= EV_WRITE;
|
||||||
}
|
}
|
||||||
if(bits) {
|
if(eventlist[i]->is_tcp && eventlist[i]->stick_events) {
|
||||||
|
verbose(VERB_ALGO, "winsock %d pass sticky %s%s",
|
||||||
|
eventlist[i]->ev_fd,
|
||||||
|
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
||||||
|
(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
|
||||||
|
bits |= eventlist[i]->old_events;
|
||||||
|
}
|
||||||
|
if(eventlist[i]->is_tcp && bits) {
|
||||||
|
eventlist[i]->old_events = bits;
|
||||||
|
eventlist[i]->stick_events = 1;
|
||||||
|
if((eventlist[i]->ev_events & bits)) {
|
||||||
|
newstickies = 1;
|
||||||
|
}
|
||||||
|
verbose(VERB_ALGO, "winsock %d store sticky %s%s",
|
||||||
|
eventlist[i]->ev_fd,
|
||||||
|
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
||||||
|
(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
|
||||||
|
}
|
||||||
|
if((bits & eventlist[i]->ev_events)) {
|
||||||
verbose(VERB_ALGO, "winsock event callback %p fd=%d "
|
verbose(VERB_ALGO, "winsock event callback %p fd=%d "
|
||||||
"%s%s%s%s%s ; %s%s%s",
|
"%s%s%s%s%s ; %s%s%s",
|
||||||
eventlist[i], eventlist[i]->ev_fd,
|
eventlist[i], eventlist[i]->ev_fd,
|
||||||
|
|
@ -296,9 +323,20 @@ static int handle_select(struct event_base* base, struct timeval* wait)
|
||||||
fptr_ok(fptr_whitelist_event(
|
fptr_ok(fptr_whitelist_event(
|
||||||
eventlist[i]->ev_callback));
|
eventlist[i]->ev_callback));
|
||||||
(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
|
(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
|
||||||
bits, eventlist[i]->ev_arg);
|
bits & eventlist[i]->ev_events,
|
||||||
|
eventlist[i]->ev_arg);
|
||||||
}
|
}
|
||||||
|
if(eventlist[i]->is_tcp && bits)
|
||||||
|
verbose(VERB_ALGO, "winsock %d got sticky %s%s",
|
||||||
|
eventlist[i]->ev_fd,
|
||||||
|
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
||||||
|
(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
|
||||||
}
|
}
|
||||||
|
if(base->tcp_reinvigorated) {
|
||||||
|
base->tcp_reinvigorated = 0;
|
||||||
|
newstickies = 1;
|
||||||
|
}
|
||||||
|
base->tcp_stickies = newstickies;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -358,6 +396,8 @@ void event_set(struct event *ev, int fd, short bits,
|
||||||
int event_base_set(struct event_base *base, struct event *ev)
|
int event_base_set(struct event_base *base, struct event *ev)
|
||||||
{
|
{
|
||||||
ev->ev_base = base;
|
ev->ev_base = base;
|
||||||
|
ev->old_events = 0;
|
||||||
|
ev->stick_events = 0;
|
||||||
ev->added = 0;
|
ev->added = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -377,6 +417,7 @@ int event_add(struct event *ev, struct timeval *tv)
|
||||||
return -1;
|
return -1;
|
||||||
ev->idx = ev->ev_base->max++;
|
ev->idx = ev->ev_base->max++;
|
||||||
ev->ev_base->items[ev->idx] = ev;
|
ev->ev_base->items[ev->idx] = ev;
|
||||||
|
ev->is_tcp = 0;
|
||||||
|
|
||||||
if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) {
|
if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) {
|
||||||
BOOL b=0;
|
BOOL b=0;
|
||||||
|
|
@ -393,6 +434,7 @@ int event_add(struct event *ev, struct timeval *tv)
|
||||||
wsa_strerror(WSAGetLastError()));
|
wsa_strerror(WSAGetLastError()));
|
||||||
if(t == SOCK_STREAM) {
|
if(t == SOCK_STREAM) {
|
||||||
/* TCP socket */
|
/* TCP socket */
|
||||||
|
ev->is_tcp = 1;
|
||||||
events |= FD_CLOSE;
|
events |= FD_CLOSE;
|
||||||
if( (ev->ev_events&EV_WRITE) )
|
if( (ev->ev_events&EV_WRITE) )
|
||||||
events |= FD_CONNECT;
|
events |= FD_CONNECT;
|
||||||
|
|
@ -414,6 +456,11 @@ int event_add(struct event *ev, struct timeval *tv)
|
||||||
log_err("WSAEventSelect failed: %s",
|
log_err("WSAEventSelect failed: %s",
|
||||||
wsa_strerror(WSAGetLastError()));
|
wsa_strerror(WSAGetLastError()));
|
||||||
}
|
}
|
||||||
|
if(ev->is_tcp && ev->stick_events &&
|
||||||
|
(ev->ev_events & ev->old_events)) {
|
||||||
|
/* go to processing the sticky event right away */
|
||||||
|
ev->ev_base->tcp_reinvigorated = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tv && (ev->ev_events&EV_TIMEOUT)) {
|
if(tv && (ev->ev_events&EV_TIMEOUT)) {
|
||||||
|
|
@ -502,4 +549,17 @@ int signal_del(struct event *ev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void winsock_tcp_wouldblock(struct event* ev, int eventbits)
|
||||||
|
{
|
||||||
|
verbose(VERB_ALGO, "winsock: tcp wouldblock %s",
|
||||||
|
eventbits==EV_READ?"EV_READ":"EV_WRITE");
|
||||||
|
ev->old_events &= (~eventbits);
|
||||||
|
if(ev->old_events == 0)
|
||||||
|
ev->stick_events = 0;
|
||||||
|
/* in case this is the last sticky event, we could
|
||||||
|
* possibly run an empty handler loop to reset the base
|
||||||
|
* tcp_stickies variable
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* USE_WINSOCK */
|
#endif /* USE_WINSOCK */
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,12 @@
|
||||||
* the socket has blocked, and the event handler can mark it as such.
|
* the socket has blocked, and the event handler can mark it as such.
|
||||||
* Thus, this file transforms the edge notify from windows to a level notify
|
* Thus, this file transforms the edge notify from windows to a level notify
|
||||||
* that is compatible with UNIX.
|
* that is compatible with UNIX.
|
||||||
* However, the WSAEventSelect page says that it does do level notify, as long
|
* The WSAEventSelect page says that it does do level notify, as long
|
||||||
* as you call a recv/write/accept at least once when it is signalled.
|
* as you call a recv/write/accept at least once when it is signalled.
|
||||||
|
* This last bit is not true, even though documented in server2008 api docs
|
||||||
|
* from microsoft, it does not happen at all. Instead you have to test for
|
||||||
|
* WSAEWOULDBLOCK on a tcp stream, and only then retest the socket.
|
||||||
|
* And before that remember the previous result as still valid.
|
||||||
*
|
*
|
||||||
* To stay 'fair', instead of emptying a socket completely, the event handler
|
* To stay 'fair', instead of emptying a socket completely, the event handler
|
||||||
* can test the other (marked as blocking) sockets for new events.
|
* can test the other (marked as blocking) sockets for new events.
|
||||||
|
|
@ -69,6 +73,8 @@
|
||||||
*
|
*
|
||||||
* on winsock, you must use recv() and send() for TCP reads and writes,
|
* on winsock, you must use recv() and send() for TCP reads and writes,
|
||||||
* not read() and write(), those work only on files.
|
* not read() and write(), those work only on files.
|
||||||
|
*
|
||||||
|
* Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTIL_WINSOCK_EVENT_H
|
#ifndef UTIL_WINSOCK_EVENT_H
|
||||||
|
|
@ -122,6 +128,20 @@ struct event_base
|
||||||
uint32_t* time_secs;
|
uint32_t* time_secs;
|
||||||
/** where to store time in microseconds */
|
/** where to store time in microseconds */
|
||||||
struct timeval* time_tv;
|
struct timeval* time_tv;
|
||||||
|
/**
|
||||||
|
* TCP streams have sticky events to them, these are not
|
||||||
|
* reported by the windows event system anymore, we have to
|
||||||
|
* keep reporting those events as present until wouldblock() is
|
||||||
|
* signalled by the handler back to use.
|
||||||
|
*/
|
||||||
|
int tcp_stickies;
|
||||||
|
/**
|
||||||
|
* should next cycle process reinvigorated stickies,
|
||||||
|
* these are stickies that have been stored, but due to a new
|
||||||
|
* event_add a sudden interest in the event has incepted.
|
||||||
|
*/
|
||||||
|
int tcp_reinvigorated;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -152,6 +172,13 @@ struct event {
|
||||||
int idx;
|
int idx;
|
||||||
/** the event handle to wait for new events to become ready */
|
/** the event handle to wait for new events to become ready */
|
||||||
WSAEVENT hEvent;
|
WSAEVENT hEvent;
|
||||||
|
/** true if this filedes is a TCP socket and needs special attention */
|
||||||
|
int is_tcp;
|
||||||
|
/** remembered EV_ values */
|
||||||
|
short old_events;
|
||||||
|
/** should remembered EV_ values be used for TCP streams.
|
||||||
|
* Reset after WOULDBLOCK is signaled using the function. */
|
||||||
|
int stick_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** create event base */
|
/** create event base */
|
||||||
|
|
@ -192,5 +219,13 @@ int signal_del(struct event *);
|
||||||
/** compare events in tree, based on timevalue, ptr for uniqueness */
|
/** compare events in tree, based on timevalue, ptr for uniqueness */
|
||||||
int mini_ev_cmp(const void* a, const void* b);
|
int mini_ev_cmp(const void* a, const void* b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routine for windows only, where the handling layer can signal that
|
||||||
|
* a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs
|
||||||
|
* retesting the event.
|
||||||
|
* Pass if EV_READ or EV_WRITE gave wouldblock.
|
||||||
|
*/
|
||||||
|
void winsock_tcp_wouldblock(struct event* ev, int eventbit);
|
||||||
|
|
||||||
#endif /* USE_WINSOCK */
|
#endif /* USE_WINSOCK */
|
||||||
#endif /* UTIL_WINSOCK_EVENT_H */
|
#endif /* UTIL_WINSOCK_EVENT_H */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue