]> granicus.if.org Git - curl/commitdiff
- Eric Wong's patch:
authorDaniel Stenberg <daniel@haxx.se>
Mon, 15 Jun 2009 21:13:00 +0000 (21:13 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 15 Jun 2009 21:13:00 +0000 (21:13 +0000)
  This allows curl(1) to be used as a client-side tunnel for arbitrary stream
  protocols by abusing chunked transfer encoding in both the HTTP request and
  HTTP response.  This requires server support for sending a response while a
  request is still being read, of course.

  If attempting to read from stdin returns EAGAIN, then we pause our sender.
  This leaves curl to attempt to read from the socket while reading from stdin
  (and thus sending) is paused.

CHANGES
RELEASE-NOTES
src/main.c

diff --git a/CHANGES b/CHANGES
index be16f61da5e308cd1db7566a704ca60eb668b136..852d16da4a3d56a387fdca5b763767706bd7aead 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,21 @@
 
                                   Changelog
 
+Daniel Stenberg (15 Jun 2009)
+- Eric Wong's patch:
+
+  This allows curl(1) to be used as a client-side tunnel for arbitrary stream
+  protocols by abusing chunked transfer encoding in both the HTTP request and
+  HTTP response.  This requires server support for sending a response while a
+  request is still being read, of course.
+
+  If attempting to read from stdin returns EAGAIN, then we pause our sender.
+  This leaves curl to attempt to read from the socket while reading from stdin
+  (and thus sending) is paused.
+
+  This change was needed to allow successfully tunneling the git protocol over
+  HTTP (--no-buffer is needed, as well).
+
 Patrick Monnerat (15 Jun 2009)
 - Replaced use of standard C library rand()/srand() by our own pseudo-random
   number generator.
index c4e9c2cb25c49db1a0536a627d66f961f20dc594..6c0c53984d878fef069d80b030a42a68f99f6ce1 100644 (file)
@@ -26,6 +26,8 @@ This release includes the following bugfixes:
  o djgpp build fix
  o configure detection of GnuTLS now based on pkg-config
  o libcurl-NSS client cert handling segfaults
+ o curl uploading from stdin/pipes now works in non-blocking way so that it
+   continues the downloading even when the read stalls
 
 This release includes the following known bugs:
 
index 663b7e32b9d0b62c38ae80c5ddfa2f631d5e2437..4abaace062e64a400a19fc44bf43df28a8007649 100644 (file)
@@ -498,6 +498,7 @@ struct Configurable {
   long httpversion;
   bool progressmode;
   bool nobuffer;
+  bool readbusy; /* set when reading input returns EAGAIN */
   bool globoff;
   bool use_httpget;
   bool insecure_ok; /* set TRUE to allow insecure SSL connects */
@@ -3230,6 +3231,19 @@ static void go_sleep(long ms)
 #endif
 }
 
+/* maybe we could just use Curl_nonblock() instead ... */
+static void set_nonblocking(struct Configurable *config, int fd)
+{
+#if defined(HAVE_FCNTL_O_NONBLOCK)
+  int flags = fcntl(fd, F_GETFL, 0);
+
+  if (flags >= 0)
+    flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+  else
+    warnf(config, "fcntl failed on fd=%d: %s\n", fd, strerror(errno));
+#endif
+}
+
 static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
 {
   size_t rc;
@@ -3259,6 +3273,11 @@ static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
     out->bytes += (sz * nmemb);
   }
 
+  if(config->readbusy) {
+    config->readbusy = false;
+    curl_easy_pause(config->easy, CURLPAUSE_CONT);
+  }
+
   if(config->nobuffer)
     /* disable output buffering */
     fflush(out->stream);
@@ -3324,9 +3343,16 @@ static size_t my_fread(void *buffer, size_t sz, size_t nmemb, void *userp)
   struct InStruct *in=(struct InStruct *)userp;
 
   rc = read(in->fd, buffer, sz*nmemb);
-  if(rc < 0)
+  if(rc < 0) {
+    if(errno == EAGAIN) {
+      errno = 0;
+      in->config->readbusy = true;
+      return CURL_READFUNC_PAUSE;
+    }
     /* since size_t is unsigned we can't return negative values fine */
-    return 0;
+    rc = 0;
+  }
+  in->config->readbusy = false;
   return (size_t)rc;
 }
 
@@ -4494,6 +4520,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
         else if(uploadfile && curlx_strequal(uploadfile, "-")) {
           SET_BINMODE(stdin);
           infd = STDIN_FILENO;
+          set_nonblocking(config, infd);
         }
 
         if(uploadfile && config->resume_from_current)