On Thu September 3 2009 00:03:33 Daniel Stenberg wrote:
> On Mon, 31 Aug 2009, Kamil Dudka wrote:
> > Attached is my current version of the patch. There are no #ifdefs and it
> > seems to work. No extensive testing yet, just a simple sftp/scp
> > download/upload with the curl tool.
>
> I like how this is turning, but unfortunately test 603 fails for me every
> time now with this applied while it runs fine without it...

My fault, I was running the test suite against the libcurl installed on my 
system instead of the just compiled one. That's why the test passed for me. 
The bug is fixed in the attached patch. Here are my test results:
$ ./runtests.pl -k SCP SFTP

http://kdudka.fedorapeople.org/curl-poll-testlog.tar.lzma

> (using libssh2 from an up-to-date git repo)

Also tested with the latest libssh2...

Kamil
Index: lib/ssh.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ssh.c,v
retrieving revision 1.137
diff -u -p -r1.137 ssh.c
--- lib/ssh.c	2 Sep 2009 21:05:47 -0000	1.137
+++ lib/ssh.c	16 Sep 2009 14:27:30 -0000
@@ -1500,6 +1500,9 @@ static CURLcode ssh_statemach_act(struct
     result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
                                  FIRSTSOCKET, NULL);
 
+    /* not set by Curl_setup_transfer to preserve keepon bits */
+    conn->sockfd = conn->writesockfd;
+
     if(result) {
       state(conn, SSH_SFTP_CLOSE);
       sshc->actualcode = result;
@@ -1911,6 +1914,12 @@ static CURLcode ssh_statemach_act(struct
   else {
     result = Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
                                  FALSE, NULL, -1, NULL);
+
+    /* not set by Curl_setup_transfer to preserve keepon bits */
+    conn->writesockfd = conn->sockfd;
+
+    /* FIXME: here should be explained why we need it to start the download */
+    conn->cselect_bits = CURL_CSELECT_IN;
   }
   if(result) {
     state(conn, SSH_SFTP_CLOSE);
@@ -2031,6 +2040,9 @@ static CURLcode ssh_statemach_act(struct
     result = Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
                                  FIRSTSOCKET, NULL);
 
+    /* not set by Curl_setup_transfer to preserve keepon bits */
+    conn->sockfd = conn->writesockfd;
+
     if(result) {
       state(conn, SSH_SCP_CHANNEL_FREE);
       sshc->actualcode = result;
@@ -2080,6 +2092,12 @@ static CURLcode ssh_statemach_act(struct
     result = Curl_setup_transfer(conn, FIRSTSOCKET,
                                  bytecount, FALSE, NULL, -1, NULL);
 
+    /* not set by Curl_setup_transfer to preserve keepon bits */
+    conn->writesockfd = conn->sockfd;
+
+    /* FIXME: here should be explained why we need it to start the download */
+    conn->cselect_bits = CURL_CSELECT_IN;
+
     if(result) {
       state(conn, SSH_SCP_CHANNEL_FREE);
       sshc->actualcode = result;
@@ -2232,10 +2250,10 @@ static int ssh_perform_getsock(const str
 
   sock[0] = conn->sock[FIRSTSOCKET];
 
-  if(conn->proto.sshc.waitfor & KEEP_RECV)
+  if(conn->waitfor & KEEP_RECV)
     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
 
-  if(conn->proto.sshc.waitfor & KEEP_SEND)
+  if(conn->waitfor & KEEP_SEND)
     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
 
   return bitmap;
@@ -2279,15 +2297,17 @@ static void ssh_block2waitfor(struct con
 {
   struct ssh_conn *sshc = &conn->proto.sshc;
   int dir;
-  if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
+  if(!block)
+    conn->waitfor = 0;
+  else if((dir = libssh2_session_block_directions(sshc->ssh_session))) {
     /* translate the libssh2 define bits into our own bit defines */
-    sshc->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
+    conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
       ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
   }
   else
     /* It didn't block or libssh2 didn't reveal in which direction, put back
        the original set */
-    sshc->waitfor = sshc->orig_waitfor;
+    conn->waitfor = sshc->orig_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 -p -r1.436 transfer.c
--- lib/transfer.c	21 Aug 2009 12:01:36 -0000	1.436
+++ lib/transfer.c	16 Sep 2009 14:27:30 -0000
@@ -1652,10 +1652,6 @@ CURLcode Curl_readwrite(struct connectda
 
   if((k->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
     fd_read = CURL_SOCKET_BAD;
 
@@ -1884,33 +1880,39 @@ Transfer(struct connectdata *conn)
     return CURLE_OK;
 
   while(!done) {
-    curl_socket_t fd_read;
-    curl_socket_t fd_write;
+    curl_socket_t fd_read = conn->sockfd;
+    curl_socket_t fd_write = conn->writesockfd;
+    int keepon = k->keepon;
+
+    if(conn->waitfor) {
+      /* if waitfor is set, get the RECV and SEND bits from that but keep the
+         other bits */
+      keepon &= ~ (KEEP_RECV|KEEP_SEND);
+      keepon |= conn->waitfor & (KEEP_RECV|KEEP_SEND);
+    }
 
     /* limit-rate logic: if speed exceeds threshold, then do not include fd in
        select set. The current speed is recalculated in each Curl_readwrite()
        call */
-    if((k->keepon & KEEP_SEND) &&
+    if((keepon & KEEP_SEND) &&
         (!data->set.max_send_speed ||
          (data->progress.ulspeed < data->set.max_send_speed) )) {
-      fd_write = conn->writesockfd;
       k->keepon &= ~KEEP_SEND_HOLD;
     }
     else {
       fd_write = CURL_SOCKET_BAD;
-      if(k->keepon & KEEP_SEND)
+      if(keepon & KEEP_SEND)
         k->keepon |= KEEP_SEND_HOLD; /* hold it */
     }
 
-    if((k->keepon & KEEP_RECV) &&
+    if((keepon & KEEP_RECV) &&
         (!data->set.max_recv_speed ||
          (data->progress.dlspeed < data->set.max_recv_speed)) ) {
-      fd_read = conn->sockfd;
       k->keepon &= ~KEEP_RECV_HOLD;
     }
     else {
       fd_read = CURL_SOCKET_BAD;
-      if(k->keepon & KEEP_RECV)
+      if(keepon & KEEP_RECV)
         k->keepon |= KEEP_RECV_HOLD; /* hold it */
     }
 
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.418
diff -u -p -r1.418 urldata.h
--- lib/urldata.h	24 Aug 2009 12:57:25 -0000	1.418
+++ lib/urldata.h	16 Sep 2009 14:27:30 -0000
@@ -568,7 +568,6 @@ struct ssh_conn {
   LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
   LIBSSH2_SFTP *sftp_session;   /* SFTP handle */
   LIBSSH2_SFTP_HANDLE *sftp_handle;
-  int waitfor;                  /* current READ/WRITE bits to wait for */
   int orig_waitfor;             /* default READ/WRITE bits wait for */
 
   /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
@@ -1075,6 +1074,8 @@ struct connectdata {
   } proto;
 
   int cselect_bits; /* bitmask of socket events */
+  int waitfor;      /* current READ/WRITE bits to wait for */
+
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
   int socks5_gssapi_enctype;
 #endif

Reply via email to