@matheusbsbs / matheus-bagliano / commits / 3944ba0cb0
Fork 0

Allow curl to rewind the read buffers

When using multi-pass authentication methods, the curl library may need to rewind the read buffers (depending on how much already has been fed to the server) used for providing data to HTTP PUT, POST or PROPFIND, and in order to allow the library to do so, we need to tell it how by providing either an ioctl callback or a seek callback. This patch adds an ioctl callback, which should be usable on older curl versions (since 7.12.3) than the seek callback (introduced in curl 7.18.0). Some HTTP servers (such as Apache) give an 401 error reply immediately after receiving the headers (so no data has been read from the read buffers, and thus no rewinding is needed), but other servers (such as Lighttpd) only replies after the whole request has been sent and all data has been read from the read buffers, making rewinding necessary. Signed-off-by: Martin Storsjo <martin@martin.st> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Martin Storsjö committed Apr 1, 2009 at 19:48 UTC 3944ba0cb0ef5119dc9d1708c572855fca88fc43
3 files changed +50
http-push.c
+24
@@ -567,6 +567,10 @@ static void start_put(struct transfer_request *request)
567 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
568 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.buf.len);
569 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
570 +#ifndef NO_CURL_IOCTL
571 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
572 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &request->buffer);
573 +#endif
574 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
575 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
576 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
@@ -1267,6 +1271,10 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
1271 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1272 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
1273 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1274 +#ifndef NO_CURL_IOCTL
1275 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1276 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1277 +#endif
1278 curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1279 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1280 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
@@ -1508,6 +1516,10 @@ static void remote_ls(const char *path, int flags,
1516 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1517 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
1518 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1519 +#ifndef NO_CURL_IOCTL
1520 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1521 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1522 +#endif
1523 curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1524 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1525 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
@@ -1584,6 +1596,10 @@ static int locking_available(void)
1596 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1597 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
1598 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1599 +#ifndef NO_CURL_IOCTL
1600 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1601 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1602 +#endif
1603 curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1604 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1605 curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
@@ -1766,6 +1782,10 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
1782 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1783 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
1784 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1785 +#ifndef NO_CURL_IOCTL
1786 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1787 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1788 +#endif
1789 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1790 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
1791 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
@@ -1910,6 +1930,10 @@ static void update_remote_info_refs(struct remote_lock *lock)
1930 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &buffer);
1931 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, buffer.buf.len);
1932 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1933 +#ifndef NO_CURL_IOCTL
1934 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1935 + curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &buffer);
1936 +#endif
1937 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1938 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
1939 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
http.c
+19
@@ -44,6 +44,25 @@ size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
44 return size;
45 }
46
47 +#ifndef NO_CURL_IOCTL
48 +curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
49 +{
50 + struct buffer *buffer = clientp;
51 +
52 + switch (cmd) {
53 + case CURLIOCMD_NOP:
54 + return CURLIOE_OK;
55 +
56 + case CURLIOCMD_RESTARTREAD:
57 + buffer->posn = 0;
58 + return CURLIOE_OK;
59 +
60 + default:
61 + return CURLIOE_UNKNOWNCMD;
62 + }
63 +}
64 +#endif
65 +
66 size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
67 {
68 size_t size = eltsize * nmemb;
http.h
+7
@@ -37,6 +37,10 @@
37 #define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
38 #endif
39
40 +#if LIBCURL_VERSION_NUM < 0x070c03
41 +#define NO_CURL_IOCTL
42 +#endif
43 +
44 struct slot_results
45 {
46 CURLcode curl_result;
@@ -67,6 +71,9 @@ struct buffer
71 extern size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
72 extern size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
73 extern size_t fwrite_null(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
74 +#ifndef NO_CURL_IOCTL
75 +extern curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
76 +#endif
77
78 /* Slot lifecycle functions */
79 extern struct active_request_slot *get_active_slot(void);