From: Wouter Wijngaards Date: Mon, 5 Oct 2009 09:19:41 +0000 (+0000) Subject: Better timeout handling. X-Git-Tag: release-1.6.2~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b07253f7663227eae1de8e2fb32e9bc55f2dc58a;p=thirdparty%2Fldns.git Better timeout handling. --- diff --git a/Changelog b/Changelog index 8fc5ea81..3138429d 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,7 @@ * bug273: fix so EDNS rdata is included in pkt to wire conversion. * bug274: fix use of c++ keyword 'class' for RR class in the code. * bug275: fix memory leak of packet edns rdata. + * Fix timeout procedure for TCP and AXFR on Solaris. 1.6.1 2009-09-14 * --enable-gost : use the GOST algorithm (experimental). diff --git a/ldns/net.h.in b/ldns/net.h.in index 9eb100fe..109a3f4d 100644 --- a/ldns/net.h.in +++ b/ldns/net.h.in @@ -134,7 +134,20 @@ ssize_t ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr * \return number of bytes sent */ ssize_t ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); + +/** + * Gives back a raw packet from the wire and reads the header data from the given + * socket. Allocates the data (of size size) itself, so don't forget to free + * + * \param[in] sockfd the socket to read from + * \param[out] size the number of bytes that are read + * \param[in] timeout the time allowed between packets. + * \return the data read + */ +uint8_t *ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout); + /** + * *DEPRECATED* please use ldns_tcp_read_wire_timeout, that checks for timeouts. * Gives back a raw packet from the wire and reads the header data from the given * socket. Allocates the data (of size size) itself, so don't forget to free * diff --git a/ldns_symbols.def b/ldns_symbols.def index 8e925f0f..3b1a0641 100644 --- a/ldns_symbols.def +++ b/ldns_symbols.def @@ -649,6 +649,7 @@ ldns_str2rdf_wks ldns_tcp_bgsend ldns_tcp_connect ldns_tcp_read_wire +ldns_tcp_read_wire_timeout ldns_tcp_send ldns_tcp_send_query ldns_traverse_postorder diff --git a/net.c b/net.c index 1ec4104d..89f83e85 100644 --- a/net.c +++ b/net.c @@ -497,6 +497,58 @@ ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from, return wire; } +uint8_t * +ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) +{ + uint8_t *wire; + uint16_t wire_size; + ssize_t bytes = 0; + + wire = LDNS_XMALLOC(uint8_t, 2); + if (!wire) { + *size = 0; + return NULL; + } + + while (bytes < 2) { + if(!ldns_sock_wait(sockfd, timeout, 0)) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + bytes = recv(sockfd, (void*)wire, 2, 0); + if (bytes == -1 || bytes == 0) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + } + + wire_size = ldns_read_uint16(wire); + + LDNS_FREE(wire); + wire = LDNS_XMALLOC(uint8_t, wire_size); + bytes = 0; + + while (bytes < (ssize_t) wire_size) { + if(!ldns_sock_wait(sockfd, timeout, 0)) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + bytes += recv(sockfd, (void*) (wire + bytes), + (size_t) (wire_size - bytes), 0); + if (bytes == -1 || bytes == 0) { + LDNS_FREE(wire); + *size = 0; + return NULL; + } + } + + *size = (size_t) bytes; + return wire; +} + uint8_t * ldns_tcp_read_wire(int sockfd, size_t *size) { @@ -555,12 +607,7 @@ ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storag return LDNS_STATUS_ERR; } - if(!ldns_sock_wait(sockfd, timeout, 0)) { - close(sockfd); - return LDNS_STATUS_NETWORK_ERR; - } - - answer = ldns_tcp_read_wire(sockfd, answer_size); + answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout); close(sockfd); if (*answer_size == 0) {