aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Fandrich <dan@coneharvesters.com>2008-06-03 18:03:11 +0000
committerDan Fandrich <dan@coneharvesters.com>2008-06-03 18:03:11 +0000
commit6f0a2608b45f83064759b3585a282de5be584966 (patch)
tree39c8ad73cc6b03b0b1bafa9279f5e719c4005c7c
parentea86edbd821fc448a4188598d18aa8ce12bb435a (diff)
Fixed a problem where telnet data would be lost if an EWOULDBLOCK
condition were encountered.
-rw-r--r--CHANGES4
-rw-r--r--RELEASE-NOTES1
-rw-r--r--lib/telnet.c104
3 files changed, 63 insertions, 46 deletions
diff --git a/CHANGES b/CHANGES
index 868e6ce0a..8eddff09e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,10 @@
Changelog
+Daniel Fandrich (3 Jun 2008)
+- Fixed a problem where telnet data would be lost if an EWOULDBLOCK
+ condition were encountered.
+
Marty Kuhrt (1 Jun 2008)
- Updated main.c to return CURLE_OK if PARAM_HELP_REQUESTED was returned
from getparameter instead of CURLE_FAILED_INIT. No point in returning
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 117a6f8c6..3e6cbf817 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -40,6 +40,7 @@ This release includes the following bugfixes:
o follow redirect with only a new query string
o SCP and SFTP memory leaks on aborted transfers
o curl_multi_socket() and HTTP pipelining transfer stalls
+ o lost telnet data on an EWOULDBLOCK condition
This release includes the following known bugs:
diff --git a/lib/telnet.c b/lib/telnet.c
index a531e6743..c44658914 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -1117,6 +1117,46 @@ void telrcv(struct connectdata *conn,
bufferflush();
}
+/* Escape and send a telnet data block */
+/* TODO: write large chunks of data instead of one byte at a time */
+static CURLcode send_telnet_data(struct connectdata *conn,
+ char *buffer, ssize_t nread)
+{
+ unsigned char outbuf[2];
+ ssize_t bytes_written, total_written;
+ int out_count;
+ CURLcode rc = CURLE_OK;
+
+ while(rc == CURLE_OK && nread--) {
+ outbuf[0] = *buffer++;
+ out_count = 1;
+ if(outbuf[0] == CURL_IAC)
+ outbuf[out_count++] = CURL_IAC;
+
+ total_written = 0;
+ do {
+ /* Make sure socket is writable to avoid EWOULDBLOCK condition */
+ struct pollfd pfd[1];
+ pfd[0].fd = conn->sock[FIRSTSOCKET];
+ pfd[0].events = POLLOUT;
+ switch (Curl_poll(pfd, 1, -1)) {
+ case -1: /* error, abort writing */
+ case 0: /* timeout (will never happen) */
+ rc = CURLE_SEND_ERROR;
+ break;
+ default: /* write! */
+ bytes_written = 0;
+ rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written,
+ out_count-total_written, &bytes_written);
+ total_written += bytes_written;
+ break;
+ }
+ /* handle partial write */
+ } while (rc == CURLE_OK && total_written < out_count);
+ }
+ return rc;
+}
+
static CURLcode telnet_done(struct connectdata *conn,
CURLcode status, bool premature)
{
@@ -1270,63 +1310,45 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
switch(waitret) {
case WAIT_TIMEOUT:
{
- unsigned char outbuf[2];
- int out_count = 0;
- ssize_t bytes_written;
- char *buffer = buf;
-
while(1) {
if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
keepon = FALSE;
+ code = CURLE_READ_ERROR;
break;
}
- nread = readfile_read;
- if(!nread)
+ if(!readfile_read)
break;
if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
&readfile_read, NULL)) {
keepon = FALSE;
+ code = CURLE_READ_ERROR;
break;
}
- nread = readfile_read;
- while(nread--) {
- outbuf[0] = *buffer++;
- out_count = 1;
- if(outbuf[0] == CURL_IAC)
- outbuf[out_count++] = CURL_IAC;
-
- Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
- out_count, &bytes_written);
- }
+ code = send_telnet_data(conn, buf, readfile_read);
+ if(code) {
+ keepon = FALSE;
+ break;
+ }
}
}
break;
case WAIT_OBJECT_0 + 1:
{
- unsigned char outbuf[2];
- int out_count = 0;
- ssize_t bytes_written;
- char *buffer = buf;
-
if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
&readfile_read, NULL)) {
keepon = FALSE;
+ code = CURLE_READ_ERROR;
break;
}
- nread = readfile_read;
- while(nread--) {
- outbuf[0] = *buffer++;
- out_count = 1;
- if(outbuf[0] == CURL_IAC)
- outbuf[out_count++] = CURL_IAC;
-
- Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
- out_count, &bytes_written);
+ code = send_telnet_data(conn, buf, readfile_read);
+ if(code) {
+ keepon = FALSE;
+ break;
}
}
break;
@@ -1389,22 +1411,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break;
default: /* read! */
if(pfd[1].revents & POLLIN) { /* read from stdin */
- unsigned char outbuf[2];
- int out_count = 0;
- ssize_t bytes_written;
- char *buffer = buf;
-
nread = read(0, buf, 255);
-
- while(nread--) {
- outbuf[0] = *buffer++;
- out_count = 1;
- if(outbuf[0] == CURL_IAC)
- outbuf[out_count++] = CURL_IAC;
-
- Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
- out_count, &bytes_written);
- }
+ code = send_telnet_data(conn, buf, nread);
+ if(code) {
+ keepon = FALSE;
+ break;
+ }
}
if(pfd[0].revents & POLLIN) {