From: Wouter Wijngaards Date: Wed, 18 Jun 2008 14:27:30 +0000 (+0000) Subject: unit test, testbound, basic udp and tcp tests are working on XP. X-Git-Tag: release-1.0.1~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc3fc7a1f3e7908ede030eba5c9294fd4690cb78;p=thirdparty%2Funbound.git unit test, testbound, basic udp and tcp tests are working on XP. ipv6 not supported by OS is a warning (nonfatal). git-svn-id: file:///svn/unbound/trunk@1127 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/Makefile.in b/Makefile.in index 5b6ed9b37..26505c57b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -131,7 +131,7 @@ tests: all unittest testbound lock-verify pktview signit memstats \ asynclook streamtcp perf delayer harvest test: tests - bash testcode/do-tests.sh + if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi lib: libunbound.la diff --git a/doc/Changelog b/doc/Changelog index 6701995e8..6b236714f 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,9 @@ do not work in ascii-mode on windows. The b does nothing on unix. unittest and testbound tests work on windows (xp too). - ioctlsocket prints nicer error message. + - fixed up some TCP porting for winsock. + - lack of IPv6 gives a warning, no fatal error. + - use WSAGetLastError() on windows instead of errno for some errors. 17 June 2008: Wouter - outgoing num fds 32 by default on windows ; it supports less diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 915b57b91..c054c268c 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -89,7 +89,7 @@ verbose_print_addr(struct addrinfo *addr) int create_udp_sock(int family, int socktype, struct sockaddr* addr, - socklen_t addrlen, int v6only, int* inuse) + socklen_t addrlen, int v6only, int* inuse, int* noproto) { int s; # if defined(IPV6_USE_MIN_MTU) @@ -98,8 +98,23 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, (void)v6only; # endif if((s = socket(family, socktype, 0)) == -1) { - log_err("can't create socket: %s", strerror(errno)); *inuse = 0; +#ifndef USE_WINSOCK + if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { + *noproto = 1; + return -1; + } + log_err("can't create socket: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEAFNOSUPPORT || + WSAGetLastError() == WSAEPROTONOSUPPORT) { + *noproto = 1; + return -1; + } + log_err("can't create socket: %s", + wsa_strerror(WSAGetLastError())); +#endif + *noproto = 0; return -1; } if(family == AF_INET6) { @@ -111,6 +126,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, log_err("setsockopt(..., IPV6_V6ONLY" ", ...) failed: %s", strerror(errno)); close(s); + *noproto = 0; *inuse = 0; return -1; } @@ -130,12 +146,14 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, log_err("setsockopt(..., IPV6_USE_MIN_MTU, " "...) failed: %s", strerror(errno)); close(s); + *noproto = 0; *inuse = 0; return -1; } # endif } if(bind(s, (struct sockaddr*)addr, addrlen) != 0) { + *noproto = 0; #ifdef EADDRINUSE *inuse = (errno == EADDRINUSE); if(errno != EADDRINUSE) @@ -145,6 +163,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, return -1; } if(!fd_set_nonblock(s)) { + *noproto = 0; *inuse = 0; close(s); return -1; @@ -156,18 +175,34 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, * Create and bind TCP listening socket * @param addr: address info ready to make socket. * @param v6only: enable ip6 only flag on ip6 sockets. + * @param noproto: if error caused by lack of protocol support. * @return: the socket. -1 on error. */ static int -create_tcp_accept_sock(struct addrinfo *addr, int v6only) +create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto) { int s; #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY) int on = 1; #endif /* SO_REUSEADDR || IPV6_V6ONLY */ verbose_print_addr(addr); + *noproto = 0; if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) { +#ifndef USE_WINSOCK + if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { + *noproto = 1; + return -1; + } log_err("can't create socket: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEAFNOSUPPORT || + WSAGetLastError() == WSAEPROTONOSUPPORT) { + *noproto = 1; + return -1; + } + log_err("can't create socket: %s", + wsa_strerror(WSAGetLastError())); +#endif return -1; } #ifdef SO_REUSEADDR @@ -209,11 +244,12 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only) */ static int make_sock(int stype, const char* ifname, const char* port, - struct addrinfo *hints, int v6only) + struct addrinfo *hints, int v6only, int* noip6) { struct addrinfo *res = NULL; - int r, s, inuse; + int r, s, inuse, noproto; hints->ai_socktype = stype; + *noip6 = 0; if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) { log_err("node %s:%s getaddrinfo: %s %s", ifname?ifname:"default", port, gai_strerror(r), @@ -229,11 +265,18 @@ make_sock(int stype, const char* ifname, const char* port, verbose_print_addr(res); s = create_udp_sock(res->ai_family, res->ai_socktype, (struct sockaddr*)res->ai_addr, - res->ai_addrlen, v6only, &inuse); + res->ai_addrlen, v6only, &inuse, &noproto); if(s == -1 && inuse) { log_err("bind: address already in use"); + } else if(s == -1 && noproto && hints->ai_family == AF_INET6){ + *noip6 = 1; } - } else s = create_tcp_accept_sock(res, v6only); + } else { + s = create_tcp_accept_sock(res, v6only, &noproto); + if(s == -1 && noproto && hints->ai_family == AF_INET6){ + *noip6 = 1; + } + } freeaddrinfo(res); return s; } @@ -330,12 +373,18 @@ static int ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, struct addrinfo *hints, const char* port, struct listen_port** list) { - int s; + int s, noip6=0; if(!do_udp && !do_tcp) return 0; if(do_auto) { - if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1)) == -1) + if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1, + &noip6)) == -1) { + if(noip6) { + log_warn("IPv6 protocol not available"); + return 1; + } return 0; + } /* getting source addr packet info is highly non-portable */ if(!set_recvpktinfo(s, hints->ai_family)) return 0; @@ -345,15 +394,26 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, } } else if(do_udp) { /* regular udp socket */ - if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1)) == -1) + if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1, + &noip6)) == -1) { + if(noip6) { + log_warn("IPv6 protocol not available"); + return 1; + } return 0; + } if(!port_insert(list, s, listen_type_udp)) { close(s); return 0; } } if(do_tcp) { - if((s = make_sock(SOCK_STREAM, ifname, port, hints, 1)) == -1) { + if((s = make_sock(SOCK_STREAM, ifname, port, hints, 1, + &noip6)) == -1) { + if(noip6) { + /*log_warn("IPv6 protocol not available");*/ + return 1; + } return 0; } if(!port_insert(list, s, listen_type_tcp)) { diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index eed71fc2c..a35ae0a4d 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -171,9 +171,11 @@ size_t listen_get_mem(struct listen_dnsport* listen); * @param v6only: if enabled, IP6 sockets get IP6ONLY option set. * if enabled with value 2 IP6ONLY option is disabled. * @param inuse: on error, this is set true if the port was in use. + * @param noproto: on error, this is set true if cause is that the + IPv6 proto (family) is not available. * @return: the socket. -1 on error. */ int create_udp_sock(int family, int socktype, struct sockaddr* addr, - socklen_t addrlen, int v6only, int* inuse); + socklen_t addrlen, int v6only, int* inuse, int* noproto); #endif /* LISTEN_DNSPORT_H */ diff --git a/services/outside_network.c b/services/outside_network.c index 59a3f6e55..9b1cf8159 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -144,20 +144,28 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) #endif s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == -1) { +#ifndef USE_WINSOCK log_err("outgoing tcp: socket: %s", strerror(errno)); +#else + log_err("outgoing tcp: socket: %s", + wsa_strerror(WSAGetLastError())); +#endif log_addr(0, "failed address", &w->addr, w->addrlen); return 0; } fd_set_nonblock(s); if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) { +#ifndef USE_WINSOCK #ifdef EINPROGRESS if(errno != EINPROGRESS) { -#elif defined(WSAEWOULDBLOCK) - if(errno != WSAEWOULDBLOCK) { #else if(1) { #endif log_err("outgoing tcp: connect: %s", strerror(errno)); +#else /* USE_WINSOCK */ + if(WSAGetLastError() != WSAEINPROGRESS && + WSAGetLastError() != WSAEWOULDBLOCK) { +#endif log_addr(0, "failed address", &w->addr, w->addrlen); close(s); return 0; @@ -682,17 +690,17 @@ static int udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port, int* inuse) { - int fd; + int fd, noproto; if(addr_is_ip6(addr, addrlen)) { struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; sa->sin6_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET6, SOCK_DGRAM, - (struct sockaddr*)addr, addrlen, 1, inuse); + (struct sockaddr*)addr, addrlen, 1, inuse, &noproto); } else { struct sockaddr_in* sa = (struct sockaddr_in*)addr; sa->sin_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET, SOCK_DGRAM, - (struct sockaddr*)addr, addrlen, 1, inuse); + (struct sockaddr*)addr, addrlen, 1, inuse, &noproto); } return fd; } diff --git a/testcode/delayer.c b/testcode/delayer.c index 37240a520..f6e089571 100644 --- a/testcode/delayer.c +++ b/testcode/delayer.c @@ -364,7 +364,11 @@ service_send(struct ringbuf* ring, struct timeval* now, ldns_buffer* pkt, ldns_buffer_limit(pkt), 0, (struct sockaddr*)srv_addr, srv_len); if(sent == -1) { +#ifndef USE_WINSOCK log_err("sendto: %s", strerror(errno)); +#else + log_err("sendto: %s", wsa_strerror(WSAGetLastError())); +#endif } else if(sent != (ssize_t)ldns_buffer_limit(pkt)) { log_err("sendto: partial send"); } @@ -383,9 +387,16 @@ do_proxy(struct proxy* p, int retsock, ldns_buffer* pkt) r = recv(p->s, ldns_buffer_begin(pkt), ldns_buffer_capacity(pkt), 0); if(r == -1) { +#ifndef USE_WINSOCK if(errno == EAGAIN || errno == EINTR) return; log_err("recv: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAEWOULDBLOCK) + return; + log_err("recv: %s", wsa_strerror(WSAGetLastError())); +#endif return; } ldns_buffer_set_limit(pkt, (size_t)r); @@ -395,7 +406,11 @@ do_proxy(struct proxy* p, int retsock, ldns_buffer* pkt) r = sendto(retsock, ldns_buffer_begin(pkt), (size_t)r, 0, (struct sockaddr*)&p->addr, p->addr_len); if(r == -1) { +#ifndef USE_WINSOCK log_err("sendto: %s", strerror(errno)); +#else + log_err("sendto: %s", wsa_strerror(WSAGetLastError())); +#endif } } } @@ -445,7 +460,13 @@ find_create_proxy(struct sockaddr_storage* from, socklen_t from_len, p = (struct proxy*)calloc(1, sizeof(*p)); if(!p) fatal_exit("out of memory"); p->s = socket(serv_ip6?AF_INET6:AF_INET, SOCK_DGRAM, 0); - if(p->s == -1) fatal_exit("socket: %s", strerror(errno)); + if(p->s == -1) { +#ifndef USE_WINSOCK + fatal_exit("socket: %s", strerror(errno)); +#else + fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } fd_set_nonblock(p->s); memmove(&p->addr, from, from_len); p->addr_len = from_len; @@ -475,9 +496,17 @@ service_recv(int s, struct ringbuf* ring, ldns_buffer* pkt, ldns_buffer_capacity(pkt), 0, (struct sockaddr*)&from, &from_len); if(len < 0) { +#ifndef USE_WINSOCK if(errno == EAGAIN || errno == EINTR) return; fatal_exit("recvfrom: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEWOULDBLOCK || + WSAGetLastError() == WSAEINPROGRESS) + return; + fatal_exit("recvfrom: %s", + wsa_strerror(WSAGetLastError())); +#endif } ldns_buffer_set_limit(pkt, (size_t)len); /* find its proxy element */ @@ -531,9 +560,17 @@ service_tcp_listen(int s, fd_set* rorig, int* max, struct tcp_proxy** proxies, socklen_t addr_len; newfd = accept(s, (struct sockaddr*)&addr, &addr_len); if(newfd == -1) { +#ifndef USE_WINSOCK if(errno == EAGAIN || errno == EINTR) return; fatal_exit("accept: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEWOULDBLOCK || + WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAECONNRESET) + return; + fatal_exit("accept: %s", wsa_strerror(WSAGetLastError())); +#endif } p = (struct tcp_proxy*)calloc(1, sizeof(*p)); if(!p) fatal_exit("out of memory"); @@ -543,17 +580,24 @@ service_tcp_listen(int s, fd_set* rorig, int* max, struct tcp_proxy** proxies, p->client_s = newfd; p->server_s = socket(addr_is_ip6(srv_addr, srv_len)?AF_INET6:AF_INET, SOCK_STREAM, 0); - if(p->server_s == -1) + if(p->server_s == -1) { +#ifndef USE_WINSOCK fatal_exit("tcp socket: %s", strerror(errno)); +#else + fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } fd_set_nonblock(p->client_s); fd_set_nonblock(p->server_s); if(connect(p->server_s, (struct sockaddr*)srv_addr, srv_len) == -1) { -#ifdef EINPROGRESS +#ifndef USE_WINSOCK if(errno != EINPROGRESS) { log_err("tcp connect: %s", strerror(errno)); #else - if(WSAGetLastError() != WSAEWOULDBLOCK) { - log_err("tcp connect: %d", WSAGetLastError()); + if(WSAGetLastError() != WSAEWOULDBLOCK && + WSAGetLastError() != WSAEINPROGRESS) { + log_err("tcp connect: %s", + wsa_strerror(WSAGetLastError())); #endif close(p->server_s); close(p->client_s); @@ -584,11 +628,19 @@ tcp_relay_read(int s, struct tcp_send_list** first, struct timeval* delay, ldns_buffer* pkt) { struct tcp_send_list* item; - ssize_t r = read(s, ldns_buffer_begin(pkt), ldns_buffer_capacity(pkt)); + ssize_t r = recv(s, ldns_buffer_begin(pkt), + ldns_buffer_capacity(pkt), 0); if(r == -1) { +#ifndef USE_WINSOCK if(errno == EINTR || errno == EAGAIN) return 1; log_err("tcp read: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAEWOULDBLOCK) + return 1; + log_err("tcp read: %s", wsa_strerror(WSAGetLastError())); +#endif return 0; } else if(r == 0) { /* connection closed */ @@ -635,11 +687,19 @@ tcp_relay_write(int s, struct tcp_send_list** first, if(!dl_tv_smaller(&p->wait, now)) return 1; /* write it */ - r = write(s, p->item + p->done, p->len - p->done); + r = send(s, (void*)(p->item + p->done), p->len - p->done, 0); if(r == -1) { +#ifndef USE_WINSOCK if(errno == EAGAIN || errno == EINTR) return 1; log_err("tcp write: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEWOULDBLOCK || + WSAGetLastError() == WSAEINPROGRESS) + return 1; + log_err("tcp write: %s", + wsa_strerror(WSAGetLastError())); +#endif return 0; } else if(r == 0) { /* closed */ @@ -947,8 +1007,13 @@ service(char* bind_str, int bindport, char* serv_str, size_t memsize, fatal_exit("could not bind to signal"); /* bind UDP port */ if((s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, - SOCK_DGRAM, 0)) == -1) + SOCK_DGRAM, 0)) == -1) { +#ifndef USE_WINSOCK fatal_exit("socket: %s", strerror(errno)); +#else + fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } i=0; if(bindport == 0) { bindport = 1024 + random()%64000; @@ -969,8 +1034,13 @@ service(char* bind_str, int bindport, char* serv_str, size_t memsize, fd_set_nonblock(s); /* and TCP port */ if((listen_s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, - SOCK_STREAM, 0)) == -1) + SOCK_STREAM, 0)) == -1) { +#ifndef USE_WINSOCK fatal_exit("tcp socket: %s", strerror(errno)); +#else + fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } #ifdef SO_REUSEADDR if(1) { int on = 1; diff --git a/testcode/do-tests.sh b/testcode/do-tests.sh index 16828e284..a50299e9e 100755 --- a/testcode/do-tests.sh +++ b/testcode/do-tests.sh @@ -6,6 +6,7 @@ NEED_LDNS_TESTNS='fwd_no_edns.tpkg fwd_tcp_tc.tpkg fwd_tcp.tpkg fwd_three_servic NEED_XXD='fwd_compress_c00c.tpkg' NEED_NC='fwd_compress_c00c.tpkg' NEED_CURL='06-ianaports.tpkg' +NEED_WHOAMI='07-confroot.tpkg' cd testdata; sh ../testcode/mini_tpkg.sh clean @@ -42,6 +43,11 @@ for test in `ls *.tpkg`; do SKIP=1; fi fi + if echo $NEED_WHOAMI | grep $test >/dev/null; then + if test ! -x "`which whoami`"; then + SKIP=1; + fi + fi if test $SKIP -eq 0; then echo $test sh ../testcode/mini_tpkg.sh -a ../.. exe $test diff --git a/testcode/perf.c b/testcode/perf.c index 3f8b331ec..feb2b4ba6 100644 --- a/testcode/perf.c +++ b/testcode/perf.c @@ -225,8 +225,14 @@ perfsetup(struct perfinfo* info) info->io[i].fd = socket( addr_is_ip6(&info->dest, info->destlen)? AF_INET6:AF_INET, SOCK_DGRAM, 0); - if(info->io[i].fd == -1) + if(info->io[i].fd == -1) { +#ifndef USE_WINSOCK fatal_exit("socket: %s", strerror(errno)); +#else + fatal_exit("socket: %s", + wsa_strerror(WSAGetLastError())); +#endif + } if(info->io[i].fd > info->maxfd) info->maxfd = info->io[i].fd; #ifndef S_SPLINT_S @@ -267,9 +273,13 @@ perfsend(struct perfinfo* info, size_t n, struct timeval* now) (struct sockaddr*)&info->dest, info->destlen); /*log_hex("send", info->qlist_data[info->qlist_idx], info->qlist_len[info->qlist_idx]);*/ - if(r == -1) + if(r == -1) { +#ifndef USE_WINSOCK log_err("sendto: %s", strerror(errno)); - else if(r != (ssize_t)info->qlist_len[info->qlist_idx]) { +#else + log_err("sendto: %s", wsa_strerror(WSAGetLastError())); +#endif + } else if(r != (ssize_t)info->qlist_len[info->qlist_idx]) { log_err("partial sendto"); } info->qlist_idx = (info->qlist_idx+1) % info->qlist_size; @@ -288,7 +298,11 @@ perfreply(struct perfinfo* info, size_t n, struct timeval* now) r = recv(info->io[n].fd, ldns_buffer_begin(info->buf), ldns_buffer_capacity(info->buf), 0); if(r == -1) { +#ifndef USE_WINSOCK log_err("recv: %s", strerror(errno)); +#else + log_err("recv: %s", wsa_strerror(WSAGetLastError())); +#endif } else { info->by_rcode[LDNS_RCODE_WIRE(ldns_buffer_begin( info->buf))]++; @@ -559,6 +573,10 @@ int main(int argc, char* argv[]) char* nm = argv[0]; int c; struct perfinfo info; +#ifdef USE_WINSOCK + int r; + WSADATA wsa_data; +#endif /* defaults */ memset(&info, 0, sizeof(info)); @@ -567,6 +585,10 @@ int main(int argc, char* argv[]) log_init(NULL, 0, NULL); log_ident_set("perf"); checklock_start(); +#ifdef USE_WINSOCK + if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) + fatal_exit("WSAStartup failed: %s", wsa_strerror(r)); +#endif info.buf = ldns_buffer_new(65553); if(!info.buf) fatal_exit("out of memory"); @@ -616,6 +638,9 @@ int main(int argc, char* argv[]) perfmain(&info); ldns_buffer_free(info.buf); +#ifdef USE_WINSOCK + WSACleanup(); +#endif checklock_stop(); return 0; } diff --git a/testcode/streamtcp.c b/testcode/streamtcp.c index 9fa7ddc4c..f646cb519 100644 --- a/testcode/streamtcp.c +++ b/testcode/streamtcp.c @@ -73,11 +73,19 @@ open_svr(char* svr) fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET, SOCK_STREAM, 0); if(fd == -1) { +#ifndef USE_WINSOCK perror("socket() error"); +#else + printf("socket: %s\n", wsa_strerror(WSAGetLastError())); +#endif exit(1); } if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { +#ifndef USE_WINSOCK perror("connect() error"); +#else + printf("connect: %s\n", wsa_strerror(WSAGetLastError())); +#endif exit(1); } return fd; @@ -115,13 +123,21 @@ write_q(int fd, ldns_buffer* buf, int id, /* send it */ len = (uint16_t)ldns_buffer_limit(buf); len = htons(len); - if(write(fd, &len, sizeof(len)) < (ssize_t)sizeof(len)) { - perror("write() len failed"); + if(send(fd, (void*)&len, sizeof(len), 0) < (ssize_t)sizeof(len)) { +#ifndef USE_WINSOCK + perror("send() len failed"); +#else + printf("send len: %s\n", wsa_strerror(WSAGetLastError())); +#endif exit(1); } - if(write(fd, ldns_buffer_begin(buf), ldns_buffer_limit(buf)) < + if(send(fd, ldns_buffer_begin(buf), ldns_buffer_limit(buf), 0) < (ssize_t)ldns_buffer_limit(buf)) { - perror("write() data failed"); +#ifndef USE_WINSOCK + perror("send() data failed"); +#else + printf("send data: %s\n", wsa_strerror(WSAGetLastError())); +#endif exit(1); } @@ -135,15 +151,23 @@ recv_one(int fd, ldns_buffer* buf) uint16_t len; ldns_pkt* pkt; ldns_status status; - if(read(fd, &len, sizeof(len)) < (ssize_t)sizeof(len)) { + if(recv(fd, (void*)&len, sizeof(len), 0) < (ssize_t)sizeof(len)) { +#ifndef USE_WINSOCK perror("read() len failed"); +#else + printf("read len: %s\n", wsa_strerror(WSAGetLastError())); +#endif exit(1); } len = ntohs(len); ldns_buffer_clear(buf); ldns_buffer_set_limit(buf, len); - if(read(fd, ldns_buffer_begin(buf), len) < (ssize_t)len) { + if(recv(fd, ldns_buffer_begin(buf), len, 0) < (ssize_t)len) { +#ifndef USE_WINSOCK perror("read() data failed"); +#else + printf("read data: %s\n", wsa_strerror(WSAGetLastError())); +#endif exit(1); } printf("\nnext received packet\n"); @@ -203,6 +227,13 @@ int main(int argc, char** argv) { int c; char* svr = "127.0.0.1"; +#ifdef USE_WINSOCK + WSADATA wsa_data; + if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) { + printf("WSAStartup failed\n"); + return 1; + } +#endif /* lock debug start (if any) */ log_init(0, 0, 0); @@ -239,5 +270,8 @@ int main(int argc, char** argv) } send_em(svr, argc, argv); checklock_stop(); +#ifdef USE_WINSOCK + WSACleanup(); +#endif return 0; } diff --git a/util/netevent.c b/util/netevent.c index 13aedee70..9cf71b5f9 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -222,7 +222,12 @@ comm_point_send_udp_msg(struct comm_point *c, ldns_buffer* packet, ldns_buffer_remaining(packet), 0, addr, addrlen); if(sent == -1) { +#ifndef USE_WINSOCK verbose(VERB_OPS, "sendto failed: %s", strerror(errno)); +#else + verbose(VERB_OPS, "sendto failed: %s", + wsa_strerror(WSAGetLastError())); +#endif log_addr(VERB_OPS, "remote address is", (struct sockaddr_storage*)addr, addrlen); return 0; @@ -491,9 +496,16 @@ comm_point_udp_callback(int fd, short event, void* arg) ldns_buffer_remaining(rep.c->buffer), 0, (struct sockaddr*)&rep.addr, &rep.addrlen); if(recv == -1) { - if(errno != EAGAIN && errno != EINTR) { +#ifndef USE_WINSOCK + if(errno != EAGAIN && errno != EINTR) log_err("recvfrom failed: %s", strerror(errno)); - } +#else + if(WSAGetLastError() != WSAEINPROGRESS && + WSAGetLastError() != WSAECONNRESET && + WSAGetLastError()!= WSAEWOULDBLOCK) + log_err("recvfrom failed: %s", + wsa_strerror(WSAGetLastError())); +#endif return; } ldns_buffer_skip(rep.c->buffer, recv); @@ -545,6 +557,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) new_fd = accept(fd, (struct sockaddr*)&c_hdl->repinfo.addr, &c_hdl->repinfo.addrlen); if(new_fd == -1) { +#ifndef USE_WINSOCK /* EINTR is signal interrupt. others are closed connection. */ if( errno != EINTR #ifdef EWOULDBLOCK @@ -559,6 +572,13 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) ) return; log_err("accept failed: %s", strerror(errno)); +#else /* USE_WINSOCK */ + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAEWOULDBLOCK || + WSAGetLastError() == WSAECONNRESET) + return; + log_err("accept failed: %s", wsa_strerror(WSAGetLastError())); +#endif log_addr(0, "remote address is", &c_hdl->repinfo.addr, c_hdl->repinfo.addrlen); return; @@ -637,11 +657,12 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) log_assert(fd != -1); if(c->tcp_byte_count < sizeof(uint16_t)) { /* read length bytes */ - r = read(fd, ldns_buffer_at(c->buffer, c->tcp_byte_count), - sizeof(uint16_t)-c->tcp_byte_count); + r = recv(fd, ldns_buffer_at(c->buffer, c->tcp_byte_count), + sizeof(uint16_t)-c->tcp_byte_count, 0); if(r == 0) return 0; else if(r == -1) { +#ifndef USE_WINSOCK if(errno == EINTR || errno == EAGAIN) return 1; #ifdef ECONNRESET @@ -649,6 +670,14 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) return 0; /* silence reset by peer */ #endif log_err("read (in tcp s): %s", strerror(errno)); +#else /* USE_WINSOCK */ + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAECONNRESET || + WSAGetLastError() == WSAEWOULDBLOCK) + return 1; + log_err("read (in tcp s): %s", + wsa_strerror(WSAGetLastError())); +#endif log_addr(0, "remote address is", &c->repinfo.addr, c->repinfo.addrlen); return 0; @@ -673,14 +702,23 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) } log_assert(ldns_buffer_remaining(c->buffer) > 0); - r = read(fd, ldns_buffer_current(c->buffer), - ldns_buffer_remaining(c->buffer)); + r = recv(fd, ldns_buffer_current(c->buffer), + ldns_buffer_remaining(c->buffer), 0); if(r == 0) { return 0; } else if(r == -1) { +#ifndef USE_WINSOCK if(errno == EINTR || errno == EAGAIN) return 1; log_err("read (in tcp r): %s", strerror(errno)); +#else /* USE_WINSOCK */ + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAECONNRESET || + WSAGetLastError() == WSAEWOULDBLOCK) + return 1; + log_err("read (in tcp r): %s", + wsa_strerror(WSAGetLastError())); +#endif log_addr(0, "remote address is", &c->repinfo.addr, c->repinfo.addrlen); return 0; @@ -747,12 +785,20 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) log_assert(iov[1].iov_len > 0); r = writev(fd, iov, 2); #else /* HAVE_WRITEV */ - r = write(fd, &len, sizeof(uint16_t)); + r = send(fd, (void*)&len, sizeof(uint16_t), 0); #endif /* HAVE_WRITEV */ if(r == -1) { +#ifndef USE_WINSOCK if(errno == EINTR || errno == EAGAIN) return 1; log_err("tcp writev: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAEWOULDBLOCK) + return 1; + log_err("tcp send s: %s", + wsa_strerror(WSAGetLastError())); +#endif log_addr(0, "remote address is", &c->repinfo.addr, c->repinfo.addrlen); return 0; @@ -764,16 +810,24 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) sizeof(uint16_t)); if(ldns_buffer_remaining(c->buffer) == 0) { tcp_callback_writer(c); + return 1; } - return 1; } log_assert(ldns_buffer_remaining(c->buffer) > 0); - r = write(fd, ldns_buffer_current(c->buffer), - ldns_buffer_remaining(c->buffer)); + r = send(fd, ldns_buffer_current(c->buffer), + ldns_buffer_remaining(c->buffer), 0); if(r == -1) { +#ifndef USE_WINSOCK if(errno == EINTR || errno == EAGAIN) return 1; - log_err("tcp write: %s", strerror(errno)); + log_err("tcp send r: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAEWOULDBLOCK) + return 1; + log_err("tcp send r: %s", + wsa_strerror(WSAGetLastError())); +#endif log_addr(0, "remote address is", &c->repinfo.addr, c->repinfo.addrlen); return 0; diff --git a/util/winsock_event.c b/util/winsock_event.c index 07ac22430..c1ccb5aad 100644 --- a/util/winsock_event.c +++ b/util/winsock_event.c @@ -239,8 +239,8 @@ static int handle_select(struct event_base* base, struct timeval* wait) short bits = 0; /* eventlist[i] fired */ if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, - /*waitfor[i],*/ /* reset the event handle */ - NULL, /* do not reset the event handle */ + waitfor[i], /* reset the event handle */ + /*NULL,*/ /* do not reset the event handle */ &netev) != 0) { log_err("WSAEnumNetworkEvents failed: %s", wsa_strerror(WSAGetLastError())); @@ -279,6 +279,20 @@ static int handle_select(struct event_base* base, struct timeval* wait) bits |= EV_WRITE; } if(bits) { + verbose(VERB_ALGO, "winsock event callback %p fd=%d " + "%s%s%s%s%s ; %s%s%s", + eventlist[i], eventlist[i]->ev_fd, + (netev.lNetworkEvents&FD_READ)?" FD_READ":"", + (netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"", + (netev.lNetworkEvents&FD_CONNECT)? + " FD_CONNECT":"", + (netev.lNetworkEvents&FD_ACCEPT)? + " FD_ACCEPT":"", + (netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"", + (bits&EV_READ)?" EV_READ":"", + (bits&EV_WRITE)?" EV_WRITE":"", + (bits&EV_TIMEOUT)?" EV_TIMEOUT":""); + fptr_ok(fptr_whitelist_event( eventlist[i]->ev_callback)); (*eventlist[i]->ev_callback)(eventlist[i]->ev_fd, @@ -350,6 +364,12 @@ int event_base_set(struct event_base *base, struct event *ev) int event_add(struct event *ev, struct timeval *tv) { + verbose(VERB_ALGO, "event_add %p added=%d fd=%d tv=%d %s%s%s", + ev, ev->added, ev->ev_fd, + (tv?(int)tv->tv_sec*1000+(int)tv->tv_usec/1000:-1), + (ev->ev_events&EV_READ)?" EV_READ":"", + (ev->ev_events&EV_WRITE)?" EV_WRITE":"", + (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); if(ev->added) event_del(ev); log_assert(ev->ev_fd==-1 || find_fd(ev->ev_base, ev->ev_fd) == -1); @@ -414,6 +434,13 @@ int event_add(struct event *ev, struct timeval *tv) int event_del(struct event *ev) { + verbose(VERB_ALGO, "event_del %p added=%d fd=%d tv=%d %s%s%s", + ev, ev->added, ev->ev_fd, + (ev->ev_events&EV_TIMEOUT)?(int)ev->ev_timeout.tv_sec*1000+ + (int)ev->ev_timeout.tv_usec/1000:-1, + (ev->ev_events&EV_READ)?" EV_READ":"", + (ev->ev_events&EV_WRITE)?" EV_WRITE":"", + (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); if(!ev->added) return 0; log_assert(ev->added && ev->ev_base->max > 0) diff --git a/util/winsock_event.h b/util/winsock_event.h index 37ce3f915..6dec399da 100644 --- a/util/winsock_event.h +++ b/util/winsock_event.h @@ -66,6 +66,9 @@ * * Socket numbers are not starting small, they can be any number (say 33060). * Therefore, bitmaps are not used, but arrays. + * + * on winsock, you must use recv() and send() for TCP reads and writes, + * not read() and write(), those work only on files. */ #ifndef UTIL_WINSOCK_EVENT_H