aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/multi.c28
-rw-r--r--lib/ssh.c15
-rw-r--r--lib/urldata.h6
3 files changed, 34 insertions, 15 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 91d92df90..d68c368f3 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -2105,35 +2105,41 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
and just move on. */
;
else {
+ struct connectdata *conn;
data = entry->easy;
if(data->magic != CURLEASY_MAGIC_NUMBER)
/* bad bad bad bad bad bad bad */
return CURLM_INTERNAL_ERROR;
+ /* note that this can possibly be NULL at this point */
+ conn = data->set.one_easy->easy_conn;
+
/* If the pipeline is enabled, take the handle which is in the head of
the pipeline. If we should write into the socket, take the send_pipe
head. If we should read from the socket, take the recv_pipe head. */
- if(data->set.one_easy->easy_conn) {
+ if(conn) {
if ((ev_bitmask & CURL_POLL_OUT) &&
- data->set.one_easy->easy_conn->send_pipe &&
- data->set.one_easy->easy_conn->send_pipe->head)
- data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
+ conn->send_pipe &&
+ conn->send_pipe->head)
+ data = conn->send_pipe->head->ptr;
else if ((ev_bitmask & CURL_POLL_IN) &&
- data->set.one_easy->easy_conn->recv_pipe &&
- data->set.one_easy->easy_conn->recv_pipe->head)
- data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
+ conn->recv_pipe &&
+ conn->recv_pipe->head)
+ data = conn->recv_pipe->head->ptr;
}
- if(data->set.one_easy->easy_conn) /* set socket event bitmask */
- data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
+ if(conn && !(conn->handler->protocol & PROT_LOCKEDBITS))
+ /* set socket event bitmask if they're not locked */
+ conn->cselect_bits = ev_bitmask;
do
result = multi_runsingle(multi, now, data->set.one_easy);
while (CURLM_CALL_MULTI_PERFORM == result);
- if(data->set.one_easy->easy_conn)
- data->set.one_easy->easy_conn->cselect_bits = 0;
+ if(conn && !(conn->handler->protocol & PROT_LOCKEDBITS))
+ /* clear the bitmask only if not locked */
+ conn->cselect_bits = 0;
if(CURLM_OK >= result)
/* get the socket(s) and check if the state has been changed since
diff --git a/lib/ssh.c b/lib/ssh.c
index 118611efc..e85ad2631 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -2028,8 +2028,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* 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 */
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh2 recv function will deal
+ with both accordingly */
conn->cselect_bits = CURL_CSELECT_IN;
}
if(result) {
@@ -2161,6 +2162,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = result;
}
else {
+ /* we want to use the _sending_ function even when the socket turns
+ out readable as the underlying libssh2 scp send function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_OUT;
+
state(conn, SSH_STOP);
}
break;
@@ -2207,8 +2213,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* 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 */
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh2 recv function will deal
+ with both accordingly */
conn->cselect_bits = CURL_CSELECT_IN;
if(result) {
diff --git a/lib/urldata.h b/lib/urldata.h
index 1d27d2626..2f7fe5e41 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -775,6 +775,12 @@ struct connectdata {
PROT_SFTP | PROT_SCP)
#define PROT_DUALCHANNEL PROT_FTP /* these protocols use two connections */
+/* some protocols will have to call the underlying functions without regard to
+ what exact state the socket signals. IE even if the socket says "readable",
+ the send function might need to be called while uploading, or vice versa.
+*/
+#define PROT_LOCKEDBITS (PROT_SCP | PROT_SFTP)
+
/* 'dns_entry' is the particular host we use. This points to an entry in the
DNS cache and it will not get pruned while locked. It gets unlocked in
Curl_done(). This entry will be NULL if the connection is re-used as then