On Fri, 21 Aug 2009, Daniel Stenberg wrote:
Okay, here's a first rough patch that shows a little what I had in mind. It
should be improved and cleaned up, and I didn't even test it with SFTP or
anything - I just ran a few hundred test cases that seemed to all work fine
still.
Did I say it is rough? :-)
Here's a minor update that should make pause and bandwidth limiting etc to
still work too.
--
/ daniel.haxx.se
Index: lib/ssh.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ssh.c,v
retrieving revision 1.136
diff -u -r1.136 ssh.c
--- lib/ssh.c 23 Jul 2009 02:15:00 -0000 1.136
+++ lib/ssh.c 21 Aug 2009 12:18:40 -0000
@@ -2291,6 +2291,8 @@
/* It didn't block or libssh2 didn't reveal in which direction, put back
the original set */
sshc->waitfor = sshc->orig_waitfor;
+
+ conn->data->req.waitfor = sshc->waitfor;
}
#else
/* no libssh2 directional support so we simply don't know */
Index: lib/transfer.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/transfer.c,v
retrieving revision 1.436
diff -u -r1.436 transfer.c
--- lib/transfer.c 21 Aug 2009 12:01:36 -0000 1.436
+++ lib/transfer.c 21 Aug 2009 12:18:41 -0000
@@ -1640,6 +1640,7 @@
struct SingleRequest *k = &data->req;
CURLcode result;
int didwhat=0;
+ int keepon;
curl_socket_t fd_read;
curl_socket_t fd_write;
@@ -1647,27 +1648,43 @@
conn->cselect_bits = 0;
+ /*
+ * Theory:
+ *
+ * k->keepon holds the bits for the generic direction of the transfer. It
+ * means a download will have KEEP_RECV set. An upload has KEEP_SEND. Both
+ * can be set, like when you upload HTTP and expects to receive as well.
+ *
+ * Some protocols have both read and write during both download and upload.
+ * The 'waitfor' bits then come into play. If no waitfor bit is set, we use
+ * the keepon bits but if waitfor is set those are in control.
+ *
+ */
+ keepon = k->keepon;
+
+ if(k->waitfor) {
+ /* if waitfor is set, get the RECV and SEND bits from that but keep the
+ other bits */
+ keepon &= ~ (KEEP_RECV|KEEP_SEND);
+ keepon |= k->waitfor & (KEEP_RECV|KEEP_SEND);
+ }
+
/* only use the proper socket if the *_HOLD bit is not set simultaneously as
then we are in rate limiting state in that transfer direction */
- if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) {
+ if((keepon & KEEP_RECVBITS) == KEEP_RECV)
fd_read = conn->sockfd;
-#if defined(USE_LIBSSH2)
- if(conn->protocol & (PROT_SCP|PROT_SFTP))
- select_res |= CURL_CSELECT_IN;
-#endif /* USE_LIBSSH2 */
- } else
+ else
fd_read = CURL_SOCKET_BAD;
- if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
+ if((keepon & KEEP_SENDBITS) == KEEP_SEND)
fd_write = conn->writesockfd;
else
fd_write = CURL_SOCKET_BAD;
- if(!select_res) { /* Call for select()/poll() only, if read/write/error
- status is not known. */
- select_res = Curl_socket_ready(fd_read, fd_write, 0);
- }
+ if(!select_res)
+ /* Call select()/poll() only if read/write/error status is not known. */
+ select_res = Curl_socket_ready(fd_read, fd_write, 0);
if(select_res == CURL_CSELECT_ERR) {
failf(data, "select/poll returned error");
@@ -1677,18 +1694,16 @@
/* We go ahead and do a read if we have a readable socket or if
the stream was rewound (in which case we have data in a
buffer) */
- if((k->keepon & KEEP_RECV) &&
+ if((keepon & KEEP_RECV) &&
((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
-
result = readwrite_data(data, conn, k, &didwhat, done);
if(result || *done)
return result;
}
/* If we still have writing to do, we check if we have a writable socket. */
- if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
+ if((keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
/* write */
-
result = readwrite_upload(data, conn, k, &didwhat);
if(result)
return result;
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.417
diff -u -r1.417 urldata.h
--- lib/urldata.h 21 Aug 2009 07:11:20 -0000 1.417
+++ lib/urldata.h 21 Aug 2009 12:18:41 -0000
@@ -784,6 +784,7 @@
char *uploadbuf;
curl_socket_t maxfd;
+ int waitfor;
int keepon;
bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload