mirror of
https://github.com/curl/curl.git
synced 2026-04-30 03:57:52 +03:00
ssh: tracing and better pollset handling
Remove connection member `waitfor` and keep it in the SSH connection meta. Add `ssh` to supported tracing features, convert many DEBUGF printgs to traces. Closes #19745
This commit is contained in:
parent
e25a3c6734
commit
12a3182fc3
7 changed files with 178 additions and 107 deletions
|
|
@ -130,6 +130,10 @@ states.
|
|||
Traces reading of upload data from the application in order to send it to the
|
||||
server.
|
||||
|
||||
## `ssh`
|
||||
|
||||
Tracing of SSH related protocols SCP and SFTP.
|
||||
|
||||
## `ssls`
|
||||
|
||||
Tracing of SSL Session handling, e.g. caching/import/export.
|
||||
|
|
|
|||
|
|
@ -453,6 +453,24 @@ void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...)
|
|||
}
|
||||
#endif /* USE_SSL */
|
||||
|
||||
#ifdef USE_SSH
|
||||
struct curl_trc_feat Curl_trc_feat_ssh = {
|
||||
"SSH",
|
||||
CURL_LOG_LVL_NONE,
|
||||
};
|
||||
|
||||
void Curl_trc_ssh(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssh)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_ssh, NULL, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SSH */
|
||||
|
||||
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
struct curl_trc_feat Curl_trc_feat_ws = {
|
||||
"WS",
|
||||
|
|
@ -500,6 +518,9 @@ static struct trc_feat_def trc_feats[] = {
|
|||
#ifdef USE_SSL
|
||||
{ &Curl_trc_feat_ssls, TRC_CT_NETWORK },
|
||||
#endif
|
||||
#ifdef USE_SSH
|
||||
{ &Curl_trc_feat_ssh, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
{ &Curl_trc_feat_ws, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
|
|
@ -696,6 +717,13 @@ void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
|
|||
(void)data; (void)fmt;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SSH
|
||||
void Curl_trc_ssh(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
(void)data;
|
||||
(void)fmt;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SSL
|
||||
void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,6 +117,11 @@ extern struct curl_trc_feat Curl_trc_feat_ssls;
|
|||
void Curl_trc_ssls(struct Curl_easy *data,
|
||||
const char *fmt, ...) CURL_PRINTF(2, 3);
|
||||
#endif
|
||||
#ifdef USE_SSH
|
||||
extern struct curl_trc_feat Curl_trc_feat_ssh;
|
||||
void Curl_trc_ssh(struct Curl_easy *data,
|
||||
const char *fmt, ...) CURL_PRINTF(2, 3);
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
extern struct curl_trc_feat Curl_trc_feat_ws;
|
||||
void Curl_trc_ws(struct Curl_easy *data,
|
||||
|
|
@ -168,6 +173,11 @@ void Curl_trc_ws(struct Curl_easy *data,
|
|||
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) \
|
||||
Curl_trc_ssls(data, __VA_ARGS__); } while(0)
|
||||
#endif /* USE_SSL */
|
||||
#ifdef USE_SSH
|
||||
#define CURL_TRC_SSH(data, ...) \
|
||||
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssh)) \
|
||||
Curl_trc_ssh(data, __VA_ARGS__); } while(0)
|
||||
#endif /* USE_SSH */
|
||||
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
#define CURL_TRC_WS(data, ...) \
|
||||
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) \
|
||||
|
|
@ -193,6 +203,9 @@ void Curl_trc_ws(struct Curl_easy *data,
|
|||
#ifdef USE_SSL
|
||||
#define CURL_TRC_SSLS Curl_trc_ssls
|
||||
#endif
|
||||
#ifdef USE_SSH
|
||||
#define CURL_TRC_SSH Curl_trc_ssh
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
#define CURL_TRC_WS Curl_trc_ws
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -713,7 +713,6 @@ struct connectdata {
|
|||
wrong connections. */
|
||||
char *localdev;
|
||||
unsigned short localportrange;
|
||||
int waitfor; /* current READ/WRITE bits to wait for */
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
int socks5_gssapi_enctype;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -210,26 +210,9 @@ static CURLcode sftp_error_to_CURLE(int err)
|
|||
return CURLE_SSH;
|
||||
}
|
||||
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
#define myssh_to(x,y,z) myssh_set_state(x,y,z, __LINE__)
|
||||
#else
|
||||
#define myssh_to(x,y,z) myssh_set_state(x,y,z)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SSH State machine related code
|
||||
*/
|
||||
/* This is the ONLY way to change SSH state! */
|
||||
static void myssh_set_state(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
sshstate nowstate
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
, int lineno
|
||||
#endif
|
||||
)
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
static const char *myssh_statename(sshstate state)
|
||||
{
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
/* for debug purposes */
|
||||
static const char *const names[] = {
|
||||
"SSH_STOP",
|
||||
"SSH_INIT",
|
||||
|
|
@ -292,14 +275,34 @@ static void myssh_set_state(struct Curl_easy *data,
|
|||
"SSH_SESSION_FREE",
|
||||
"QUIT"
|
||||
};
|
||||
/* a precaution to make sure the lists are in sync */
|
||||
DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST);
|
||||
return ((size_t)state < CURL_ARRAYSIZE(names)) ? names[state] : "";
|
||||
}
|
||||
#else
|
||||
#define myssh_statename(x) ""
|
||||
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
|
||||
#define myssh_to(x,y,z) myssh_set_state(x,y,z)
|
||||
|
||||
/*
|
||||
* SSH State machine related code
|
||||
*/
|
||||
/* This is the ONLY way to change SSH state! */
|
||||
static void myssh_set_state(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
sshstate nowstate)
|
||||
{
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
if(sshc->state != nowstate) {
|
||||
infof(data, "SSH %p state change from %s to %s (line %d)",
|
||||
(void *) sshc, names[sshc->state], names[nowstate],
|
||||
lineno);
|
||||
CURL_TRC_SSH(data, "[%s] -> [%s]",
|
||||
myssh_statename(sshc->state),
|
||||
myssh_statename(nowstate));
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
(void)data;
|
||||
#endif
|
||||
sshc->state = nowstate;
|
||||
}
|
||||
|
||||
|
|
@ -887,7 +890,7 @@ static int myssh_in_S_STARTUP(struct Curl_easy *data,
|
|||
|
||||
myssh_block2waitfor(conn, sshc, (rc == SSH_AGAIN));
|
||||
if(rc == SSH_AGAIN) {
|
||||
DEBUGF(infof(data, "ssh_connect -> EAGAIN"));
|
||||
CURL_TRC_SSH(data, "connect -> EAGAIN");
|
||||
}
|
||||
else if(rc != SSH_OK) {
|
||||
failf(data, "Failure establishing ssh session");
|
||||
|
|
@ -1259,10 +1262,6 @@ static int myssh_in_UPLOAD_INIT(struct Curl_easy *data,
|
|||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
data->conn->recv_idx = FIRSTSOCKET;
|
||||
|
||||
/* store this original bitmask setup to use later on if we cannot
|
||||
figure out a "real" bitmask */
|
||||
sshc->orig_waitfor = data->req.keepon;
|
||||
|
||||
/* since we do not really wait for anything at this point, we want the
|
||||
state machine to move on as soon as possible so we mark this as dirty */
|
||||
Curl_multi_mark_dirty(data);
|
||||
|
|
@ -1401,7 +1400,7 @@ static int myssh_in_SFTP_CLOSE(struct Curl_easy *data,
|
|||
}
|
||||
Curl_safefree(sshp->path);
|
||||
|
||||
DEBUGF(infof(data, "SFTP DONE done"));
|
||||
CURL_TRC_SSH(data, "SFTP DONE done");
|
||||
|
||||
/* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
|
||||
After nextstate is executed, the control should come back to
|
||||
|
|
@ -1485,7 +1484,7 @@ static int myssh_in_SFTP_REALPATH(struct Curl_easy *data,
|
|||
we get the homedir here, we get the "workingpath" in the DO action
|
||||
since the homedir will remain the same between request but the
|
||||
working path will not. */
|
||||
DEBUGF(infof(data, "SSH CONNECT phase done"));
|
||||
CURL_TRC_SSH(data, "CONNECT phase done");
|
||||
myssh_to(data, sshc, SSH_STOP);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
|
@ -2285,10 +2284,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
|||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
data->conn->recv_idx = FIRSTSOCKET;
|
||||
|
||||
/* store this original bitmask setup to use later on if we cannot
|
||||
figure out a "real" bitmask */
|
||||
sshc->orig_waitfor = data->req.keepon;
|
||||
|
||||
myssh_to(data, sshc, SSH_STOP);
|
||||
|
||||
break;
|
||||
|
|
@ -2357,7 +2352,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
|||
ssh_scp_free(sshc->scp_session);
|
||||
sshc->scp_session = NULL;
|
||||
}
|
||||
DEBUGF(infof(data, "SCP DONE phase complete"));
|
||||
CURL_TRC_SSH(data, "SCP DONE phase complete");
|
||||
|
||||
ssh_set_blocking(sshc->ssh_session, 0);
|
||||
|
||||
|
|
@ -2422,7 +2417,8 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
|||
}
|
||||
if(!result && (sshc->state == SSH_STOP))
|
||||
result = sshc->actualcode;
|
||||
DEBUGF(infof(data, "SSH: myssh_statemach_act -> %d", result));
|
||||
CURL_TRC_SSH(data, "[%s] statemachine() -> %d, block=%d",
|
||||
myssh_statename(sshc->state), result, *block);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -2432,33 +2428,45 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
|||
static CURLcode myssh_pollset(struct Curl_easy *data,
|
||||
struct easy_pollset *ps)
|
||||
{
|
||||
int flags = 0;
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn->waitfor & KEEP_RECV)
|
||||
flags |= CURL_POLL_IN;
|
||||
if(conn->waitfor & KEEP_SEND)
|
||||
flags |= CURL_POLL_OUT;
|
||||
if(!conn->waitfor)
|
||||
flags |= CURL_POLL_OUT;
|
||||
return flags ?
|
||||
Curl_pollset_change(data, ps, conn->sock[FIRSTSOCKET], flags, 0) :
|
||||
CURLE_OK;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
int waitfor;
|
||||
|
||||
if(!sshc || (sock == CURL_SOCKET_BAD))
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
waitfor = sshc->waitfor ? sshc->waitfor : data->req.keepon;
|
||||
if(waitfor) {
|
||||
int flags = 0;
|
||||
if(waitfor & KEEP_RECV)
|
||||
flags |= CURL_POLL_IN;
|
||||
if(waitfor & KEEP_SEND)
|
||||
flags |= CURL_POLL_OUT;
|
||||
DEBUGASSERT(flags);
|
||||
CURL_TRC_SSH(data, "pollset, flags=%x", flags);
|
||||
return Curl_pollset_change(data, ps, sock, flags, 0);
|
||||
}
|
||||
/* While we still have a session, we listen incoming data. */
|
||||
if(sshc->ssh_session)
|
||||
return Curl_pollset_change(data, ps, sock, CURL_POLL_IN, 0);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static void myssh_block2waitfor(struct connectdata *conn,
|
||||
struct ssh_conn *sshc,
|
||||
bool block)
|
||||
{
|
||||
(void)conn;
|
||||
if(block) {
|
||||
int dir = ssh_get_poll_flags(sshc->ssh_session);
|
||||
/* translate the libssh define bits into our own bit defines */
|
||||
conn->waitfor =
|
||||
sshc->waitfor =
|
||||
((dir & SSH_READ_PENDING) ? KEEP_RECV : 0) |
|
||||
((dir & SSH_WRITE_PENDING) ? KEEP_SEND : 0);
|
||||
}
|
||||
else
|
||||
/* if it did not block, use the original set */
|
||||
conn->waitfor = sshc->orig_waitfor;
|
||||
sshc->waitfor = 0;
|
||||
}
|
||||
|
||||
/* called repeatedly until done from multi.c */
|
||||
|
|
@ -2584,6 +2592,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
|
|||
if(!sshc || !ssh)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
CURL_TRC_SSH(data, "myssh_connect");
|
||||
if(conn->handler->protocol & CURLPROTO_SCP) {
|
||||
conn->recv[FIRSTSOCKET] = scp_recv;
|
||||
conn->send[FIRSTSOCKET] = scp_send;
|
||||
|
|
@ -2618,6 +2627,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
|
|||
/* ignore */
|
||||
}
|
||||
|
||||
CURL_TRC_SSH(data, "myssh_connect, set socket=%" FMT_SOCKET_T, sock);
|
||||
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_FD, &sock);
|
||||
if(rc != SSH_OK) {
|
||||
failf(data, "Could not set socket");
|
||||
|
|
@ -2691,7 +2701,7 @@ static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
|
|||
result = myssh_multi_statemach(data, dophase_done);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -2712,7 +2722,7 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
CURLcode result = CURLE_OK;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
CURL_TRC_SSH(data, "DO phase starts");
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
if(!sshc)
|
||||
|
|
@ -2726,7 +2736,7 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
*connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -2959,7 +2969,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
|
|||
struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
CURL_TRC_SSH(data, "DO phase starts");
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
if(!sshc)
|
||||
|
|
@ -2974,7 +2984,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
|
|||
*connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -2986,7 +2996,7 @@ static CURLcode sftp_doing(struct Curl_easy *data,
|
|||
{
|
||||
CURLcode result = myssh_multi_statemach(data, dophase_done);
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3003,7 +3013,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
|
|||
CURLcode result = CURLE_OK;
|
||||
(void)dead_connection;
|
||||
|
||||
DEBUGF(infof(data, "SSH DISCONNECT starts now"));
|
||||
CURL_TRC_SSH(data, "DISCONNECT starts now");
|
||||
|
||||
if(sshc && sshc->ssh_session) {
|
||||
/* only if there is a session still around to use! */
|
||||
|
|
@ -3011,7 +3021,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
|
|||
result = myssh_block_statemach(data, sshc, sshp, TRUE);
|
||||
}
|
||||
|
||||
DEBUGF(infof(data, "SSH DISCONNECT is done"));
|
||||
CURL_TRC_SSH(data, "DISCONNECT is done");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -280,17 +280,10 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free)
|
|||
Curl_cfree(ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* SSH State machine related code
|
||||
*/
|
||||
/* This is the ONLY way to change SSH state! */
|
||||
static void myssh_state(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
sshstate nowstate)
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
static const char *myssh_statename(sshstate state)
|
||||
{
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
/* for debug purposes */
|
||||
static const char * const names[] = {
|
||||
static const char *const names[] = {
|
||||
"SSH_STOP",
|
||||
"SSH_INIT",
|
||||
"SSH_S_STARTUP",
|
||||
|
|
@ -352,16 +345,34 @@ static void myssh_state(struct Curl_easy *data,
|
|||
"SSH_SESSION_FREE",
|
||||
"QUIT"
|
||||
};
|
||||
|
||||
/* a precaution to make sure the lists are in sync */
|
||||
DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST);
|
||||
return ((size_t)state < CURL_ARRAYSIZE(names)) ? names[state] : "";
|
||||
}
|
||||
#else
|
||||
#define myssh_statename(x) ""
|
||||
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
|
||||
#define myssh_state(x,y,z) myssh_set_state(x,y,z)
|
||||
|
||||
/*
|
||||
* SSH State machine related code
|
||||
*/
|
||||
/* This is the ONLY way to change SSH state! */
|
||||
static void myssh_set_state(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
sshstate nowstate)
|
||||
{
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
if(sshc->state != nowstate) {
|
||||
infof(data, "SFTP %p state change from %s to %s",
|
||||
(void *)sshc, names[sshc->state], names[nowstate]);
|
||||
CURL_TRC_SSH(data, "[%s] -> [%s]",
|
||||
myssh_statename(sshc->state),
|
||||
myssh_statename(nowstate));
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
(void)data;
|
||||
#endif
|
||||
sshc->state = nowstate;
|
||||
}
|
||||
|
||||
|
|
@ -1172,10 +1183,6 @@ sftp_upload_init(struct Curl_easy *data,
|
|||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
data->conn->recv_idx = FIRSTSOCKET;
|
||||
|
||||
/* store this original bitmask setup to use later on if we cannot
|
||||
figure out a "real" bitmask */
|
||||
sshc->orig_waitfor = data->req.keepon;
|
||||
|
||||
/* since we do not really wait for anything at this point, we want the
|
||||
state machine to move on as soon as possible so mark this as dirty */
|
||||
Curl_multi_mark_dirty(data);
|
||||
|
|
@ -1951,8 +1958,7 @@ static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data,
|
|||
/* in this case, the error was not in the SFTP level but for example a
|
||||
time-out or similar */
|
||||
result = CURLE_SSH;
|
||||
DEBUGF(infof(data, "error = %lu makes libcurl = %d",
|
||||
sftperr, (int)result));
|
||||
CURL_TRC_SSH(data, "error = %lu makes libcurl = %d", sftperr, (int)result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1960,7 +1966,7 @@ static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data,
|
|||
get the homedir here, we get the "workingpath" in the DO action since the
|
||||
homedir will remain the same between request but the working path will
|
||||
not. */
|
||||
DEBUGF(infof(data, "SSH CONNECT phase done"));
|
||||
CURL_TRC_SSH(data, "CONNECT phase done");
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2418,7 +2424,7 @@ static CURLcode ssh_state_sftp_close(struct Curl_easy *data,
|
|||
|
||||
Curl_safefree(sshp->path);
|
||||
|
||||
DEBUGF(infof(data, "SFTP DONE done"));
|
||||
CURL_TRC_SSH(data, "SFTP DONE done");
|
||||
|
||||
/* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
|
||||
After nextstate is executed, the control should come back to
|
||||
|
|
@ -2542,10 +2548,6 @@ static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data,
|
|||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||
data->conn->recv_idx = FIRSTSOCKET;
|
||||
|
||||
/* store this original bitmask setup to use later on if we cannot
|
||||
figure out a "real" bitmask */
|
||||
sshc->orig_waitfor = data->req.keepon;
|
||||
|
||||
myssh_state(data, sshc, SSH_STOP);
|
||||
|
||||
return CURLE_OK;
|
||||
|
|
@ -3008,7 +3010,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
|
|||
}
|
||||
sshc->ssh_channel = NULL;
|
||||
}
|
||||
DEBUGF(infof(data, "SCP DONE phase complete"));
|
||||
CURL_TRC_SSH(data, "SCP DONE phase complete");
|
||||
myssh_state(data, sshc, SSH_STOP);
|
||||
break;
|
||||
|
||||
|
|
@ -3042,6 +3044,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
|
|||
*block = TRUE;
|
||||
result = CURLE_OK;
|
||||
}
|
||||
CURL_TRC_SSH(data, "[%s] statemachine() -> %d, block=%d",
|
||||
myssh_statename(sshc->state), result, *block);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3051,15 +3055,29 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
|
|||
static CURLcode ssh_pollset(struct Curl_easy *data,
|
||||
struct easy_pollset *ps)
|
||||
{
|
||||
int flags = 0;
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn->waitfor & KEEP_RECV)
|
||||
flags |= CURL_POLL_IN;
|
||||
if(conn->waitfor & KEEP_SEND)
|
||||
flags |= CURL_POLL_OUT;
|
||||
return flags ?
|
||||
Curl_pollset_change(data, ps, conn->sock[FIRSTSOCKET], flags, 0) :
|
||||
CURLE_OK;
|
||||
struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
int waitfor;
|
||||
|
||||
if(!sshc || (sock == CURL_SOCKET_BAD))
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
waitfor = sshc->waitfor ? sshc->waitfor : data->req.keepon;
|
||||
if(waitfor) {
|
||||
int flags = 0;
|
||||
if(waitfor & KEEP_RECV)
|
||||
flags |= CURL_POLL_IN;
|
||||
if(waitfor & KEEP_SEND)
|
||||
flags |= CURL_POLL_OUT;
|
||||
DEBUGASSERT(flags);
|
||||
CURL_TRC_SSH(data, "pollset, flags=%x", flags);
|
||||
return Curl_pollset_change(data, ps, sock, flags, 0);
|
||||
}
|
||||
/* While we still have a session, we listen incoming data. */
|
||||
if(sshc->ssh_session)
|
||||
return Curl_pollset_change(data, ps, sock, CURL_POLL_IN, 0);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3073,20 +3091,18 @@ static void ssh_block2waitfor(struct Curl_easy *data,
|
|||
struct ssh_conn *sshc,
|
||||
bool block)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
int dir = 0;
|
||||
(void)data;
|
||||
if(block) {
|
||||
dir = libssh2_session_block_directions(sshc->ssh_session);
|
||||
if(dir) {
|
||||
/* translate the libssh2 define bits into our own bit defines */
|
||||
conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND) ? KEEP_RECV : 0) |
|
||||
sshc->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND) ? KEEP_RECV : 0) |
|
||||
((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND) ? KEEP_SEND : 0);
|
||||
}
|
||||
}
|
||||
if(!dir)
|
||||
/* It did not block or libssh2 did not reveal in which direction, put back
|
||||
the original set */
|
||||
conn->waitfor = sshc->orig_waitfor;
|
||||
sshc->waitfor = 0;
|
||||
}
|
||||
|
||||
/* called repeatedly until done from multi.c */
|
||||
|
|
@ -3468,7 +3484,7 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
CURL_TRC_SSH(data, "DO phase starts");
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
if(!sshc)
|
||||
|
|
@ -3483,7 +3499,7 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
*connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -3497,7 +3513,7 @@ static CURLcode scp_doing(struct Curl_easy *data,
|
|||
result = ssh_multi_statemach(data, dophase_done);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3778,7 +3794,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
|
|||
struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
CURL_TRC_SSH(data, "DO phase starts");
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
if(!sshc)
|
||||
|
|
@ -3793,7 +3809,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
|
|||
*connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -3806,7 +3822,7 @@ static CURLcode sftp_doing(struct Curl_easy *data,
|
|||
CURLcode result = ssh_multi_statemach(data, dophase_done);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
CURL_TRC_SSH(data, "DO phase is complete");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3825,10 +3841,10 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
|
|||
if(sshc) {
|
||||
if(sshc->ssh_session) {
|
||||
/* only if there is a session still around to use! */
|
||||
DEBUGF(infof(data, "SSH DISCONNECT starts now"));
|
||||
CURL_TRC_SSH(data, "DISCONNECT starts now");
|
||||
myssh_state(data, sshc, SSH_SFTP_SHUTDOWN);
|
||||
result = ssh_block_statemach(data, sshc, sshp, TRUE);
|
||||
DEBUGF(infof(data, "SSH DISCONNECT is done -> %d", result));
|
||||
CURL_TRC_SSH(data, "DISCONNECT is done -> %d", result);
|
||||
}
|
||||
sshc_cleanup(sshc, data, TRUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,8 @@ struct ssh_conn {
|
|||
int secondCreateDirs; /* counter use by the code to see if the
|
||||
second attempt has been made to change
|
||||
to/create a directory */
|
||||
int orig_waitfor; /* default READ/WRITE bits wait for */
|
||||
int waitfor; /* KEEP_RECV/KEEP_SEND bits overriding
|
||||
pollset given flags */
|
||||
char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
|
||||
|
||||
#ifdef USE_LIBSSH
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue