Commit 6f0a2608 authored by Dan Fandrich's avatar Dan Fandrich
Browse files

Fixed a problem where telnet data would be lost if an EWOULDBLOCK

condition were encountered.
parent ea86edbd
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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:

+58 −46
Original line number Diff line number Diff line
@@ -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,36 +1310,27 @@ 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;
	}
      }
    }
@@ -1307,26 +1338,17 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)

    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,21 +1411,11 @@ 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;
	}
      }