From 895f7c9ab4f276b76344d882d4aadcc2460e1687 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 19 Dec 2007 18:39:59 +0000 Subject: [PATCH] * Curl 7.17.1. * Added a patch to fix --retry in case of connection timeouts when --connect-timeout is used. (--retry is still broken when --connect-timeout isn't used.) svn path=/nixpkgs/trunk/; revision=9956 --- .../networking/curl/connect-timeout.patch | 156 ++++++++++++++++++ pkgs/tools/networking/curl/default.nix | 17 +- 2 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 pkgs/tools/networking/curl/connect-timeout.patch diff --git a/pkgs/tools/networking/curl/connect-timeout.patch b/pkgs/tools/networking/curl/connect-timeout.patch new file mode 100644 index 00000000000..829c724c30e --- /dev/null +++ b/pkgs/tools/networking/curl/connect-timeout.patch @@ -0,0 +1,156 @@ +diff -rc curl-7.17.1-orig/lib/connect.c curl-7.17.1/lib/connect.c +*** curl-7.17.1-orig/lib/connect.c 2007-10-22 16:30:17.000000000 +0200 +--- curl-7.17.1/lib/connect.c 2007-12-19 18:30:32.000000000 +0100 +*************** +*** 99,105 **** + singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, /* start connecting to this */ + long timeout_ms, +! bool *connected); + + /* + * Curl_nonblock() set the given socket to either blocking or non-blocking +--- 99,106 ---- + singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, /* start connecting to this */ + long timeout_ms, +! bool *connected, +! bool *timed_out); + + /* + * Curl_nonblock() set the given socket to either blocking or non-blocking +*************** +*** 492,497 **** +--- 493,499 ---- + { + curl_socket_t sockfd; + Curl_addrinfo *ai; ++ bool timed_out; + + /* first close the failed socket */ + sclose(conn->sock[sockindex]); +*************** +*** 505,511 **** + ai = conn->ip_addr->ai_next; + + while (ai) { +! sockfd = singleipconnect(conn, ai, 0L, connected); + if(sockfd != CURL_SOCKET_BAD) { + /* store the new socket descriptor */ + conn->sock[sockindex] = sockfd; +--- 507,513 ---- + ai = conn->ip_addr->ai_next; + + while (ai) { +! sockfd = singleipconnect(conn, ai, 0L, connected, &timed_out); + if(sockfd != CURL_SOCKET_BAD) { + /* store the new socket descriptor */ + conn->sock[sockindex] = sockfd; +*************** +*** 669,675 **** + singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, + long timeout_ms, +! bool *connected) + { + char addr_buf[128]; + int rc; +--- 671,678 ---- + singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, + long timeout_ms, +! bool *connected, +! bool *timed_out) + { + char addr_buf[128]; + int rc; +*************** +*** 689,694 **** +--- 692,699 ---- + struct curl_sockaddr *addr=(struct curl_sockaddr*)&addr_storage; + const void *iptoprint; + ++ *timed_out = FALSE; ++ + addr->family=ai->ai_family; + addr->socktype=conn->socktype; + addr->protocol=ai->ai_protocol; +*************** +*** 790,797 **** + infof(data, "connected\n"); + return sockfd; + } +! else if(WAITCONN_TIMEOUT == rc) + infof(data, "Timeout\n"); + else { + data->state.os_errno = error; + infof(data, "%s\n", Curl_strerror(conn, error)); +--- 795,804 ---- + infof(data, "connected\n"); + return sockfd; + } +! else if(WAITCONN_TIMEOUT == rc) { +! *timed_out = TRUE; + infof(data, "Timeout\n"); ++ } + else { + data->state.os_errno = error; + infof(data, "%s\n", Curl_strerror(conn, error)); +*************** +*** 822,829 **** + Curl_addrinfo *ai; + Curl_addrinfo *curr_addr; + int timeout_set = 0; + +- struct timeval after; + struct timeval before = Curl_tvnow(); + + /************************************************************* +--- 829,836 ---- + Curl_addrinfo *ai; + Curl_addrinfo *curr_addr; + int timeout_set = 0; ++ bool timed_out; + + struct timeval before = Curl_tvnow(); + + /************************************************************* +*************** +*** 891,909 **** + curr_addr = curr_addr->ai_next, aliasindex++) { + + /* start connecting to the IP curr_addr points to */ +! sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected); + + if(sockfd != CURL_SOCKET_BAD) + break; + +! /* get a new timeout for next attempt */ +! after = Curl_tvnow(); +! timeout_ms -= Curl_tvdiff(after, before); +! if(timeout_ms < 0) { + failf(data, "connect() timed out!"); + return CURLE_OPERATION_TIMEDOUT; + } +- before = after; + } /* end of connect-to-each-address loop */ + + if (sockfd == CURL_SOCKET_BAD) { +--- 898,914 ---- + curr_addr = curr_addr->ai_next, aliasindex++) { + + /* start connecting to the IP curr_addr points to */ +! sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected, &timed_out); + + if(sockfd != CURL_SOCKET_BAD) + break; + +! /* if this is the last address and it timed out, propagate the +! timeout to the caller */ +! if(!curr_addr->ai_next && timed_out) { + failf(data, "connect() timed out!"); + return CURLE_OPERATION_TIMEDOUT; + } + } /* end of connect-to-each-address loop */ + + if (sockfd == CURL_SOCKET_BAD) { diff --git a/pkgs/tools/networking/curl/default.nix b/pkgs/tools/networking/curl/default.nix index 21866f02bc8..7f3488b2f35 100644 --- a/pkgs/tools/networking/curl/default.nix +++ b/pkgs/tools/networking/curl/default.nix @@ -4,10 +4,10 @@ assert zlibSupport -> zlib != null; assert sslSupport -> openssl != null; stdenv.mkDerivation { - name = "curl-7.16.2"; + name = "curl-7.17.1"; src = fetchurl { - url = http://curl.haxx.se/download/curl-7.16.2.tar.bz2; - sha256 = "18mzp56y8qhlvi27av7866mvsiyiigb7c5qdppjr8qizsj0kx0rf"; + url = http://curl.haxx.se/download/curl-7.17.1.tar.bz2; + sha256 = "0yz50r75jhfr2ya6wqi6n90bn4ij30299pjglmlckzq6jp28wrkz"; }; buildInputs = stdenv.lib.optional zlibSupport zlib ++ @@ -19,4 +19,15 @@ stdenv.mkDerivation { CXX = "g++"; CXXCPP = "g++ -E"; inherit sslSupport openssl; + + patches = [ + /* Fixes broken retry support when a timeout is used. The + select() system call (used to wait for the connection to come + up) can return slightly before the computed deadline (a few + milliseconds). Curl will think the problem is something else, + proceed with the next IP address (which usually doesn't exist), + then barf with a CURLE_COULDNT_CONNECT error, which is + considered non-transient so it won't retry. */ + ./connect-timeout.patch + ]; }