aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES15
-rw-r--r--RELEASE-NOTES2
-rw-r--r--src/main.c31
3 files changed, 46 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index be16f61da..852d16da4 100644
--- 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.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index c4e9c2cb2..6c0c53984 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -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:
diff --git a/src/main.c b/src/main.c
index 663b7e32b..4abaace06 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)