aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2009-06-15 21:13:00 +0000
committerDaniel Stenberg <daniel@haxx.se>2009-06-15 21:13:00 +0000
commit4b6d3a2bfdb46fd6a698b9218bbceea4ce865ac2 (patch)
treee990dab9f993fe625a285e8172d1f5ead7f2fab4 /src
parent7ae624e7004338683c659fe881c1847fe9ee708a (diff)
- 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.
Diffstat (limited to 'src')
-rw-r--r--src/main.c31
1 files changed, 29 insertions, 2 deletions
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)