lib: pass in 'struct Curl_easy *' to most functions

... in most cases instead of 'struct connectdata *' but in some cases in
addition to.

- We mostly operate on transfers and not connections.

- We need the transfer handle to log, store data and more. Everything in
  libcurl is driven by a transfer (the CURL * in the public API).

- This work clarifies and separates the transfers from the connections
  better.

- We should avoid "conn->data". Since individual connections can be used
  by many transfers when multiplexing, making sure that conn->data
  points to the current and correct transfer at all times is difficult
  and has been notoriously error-prone over the years. The goal is to
  ultimately remove the conn->data pointer for this reason.

Closes #6425
This commit is contained in:
Daniel Stenberg 2021-01-08 17:58:15 +01:00
parent 0d26ab9ed3
commit 215db086e0
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
76 changed files with 2852 additions and 2588 deletions

View file

@ -671,7 +671,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
res->last_status = ARES_ENOTFOUND; res->last_status = ARES_ENOTFOUND;
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
if(family == PF_UNSPEC) { if(family == PF_UNSPEC) {
if(Curl_ipv6works(conn)) { if(Curl_ipv6works(data)) {
res->num_pending = 2; res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */ /* areschannel is already setup in the Curl_open() function */

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -749,7 +749,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
break; break;
} }
if((pf != PF_INET) && !Curl_ipv6works(conn)) if((pf != PF_INET) && !Curl_ipv6works(data))
/* The stack seems to be a non-IPv6 one */ /* The stack seems to be a non-IPv6 one */
pf = PF_INET; pf = PF_INET;
#endif /* CURLRES_IPV6 */ #endif /* CURLRES_IPV6 */

View file

@ -67,7 +67,7 @@ size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
(void)ctx; (void)ctx;
result = Curl_read(conn, conn->sockfd, (char *)buf, buflen, &nread); result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
if(result == CURLE_AGAIN) { if(result == CURLE_AGAIN) {
/* would block, register interest */ /* would block, register interest */
if(data->hyp.read_waker) if(data->hyp.read_waker)
@ -94,7 +94,7 @@ size_t Curl_hyper_send(void *userp, hyper_context *ctx,
CURLcode result; CURLcode result;
ssize_t nwrote; ssize_t nwrote;
result = Curl_write(conn, conn->sockfd, (void *)buf, buflen, &nwrote); result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
if(result == CURLE_AGAIN) { if(result == CURLE_AGAIN) {
/* would block, register interest */ /* would block, register interest */
if(data->hyp.write_waker) if(data->hyp.write_waker)
@ -380,7 +380,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
/* Curl_http_auth_act() checks what authentication methods that are /* Curl_http_auth_act() checks what authentication methods that are
* available and decides which one (if any) to use. It will set 'newurl' * available and decides which one (if any) to use. It will set 'newurl'
* if an auth method was picked. */ * if an auth method was picked. */
result = Curl_http_auth_act(conn); result = Curl_http_auth_act(data);
if(result) if(result)
break; break;
@ -628,9 +628,9 @@ static CURLcode cookies(struct Curl_easy *data,
* request is to be performed. This creates and sends a properly constructed * request is to be performed. This creates and sends a properly constructed
* HTTP request. * HTTP request.
*/ */
CURLcode Curl_http(struct connectdata *conn, bool *done) CURLcode Curl_http(struct Curl_easy *data, bool *done)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct hyptransfer *h = &data->hyp; struct hyptransfer *h = &data->hyp;
hyper_io *io = NULL; hyper_io *io = NULL;
hyper_clientconn_options *options = NULL; hyper_clientconn_options *options = NULL;
@ -670,7 +670,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!pq) if(!pq)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
result = Curl_http_output_auth(conn, method, httpreq, result = Curl_http_output_auth(data, conn, method, httpreq,
(pq ? pq : data->state.up.path), FALSE); (pq ? pq : data->state.up.path), FALSE);
free(pq); free(pq);
if(result) if(result)
@ -681,11 +681,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result) if(result)
return result; return result;
result = Curl_http_range(data, conn, httpreq); result = Curl_http_range(data, httpreq);
if(result) if(result)
return result; return result;
result = Curl_http_useragent(data, conn); result = Curl_http_useragent(data);
if(result) if(result)
return result; return result;
@ -799,7 +799,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_hyper_header(data, headers, data->state.aptr.uagent)) Curl_hyper_header(data, headers, data->state.aptr.uagent))
goto error; goto error;
p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n"; p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
if(p_accept && Curl_hyper_header(data, headers, p_accept)) if(p_accept && Curl_hyper_header(data, headers, p_accept))
goto error; goto error;
@ -808,14 +808,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy && if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
!Curl_checkProxyheaders(conn, "Proxy-Connection")) { !Curl_checkProxyheaders(data, conn, "Proxy-Connection")) {
if(Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive")) if(Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
goto error; goto error;
} }
#endif #endif
Curl_safefree(data->state.aptr.ref); Curl_safefree(data->state.aptr.ref);
if(data->change.referer && !Curl_checkheaders(conn, "Referer")) { if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
if(!data->state.aptr.ref) if(!data->state.aptr.ref)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -827,11 +827,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result) if(result)
return result; return result;
result = Curl_add_timecondition(conn, headers); result = Curl_add_timecondition(data, headers);
if(result) if(result)
return result; return result;
result = Curl_add_custom_headers(conn, FALSE, headers); result = Curl_add_custom_headers(data, FALSE, headers);
if(result) if(result)
return result; return result;

View file

@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se> * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -318,7 +318,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
bool Curl_conncache_foreach(struct Curl_easy *data, bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc, struct conncache *connc,
void *param, void *param,
int (*func)(struct connectdata *conn, void *param)) int (*func)(struct Curl_easy *data,
struct connectdata *conn, void *param))
{ {
struct Curl_hash_iterator iter; struct Curl_hash_iterator iter;
struct Curl_llist_element *curr; struct Curl_llist_element *curr;
@ -344,7 +345,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
struct connectdata *conn = curr->ptr; struct connectdata *conn = curr->ptr;
curr = curr->next; curr = curr->next;
if(1 == func(conn, param)) { if(1 == func(data, conn, param)) {
CONNCACHE_UNLOCK(data); CONNCACHE_UNLOCK(data);
return TRUE; return TRUE;
} }

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2015 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se> * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
@ -101,7 +101,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
bool Curl_conncache_foreach(struct Curl_easy *data, bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc, struct conncache *connc,
void *param, void *param,
int (*func)(struct connectdata *conn, int (*func)(struct Curl_easy *data,
struct connectdata *conn,
void *param)); void *param));
struct connectdata * struct connectdata *

View file

@ -160,7 +160,8 @@ tcpkeepalive(struct Curl_easy *data,
} }
static CURLcode static CURLcode
singleipconnect(struct connectdata *conn, singleipconnect(struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai, /* start connecting to this */ const struct Curl_addrinfo *ai, /* start connecting to this */
int tempindex); /* 0 or 1 among the temp ones */ int tempindex); /* 0 or 1 among the temp ones */
@ -236,11 +237,10 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
return timeout_ms; return timeout_ms;
} }
static CURLcode bindlocal(struct connectdata *conn, static CURLcode bindlocal(struct Curl_easy *data,
curl_socket_t sockfd, int af, unsigned int scope) curl_socket_t sockfd, int af, unsigned int scope)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct Curl_sockaddr_storage sa; struct Curl_sockaddr_storage sa;
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
@ -573,7 +573,8 @@ static struct Curl_addrinfo *ainext(struct connectdata *conn,
/* Used within the multi interface. Try next IP address, returns error if no /* Used within the multi interface. Try next IP address, returns error if no
more address exists or error */ more address exists or error */
static CURLcode trynextip(struct connectdata *conn, static CURLcode trynextip(struct Curl_easy *data,
struct connectdata *conn,
int sockindex, int sockindex,
int tempindex) int tempindex)
{ {
@ -591,7 +592,7 @@ static CURLcode trynextip(struct connectdata *conn,
while(ai) { while(ai) {
if(ai) { if(ai) {
result = singleipconnect(conn, ai, tempindex); result = singleipconnect(data, conn, ai, tempindex);
if(result == CURLE_COULDNT_CONNECT) { if(result == CURLE_COULDNT_CONNECT) {
ai = ainext(conn, tempindex, TRUE); ai = ainext(conn, tempindex, TRUE);
continue; continue;
@ -602,21 +603,21 @@ static CURLcode trynextip(struct connectdata *conn,
} }
if(fd_to_close != CURL_SOCKET_BAD) if(fd_to_close != CURL_SOCKET_BAD)
Curl_closesocket(conn, fd_to_close); Curl_closesocket(data, conn, fd_to_close);
return result; return result;
} }
/* Copies connection info into the session handle to make it available /* Copies connection info into the transfer handle to make it available when
when the session handle is no longer associated with a connection. */ the transfer handle is no longer associated with the connection. */
void Curl_persistconninfo(struct connectdata *conn) void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn)
{ {
memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); memcpy(data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
conn->data->info.conn_scheme = conn->handler->scheme; data->info.conn_scheme = conn->handler->scheme;
conn->data->info.conn_protocol = conn->handler->protocol; data->info.conn_protocol = conn->handler->protocol;
conn->data->info.conn_primary_port = conn->primary_port; data->info.conn_primary_port = conn->primary_port;
conn->data->info.conn_local_port = conn->local_port; data->info.conn_local_port = conn->local_port;
} }
/* retrieves ip address and port from a sockaddr structure. /* retrieves ip address and port from a sockaddr structure.
@ -678,7 +679,8 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
/* retrieves the start/end point information of a socket of an established /* retrieves the start/end point information of a socket of an established
connection */ connection */
void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd) void Curl_conninfo_remote(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t sockfd)
{ {
#ifdef HAVE_GETPEERNAME #ifdef HAVE_GETPEERNAME
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
@ -688,18 +690,19 @@ void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd)
memset(&ssrem, 0, sizeof(ssrem)); memset(&ssrem, 0, sizeof(ssrem));
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) { if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
int error = SOCKERRNO; int error = SOCKERRNO;
failf(conn->data, "getpeername() failed with errno %d: %s", failf(data, "getpeername() failed with errno %d: %s",
error, Curl_strerror(error, buffer, sizeof(buffer))); error, Curl_strerror(error, buffer, sizeof(buffer)));
return; return;
} }
if(!Curl_addr2string((struct sockaddr*)&ssrem, plen, if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
conn->primary_ip, &conn->primary_port)) { conn->primary_ip, &conn->primary_port)) {
failf(conn->data, "ssrem inet_ntop() failed with errno %d: %s", failf(data, "ssrem inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer))); errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return; return;
} }
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
#else #else
(void)data;
(void)conn; (void)conn;
(void)sockfd; (void)sockfd;
#endif #endif
@ -707,7 +710,8 @@ void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd)
/* retrieves the start/end point information of a socket of an established /* retrieves the start/end point information of a socket of an established
connection */ connection */
void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd) void Curl_conninfo_local(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sockfd)
{ {
#ifdef HAVE_GETSOCKNAME #ifdef HAVE_GETSOCKNAME
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
@ -717,17 +721,18 @@ void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd)
memset(&ssloc, 0, sizeof(ssloc)); memset(&ssloc, 0, sizeof(ssloc));
if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) { if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
int error = SOCKERRNO; int error = SOCKERRNO;
failf(conn->data, "getsockname() failed with errno %d: %s", failf(data, "getsockname() failed with errno %d: %s",
error, Curl_strerror(error, buffer, sizeof(buffer))); error, Curl_strerror(error, buffer, sizeof(buffer)));
return; return;
} }
if(!Curl_addr2string((struct sockaddr*)&ssloc, slen, if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
conn->local_ip, &conn->local_port)) { conn->local_ip, &conn->local_port)) {
failf(conn->data, "ssloc inet_ntop() failed with errno %d: %s", failf(data, "ssloc inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer))); errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return; return;
} }
#else #else
(void)data;
(void)conn; (void)conn;
(void)sockfd; (void)sockfd;
#endif #endif
@ -735,17 +740,18 @@ void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd)
/* retrieves the start/end point information of a socket of an established /* retrieves the start/end point information of a socket of an established
connection */ connection */
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sockfd)
{ {
if(conn->transport == TRNSPRT_TCP) { if(conn->transport == TRNSPRT_TCP) {
if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
Curl_conninfo_remote(conn, sockfd); Curl_conninfo_remote(data, conn, sockfd);
Curl_conninfo_local(conn, sockfd); Curl_conninfo_local(data, conn, sockfd);
} }
} /* end of TCP-only section */ } /* end of TCP-only section */
/* persist connection info in session handle */ /* persist connection info in session handle */
Curl_persistconninfo(conn); Curl_persistconninfo(data, conn);
} }
/* After a TCP connection to the proxy has been verified, this function does /* After a TCP connection to the proxy has been verified, this function does
@ -755,12 +761,13 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
Note: this function's sub-functions call failf() Note: this function's sub-functions call failf()
*/ */
static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex, static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex,
bool *done) bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
CURLproxycode pxresult = CURLPX_OK; CURLproxycode pxresult = CURLPX_OK;
struct connectdata *conn = data->conn;
if(conn->bits.socksproxy) { if(conn->bits.socksproxy) {
/* for the secondary socket (FTP), use the "connect to host" /* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port) * but ignore the "connect to port" (use the secondary port)
@ -791,17 +798,17 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
break; break;
default: default:
failf(conn->data, "unknown proxytype option given"); failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT; result = CURLE_COULDNT_CONNECT;
} /* switch proxytype */ } /* switch proxytype */
if(pxresult) { if(pxresult) {
result = CURLE_PROXY; result = CURLE_PROXY;
conn->data->info.pxcode = pxresult; data->info.pxcode = pxresult;
} }
} }
else else
#else #else
(void)conn; (void)data;
(void)sockindex; (void)sockindex;
#endif /* CURL_DISABLE_PROXY */ #endif /* CURL_DISABLE_PROXY */
*done = TRUE; /* no SOCKS proxy, so consider us connected */ *done = TRUE; /* no SOCKS proxy, so consider us connected */
@ -813,7 +820,8 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
* post_SOCKS() is called after a successful connect to the peer, which * post_SOCKS() is called after a successful connect to the peer, which
* *could* be a SOCKS proxy * *could* be a SOCKS proxy
*/ */
static void post_SOCKS(struct connectdata *conn, static void post_SOCKS(struct Curl_easy *data,
struct connectdata *conn,
int sockindex, int sockindex,
bool *connected) bool *connected)
{ {
@ -821,21 +829,21 @@ static void post_SOCKS(struct connectdata *conn,
*connected = TRUE; *connected = TRUE;
if(sockindex == FIRSTSOCKET) if(sockindex == FIRSTSOCKET)
Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
Curl_updateconninfo(conn, conn->sock[sockindex]); Curl_updateconninfo(data, conn, conn->sock[sockindex]);
Curl_verboseconnect(conn); Curl_verboseconnect(data, conn);
conn->data->info.numconnects++; /* to track the number of connections made */ data->info.numconnects++; /* to track the number of connections made */
} }
/* /*
* Curl_is_connected() checks if the socket has connected. * Curl_is_connected() checks if the socket has connected.
*/ */
CURLcode Curl_is_connected(struct connectdata *conn, CURLcode Curl_is_connected(struct Curl_easy *data,
struct connectdata *conn,
int sockindex, int sockindex,
bool *connected) bool *connected)
{ {
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
timediff_t allow; timediff_t allow;
int error = 0; int error = 0;
@ -866,9 +874,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
if(SOCKS_STATE(conn->cnnct.state)) { if(SOCKS_STATE(conn->cnnct.state)) {
/* still doing SOCKS */ /* still doing SOCKS */
result = connect_SOCKS(conn, sockindex, connected); result = connect_SOCKS(data, sockindex, connected);
if(!result && *connected) if(!result && *connected)
post_SOCKS(conn, sockindex, connected); post_SOCKS(data, conn, sockindex, connected);
return result; return result;
} }
@ -885,7 +893,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
conn->sock[sockindex] = conn->tempsock[i]; conn->sock[sockindex] = conn->tempsock[i];
conn->ip_addr = conn->tempaddr[i]; conn->ip_addr = conn->tempaddr[i];
conn->tempsock[i] = CURL_SOCKET_BAD; conn->tempsock[i] = CURL_SOCKET_BAD;
post_SOCKS(conn, sockindex, connected); post_SOCKS(data, conn, sockindex, connected);
connkeep(conn, "HTTP/3 default"); connkeep(conn, "HTTP/3 default");
return CURLE_OK; return CURLE_OK;
} }
@ -920,7 +928,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
(Curl_timediff(now, conn->connecttime) >= (Curl_timediff(now, conn->connecttime) >=
data->set.happy_eyeballs_timeout)) { data->set.happy_eyeballs_timeout)) {
conn->bits.parallel_connect = TRUE; /* starting now */ conn->bits.parallel_connect = TRUE; /* starting now */
trynextip(conn, sockindex, 1); trynextip(data, conn, sockindex, 1);
} }
} }
else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) { else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
@ -937,17 +945,17 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* close the other socket, if open */ /* close the other socket, if open */
if(conn->tempsock[other] != CURL_SOCKET_BAD) { if(conn->tempsock[other] != CURL_SOCKET_BAD) {
Curl_closesocket(conn, conn->tempsock[other]); Curl_closesocket(data, conn, conn->tempsock[other]);
conn->tempsock[other] = CURL_SOCKET_BAD; conn->tempsock[other] = CURL_SOCKET_BAD;
} }
/* see if we need to kick off any SOCKS proxy magic once we /* see if we need to kick off any SOCKS proxy magic once we
connected */ connected */
result = connect_SOCKS(conn, sockindex, connected); result = connect_SOCKS(data, sockindex, connected);
if(result || !*connected) if(result || !*connected)
return result; return result;
post_SOCKS(conn, sockindex, connected); post_SOCKS(data, conn, sockindex, connected);
return CURLE_OK; return CURLE_OK;
} }
@ -978,7 +986,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ? conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
allow : allow / 2; allow : allow / 2;
ainext(conn, i, TRUE); ainext(conn, i, TRUE);
status = trynextip(conn, sockindex, i); status = trynextip(data, conn, sockindex, i);
if((status != CURLE_COULDNT_CONNECT) || if((status != CURLE_COULDNT_CONNECT) ||
conn->tempsock[other] == CURL_SOCKET_BAD) conn->tempsock[other] == CURL_SOCKET_BAD)
/* the last attempt failed and no other sockets remain open */ /* the last attempt failed and no other sockets remain open */
@ -996,7 +1004,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* if the first address family runs out of addresses to try before the /* if the first address family runs out of addresses to try before the
happy eyeball timeout, go ahead and try the next family now */ happy eyeball timeout, go ahead and try the next family now */
result = trynextip(conn, sockindex, 1); result = trynextip(data, conn, sockindex, 1);
if(!result) if(!result)
return result; return result;
@ -1033,16 +1041,15 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return result; return result;
} }
static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
{ {
#if defined(TCP_NODELAY) #if defined(TCP_NODELAY)
curl_socklen_t onoff = (curl_socklen_t) 1; curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP; int level = IPPROTO_TCP;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS) #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
struct Curl_easy *data = conn->data;
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
#else #else
(void) conn; (void) data;
#endif #endif
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
@ -1050,7 +1057,7 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
infof(data, "Could not set TCP_NODELAY: %s\n", infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
#else #else
(void)conn; (void)data;
(void)sockfd; (void)sockfd;
#endif #endif
} }
@ -1060,10 +1067,9 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
sending data to a dead peer (instead of relying on the 4th argument to send sending data to a dead peer (instead of relying on the 4th argument to send
being MSG_NOSIGNAL). Possibly also existing and in use on other BSD being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
systems? */ systems? */
static void nosigpipe(struct connectdata *conn, static void nosigpipe(struct Curl_easy *data,
curl_socket_t sockfd) curl_socket_t sockfd)
{ {
struct Curl_easy *data = conn->data;
int onoff = 1; int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0) { sizeof(onoff)) < 0) {
@ -1129,7 +1135,8 @@ void Curl_sndbufset(curl_socket_t sockfd)
* singleipconnect() connects to the given IP only, and it may return without * singleipconnect() connects to the given IP only, and it may return without
* having connected. * having connected.
*/ */
static CURLcode singleipconnect(struct connectdata *conn, static CURLcode singleipconnect(struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai, const struct Curl_addrinfo *ai,
int tempindex) int tempindex)
{ {
@ -1137,7 +1144,6 @@ static CURLcode singleipconnect(struct connectdata *conn,
int rc = -1; int rc = -1;
int error = 0; int error = 0;
bool isconnected = FALSE; bool isconnected = FALSE;
struct Curl_easy *data = conn->data;
curl_socket_t sockfd; curl_socket_t sockfd;
CURLcode result; CURLcode result;
char ipaddress[MAX_IPADR_LEN]; char ipaddress[MAX_IPADR_LEN];
@ -1150,7 +1156,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
curl_socket_t *sockp = &conn->tempsock[tempindex]; curl_socket_t *sockp = &conn->tempsock[tempindex];
*sockp = CURL_SOCKET_BAD; *sockp = CURL_SOCKET_BAD;
result = Curl_socket(conn, ai, &addr, &sockfd); result = Curl_socket(data, ai, &addr, &sockfd);
if(result) if(result)
return result; return result;
@ -1160,7 +1166,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
/* malformed address or bug in inet_ntop, try next address */ /* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s", failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer))); errno, Curl_strerror(errno, buffer, sizeof(buffer)));
Curl_closesocket(conn, sockfd); Curl_closesocket(data, conn, sockfd);
return CURLE_OK; return CURLE_OK;
} }
infof(data, " Trying %s:%ld...\n", ipaddress, port); infof(data, " Trying %s:%ld...\n", ipaddress, port);
@ -1172,9 +1178,9 @@ static CURLcode singleipconnect(struct connectdata *conn,
is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
#endif #endif
if(is_tcp && data->set.tcp_nodelay) if(is_tcp && data->set.tcp_nodelay)
tcpnodelay(conn, sockfd); tcpnodelay(data, sockfd);
nosigpipe(conn, sockfd); nosigpipe(data, sockfd);
Curl_sndbufset(sockfd); Curl_sndbufset(sockfd);
@ -1192,7 +1198,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
if(error == CURL_SOCKOPT_ALREADY_CONNECTED) if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
isconnected = TRUE; isconnected = TRUE;
else if(error) { else if(error) {
Curl_closesocket(conn, sockfd); /* close the socket and bail out */ Curl_closesocket(data, conn, sockfd); /* close the socket and bail out */
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
} }
} }
@ -1203,10 +1209,10 @@ static CURLcode singleipconnect(struct connectdata *conn,
|| addr.family == AF_INET6 || addr.family == AF_INET6
#endif #endif
) { ) {
result = bindlocal(conn, sockfd, addr.family, result = bindlocal(data, sockfd, addr.family,
Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr)); Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
if(result) { if(result) {
Curl_closesocket(conn, sockfd); /* close socket and bail out */ Curl_closesocket(data, conn, sockfd); /* close socket and bail out */
if(result == CURLE_UNSUPPORTED_PROTOCOL) { if(result == CURLE_UNSUPPORTED_PROTOCOL) {
/* The address family is not supported on this interface. /* The address family is not supported on this interface.
We can continue trying addresses */ We can continue trying addresses */
@ -1309,7 +1315,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
data->state.os_errno = error; data->state.os_errno = error;
/* connect failed */ /* connect failed */
Curl_closesocket(conn, sockfd); Curl_closesocket(data, conn, sockfd);
result = CURLE_COULDNT_CONNECT; result = CURLE_COULDNT_CONNECT;
} }
} }
@ -1326,10 +1332,10 @@ static CURLcode singleipconnect(struct connectdata *conn,
* pointer with the connected socket. * pointer with the connected socket.
*/ */
CURLcode Curl_connecthost(struct connectdata *conn, /* context */ CURLcode Curl_connecthost(struct Curl_easy *data,
struct connectdata *conn, /* context */
const struct Curl_dns_entry *remotehost) const struct Curl_dns_entry *remotehost)
{ {
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_COULDNT_CONNECT; CURLcode result = CURLE_COULDNT_CONNECT;
int i; int i;
timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
@ -1367,7 +1373,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* get through the list in family order in case of quick failures */ /* get through the list in family order in case of quick failures */
for(i = 0; (i < 2) && result; i++) { for(i = 0; (i < 2) && result; i++) {
while(conn->tempaddr[i]) { while(conn->tempaddr[i]) {
result = singleipconnect(conn, conn->tempaddr[i], i); result = singleipconnect(data, conn, conn->tempaddr[i], i);
if(!result) if(!result)
break; break;
ainext(conn, i, TRUE); ainext(conn, i, TRUE);
@ -1376,7 +1382,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if(result) if(result)
return result; return result;
Curl_expire(conn->data, data->set.happy_eyeballs_timeout, Curl_expire(data, data->set.happy_eyeballs_timeout,
EXPIRE_HAPPY_EYEBALLS); EXPIRE_HAPPY_EYEBALLS);
return CURLE_OK; return CURLE_OK;
@ -1387,9 +1393,11 @@ struct connfind {
struct connectdata *found; struct connectdata *found;
}; };
static int conn_is_conn(struct connectdata *conn, void *param) static int conn_is_conn(struct Curl_easy *data,
struct connectdata *conn, void *param)
{ {
struct connfind *f = (struct connfind *)param; struct connfind *f = (struct connfind *)param;
(void)data;
if(conn->connection_id == f->id_tofind) { if(conn->connection_id == f->id_tofind) {
f->found = conn; f->found = conn;
return 1; return 1;
@ -1471,8 +1479,8 @@ bool Curl_connalive(struct connectdata *conn)
* *
* 'conn' can be NULL, beware! * 'conn' can be NULL, beware!
*/ */
int Curl_closesocket(struct connectdata *conn, int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sock) curl_socket_t sock)
{ {
if(conn && conn->fclosesocket) { if(conn && conn->fclosesocket) {
if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted) if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
@ -1482,17 +1490,17 @@ int Curl_closesocket(struct connectdata *conn,
conn->bits.sock_accepted = FALSE; conn->bits.sock_accepted = FALSE;
else { else {
int rc; int rc;
Curl_multi_closed(conn->data, sock); Curl_multi_closed(data, sock);
Curl_set_in_callback(conn->data, true); Curl_set_in_callback(data, true);
rc = conn->fclosesocket(conn->closesocket_client, sock); rc = conn->fclosesocket(conn->closesocket_client, sock);
Curl_set_in_callback(conn->data, false); Curl_set_in_callback(data, false);
return rc; return rc;
} }
} }
if(conn) if(conn)
/* tell the multi-socket code about this */ /* tell the multi-socket code about this */
Curl_multi_closed(conn->data, sock); Curl_multi_closed(data, sock);
sclose(sock); sclose(sock);
@ -1508,12 +1516,12 @@ int Curl_closesocket(struct connectdata *conn,
* If the open socket callback is set, used that! * If the open socket callback is set, used that!
* *
*/ */
CURLcode Curl_socket(struct connectdata *conn, CURLcode Curl_socket(struct Curl_easy *data,
const struct Curl_addrinfo *ai, const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr, struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd) curl_socket_t *sockfd)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct Curl_sockaddr_ex dummy; struct Curl_sockaddr_ex dummy;
if(!addr) if(!addr)
@ -1601,16 +1609,20 @@ void Curl_conncontrol(struct connectdata *conn,
#endif #endif
) )
{ {
/* close if a connection, or a stream that isn't multiplexed */ /* close if a connection, or a stream that isn't multiplexed. */
bool closeit = (ctrl == CONNCTRL_CONNECTION) || /* This function will be called both before and after this connection is
((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM)); associated with a transfer. */
bool closeit;
DEBUGASSERT(conn); DEBUGASSERT(conn);
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)reason; /* useful for debugging */
#endif
closeit = (ctrl == CONNCTRL_CONNECTION) ||
((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
if((ctrl == CONNCTRL_STREAM) && if((ctrl == CONNCTRL_STREAM) &&
(conn->handler->flags & PROTOPT_STREAM)) (conn->handler->flags & PROTOPT_STREAM))
DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); ;
else if((bit)closeit != conn->bits.close) { else if((bit)closeit != conn->bits.close) {
DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
closeit?"closure":"keep alive", reason));
conn->bits.close = closeit; /* the only place in the source code that conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */ should assign this bit */
} }

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -27,11 +27,13 @@
#include "sockaddr.h" #include "sockaddr.h"
#include "timeval.h" #include "timeval.h"
CURLcode Curl_is_connected(struct connectdata *conn, CURLcode Curl_is_connected(struct Curl_easy *data,
struct connectdata *conn,
int sockindex, int sockindex,
bool *connected); bool *connected);
CURLcode Curl_connecthost(struct connectdata *conn, CURLcode Curl_connecthost(struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_dns_entry *host); const struct Curl_dns_entry *host);
/* generic function that returns how much time there's left to run, according /* generic function that returns how much time there's left to run, according
@ -74,11 +76,15 @@ void Curl_sndbufset(curl_socket_t sockfd);
#define Curl_sndbufset(y) Curl_nop_stmt #define Curl_sndbufset(y) Curl_nop_stmt
#endif #endif
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
void Curl_conninfo_remote(struct connectdata *conn, curl_socket_t sockfd); curl_socket_t sockfd);
void Curl_conninfo_local(struct connectdata *conn, curl_socket_t sockfd); void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn,
void Curl_persistconninfo(struct connectdata *conn); curl_socket_t sockfd);
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); void Curl_conninfo_local(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sockfd);
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn);
int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sock);
/* /*
* The Curl_sockaddr_ex structure is basically libcurl's external API * The Curl_sockaddr_ex structure is basically libcurl's external API
@ -106,7 +112,7 @@ struct Curl_sockaddr_ex {
* socket callback is set, used that! * socket callback is set, used that!
* *
*/ */
CURLcode Curl_socket(struct connectdata *conn, CURLcode Curl_socket(struct Curl_easy *data,
const struct Curl_addrinfo *ai, const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr, struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd); curl_socket_t *sockfd);

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -904,7 +904,7 @@ static CURLcode client_unencode_write(struct connectdata *conn,
if(!nbytes || k->ignorebody) if(!nbytes || k->ignorebody)
return CURLE_OK; return CURLE_OK;
return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes); return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
} }
static void client_close_writer(struct connectdata *conn, static void client_close_writer(struct connectdata *conn,

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -131,6 +131,10 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
display_gss_error(minor, GSS_C_MECH_CODE, buf, len); display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
infof(data, "%s%s\n", prefix, buf); infof(data, "%s%s\n", prefix, buf);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
(void)prefix;
#endif
} }
#endif /* HAVE_GSSAPI */ #endif /* HAVE_GSSAPI */

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com> * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
@ -48,11 +48,13 @@
#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ #define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
static CURLcode rtmp_setup_connection(struct connectdata *conn); static CURLcode rtmp_setup_connection(struct Curl_easy *data,
static CURLcode rtmp_do(struct connectdata *conn, bool *done); struct connectdata *conn);
static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature); static CURLcode rtmp_do(struct Curl_easy *data, bool *done);
static CURLcode rtmp_connect(struct connectdata *conn, bool *done); static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature);
static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead); static CURLcode rtmp_connect(struct Curl_easy *data, bool *done);
static CURLcode rtmp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead);
static Curl_recv rtmp_recv; static Curl_recv rtmp_recv;
static Curl_send rtmp_send; static Curl_send rtmp_send;
@ -193,7 +195,8 @@ const struct Curl_handler Curl_handler_rtmpts = {
PROTOPT_NONE /* flags*/ PROTOPT_NONE /* flags*/
}; };
static CURLcode rtmp_setup_connection(struct connectdata *conn) static CURLcode rtmp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
RTMP *r = RTMP_Alloc(); RTMP *r = RTMP_Alloc();
if(!r) if(!r)
@ -201,7 +204,7 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn)
RTMP_Init(r); RTMP_Init(r);
RTMP_SetBufferMS(r, DEF_BUFTIME); RTMP_SetBufferMS(r, DEF_BUFTIME);
if(!RTMP_SetupURL(r, conn->data->change.url)) { if(!RTMP_SetupURL(r, data->change.url)) {
RTMP_Free(r); RTMP_Free(r);
return CURLE_URL_MALFORMAT; return CURLE_URL_MALFORMAT;
} }
@ -209,8 +212,9 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode rtmp_connect(struct connectdata *conn, bool *done) static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp; RTMP *r = conn->proto.rtmp;
SET_RCVTIMEO(tv, 10); SET_RCVTIMEO(tv, 10);
@ -243,9 +247,9 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode rtmp_do(struct connectdata *conn, bool *done) static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp; RTMP *r = conn->proto.rtmp;
if(!RTMP_ConnectStream(r, 0)) if(!RTMP_ConnectStream(r, 0))
@ -261,20 +265,22 @@ static CURLcode rtmp_do(struct connectdata *conn, bool *done)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode rtmp_done(struct connectdata *conn, CURLcode status, static CURLcode rtmp_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
(void)conn; /* unused */ (void)data; /* unused */
(void)status; /* unused */ (void)status; /* unused */
(void)premature; /* unused */ (void)premature; /* unused */
return CURLE_OK; return CURLE_OK;
} }
static CURLcode rtmp_disconnect(struct connectdata *conn, static CURLcode rtmp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection) bool dead_connection)
{ {
RTMP *r = conn->proto.rtmp; RTMP *r = conn->proto.rtmp;
(void)data;
(void)dead_connection; (void)dead_connection;
if(r) { if(r) {
conn->proto.rtmp = NULL; conn->proto.rtmp = NULL;
@ -284,9 +290,10 @@ static CURLcode rtmp_disconnect(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *err) size_t len, CURLcode *err)
{ {
struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp; RTMP *r = conn->proto.rtmp;
ssize_t nread; ssize_t nread;
@ -295,8 +302,8 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
nread = RTMP_Read(r, buf, curlx_uztosi(len)); nread = RTMP_Read(r, buf, curlx_uztosi(len));
if(nread < 0) { if(nread < 0) {
if(r->m_read.status == RTMP_READ_COMPLETE || if(r->m_read.status == RTMP_READ_COMPLETE ||
r->m_read.status == RTMP_READ_EOF) { r->m_read.status == RTMP_READ_EOF) {
conn->data->req.size = conn->data->req.bytecount; data->req.size = data->req.bytecount;
nread = 0; nread = 0;
} }
else else
@ -305,9 +312,10 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
return nread; return nread;
} }
static ssize_t rtmp_send(struct connectdata *conn, int sockindex, static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err) const void *buf, size_t len, CURLcode *err)
{ {
struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp; RTMP *r = conn->proto.rtmp;
ssize_t num; ssize_t num;

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -398,7 +398,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
resp = NULL; resp = NULL;
} }
result = sasl->params->sendauth(conn, mech, resp); result = sasl->params->sendauth(data, conn, mech, resp);
if(!result) { if(!result) {
*progress = SASL_INPROGRESS; *progress = SASL_INPROGRESS;
state(sasl, conn, resp ? state2 : state1); state(sasl, conn, resp ? state2 : state1);
@ -621,12 +621,12 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
switch(result) { switch(result) {
case CURLE_BAD_CONTENT_ENCODING: case CURLE_BAD_CONTENT_ENCODING:
/* Cancel dialog */ /* Cancel dialog */
result = sasl->params->sendcont(conn, "*"); result = sasl->params->sendcont(data, conn, "*");
newstate = SASL_CANCEL; newstate = SASL_CANCEL;
break; break;
case CURLE_OK: case CURLE_OK:
if(resp) if(resp)
result = sasl->params->sendcont(conn, resp); result = sasl->params->sendcont(data, conn, resp);
break; break;
default: default:
newstate = SASL_STOP; /* Stop on error */ newstate = SASL_STOP; /* Stop on error */

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -88,10 +88,12 @@ struct SASLproto {
int contcode; /* Code to receive when continuation is expected */ int contcode; /* Code to receive when continuation is expected */
int finalcode; /* Code to receive upon authentication success */ int finalcode; /* Code to receive upon authentication success */
size_t maxirlen; /* Maximum initial response length */ size_t maxirlen; /* Maximum initial response length */
CURLcode (*sendauth)(struct connectdata *conn, CURLcode (*sendauth)(struct Curl_easy *data,
struct connectdata *conn,
const char *mech, const char *ir); const char *mech, const char *ir);
/* Send authentication command */ /* Send authentication command */
CURLcode (*sendcont)(struct connectdata *conn, const char *contauth); CURLcode (*sendcont)(struct Curl_easy *data,
struct connectdata *conn, const char *contauth);
/* Send authentication continuation */ /* Send authentication continuation */
void (*getmessage)(char *buffer, char **outptr); void (*getmessage)(char *buffer, char **outptr);
/* Get SASL response message */ /* Get SASL response message */

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -67,7 +67,7 @@
* Forward declarations. * Forward declarations.
*/ */
static CURLcode dict_do(struct connectdata *conn, bool *done); static CURLcode dict_do(struct Curl_easy *data, bool *done);
/* /*
* DICT protocol handler. * DICT protocol handler.
@ -129,10 +129,9 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
} }
/* sendf() sends formatted data to the server */ /* sendf() sends formatted data to the server */
static CURLcode sendf(curl_socket_t sockfd, struct connectdata *conn, static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
const char *fmt, ...) const char *fmt, ...)
{ {
struct Curl_easy *data = conn->data;
ssize_t bytes_written; ssize_t bytes_written;
size_t write_len; size_t write_len;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -151,7 +150,7 @@ static CURLcode sendf(curl_socket_t sockfd, struct connectdata *conn,
for(;;) { for(;;) {
/* Write the buffer to the socket */ /* Write the buffer to the socket */
result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); result = Curl_write(data, sockfd, sptr, write_len, &bytes_written);
if(result) if(result)
break; break;
@ -173,7 +172,7 @@ static CURLcode sendf(curl_socket_t sockfd, struct connectdata *conn,
return result; return result;
} }
static CURLcode dict_do(struct connectdata *conn, bool *done) static CURLcode dict_do(struct Curl_easy *data, bool *done)
{ {
char *word; char *word;
char *eword; char *eword;
@ -183,7 +182,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
char *nthdef = NULL; /* This is not part of the protocol, but required char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */ by RFC 2229 */
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = data->state.up.path; char *path = data->state.up.path;
@ -230,7 +229,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(!eword) if(!eword)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
result = sendf(sockfd, conn, result = sendf(sockfd, data,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
"MATCH " "MATCH "
"%s " /* database */ "%s " /* database */
@ -278,7 +277,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(!eword) if(!eword)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
result = sendf(sockfd, conn, result = sendf(sockfd, data,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
"DEFINE " "DEFINE "
"%s " /* database */ "%s " /* database */
@ -306,7 +305,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(ppath[i] == ':') if(ppath[i] == ':')
ppath[i] = ' '; ppath[i] = ' ';
} }
result = sendf(sockfd, conn, result = sendf(sockfd, data,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
"%s\r\n" "%s\r\n"
"QUIT\r\n", ppath); "QUIT\r\n", ppath);

View file

@ -1072,7 +1072,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* even if one function returns error, this loops through and frees /* even if one function returns error, this loops through and frees
all buffers */ all buffers */
if(!result) if(!result)
result = Curl_client_write(conn, writebuf[i].type, result = Curl_client_write(data, writebuf[i].type,
Curl_dyn_ptr(&writebuf[i].b), Curl_dyn_ptr(&writebuf[i].b),
Curl_dyn_len(&writebuf[i].b)); Curl_dyn_len(&writebuf[i].b));
Curl_dyn_free(&writebuf[i].b); Curl_dyn_free(&writebuf[i].b);
@ -1156,8 +1156,13 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
if(result) if(result)
return result; return result;
if(!data->conn)
/* on first invoke, the transfer has been detached from the connection and
needs to be reattached */
Curl_attach_connnection(data, c);
*n = 0; *n = 0;
result = Curl_read(c, sfd, buffer, buflen, &n1); result = Curl_read(data, sfd, buffer, buflen, &n1);
if(result) if(result)
return result; return result;
@ -1186,8 +1191,13 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
if(result) if(result)
return result; return result;
if(!data->conn)
/* on first invoke, the transfer has been detached from the connection and
needs to be reattached */
Curl_attach_connnection(data, c);
*n = 0; *n = 0;
result = Curl_write(c, sfd, buffer, buflen, &n1); result = Curl_write(data, sfd, buffer, buflen, &n1);
if(n1 == -1) if(n1 == -1)
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
@ -1206,16 +1216,16 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
* *
* Returns always 0. * Returns always 0.
*/ */
static int conn_upkeep(struct connectdata *conn, static int conn_upkeep(struct Curl_easy *data,
struct connectdata *conn,
void *param) void *param)
{ {
/* Param is unused. */ /* Param is unused. */
(void)param; (void)param;
if(conn->handler->connection_check) { if(conn->handler->connection_check)
/* Do a protocol-specific keepalive check on the connection. */ /* Do a protocol-specific keepalive check on the connection. */
conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE); conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
}
return 0; /* continue iteration */ return 0; /* continue iteration */
} }

View file

@ -81,13 +81,15 @@
* Forward declarations. * Forward declarations.
*/ */
static CURLcode file_do(struct connectdata *, bool *done); static CURLcode file_do(struct Curl_easy *data, bool *done);
static CURLcode file_done(struct connectdata *conn, static CURLcode file_done(struct Curl_easy *data,
CURLcode status, bool premature); CURLcode status, bool premature);
static CURLcode file_connect(struct connectdata *conn, bool *done); static CURLcode file_connect(struct Curl_easy *data, bool *done);
static CURLcode file_disconnect(struct connectdata *conn, static CURLcode file_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection); bool dead_connection);
static CURLcode file_setup_connection(struct connectdata *conn); static CURLcode file_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
/* /*
* FILE scheme handler. * FILE scheme handler.
@ -116,11 +118,13 @@ const struct Curl_handler Curl_handler_file = {
}; };
static CURLcode file_setup_connection(struct connectdata *conn) static CURLcode file_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
(void)conn;
/* allocate the FILE specific struct */ /* allocate the FILE specific struct */
conn->data->req.p.file = calloc(1, sizeof(struct FILEPROTO)); data->req.p.file = calloc(1, sizeof(struct FILEPROTO));
if(!conn->data->req.p.file) if(!data->req.p.file)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
return CURLE_OK; return CURLE_OK;
@ -131,9 +135,8 @@ static CURLcode file_setup_connection(struct connectdata *conn)
* do protocol-specific actions at connect-time. We emulate a * do protocol-specific actions at connect-time. We emulate a
* connect-then-transfer protocol and "connect" to the file here * connect-then-transfer protocol and "connect" to the file here
*/ */
static CURLcode file_connect(struct connectdata *conn, bool *done) static CURLcode file_connect(struct Curl_easy *data, bool *done)
{ {
struct Curl_easy *data = conn->data;
char *real_path; char *real_path;
struct FILEPROTO *file = data->req.p.file; struct FILEPROTO *file = data->req.p.file;
int fd; int fd;
@ -198,7 +201,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
file->fd = fd; file->fd = fd;
if(!data->set.upload && (fd == -1)) { if(!data->set.upload && (fd == -1)) {
failf(data, "Couldn't open file %s", data->state.up.path); failf(data, "Couldn't open file %s", data->state.up.path);
file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE);
return CURLE_FILE_COULDNT_READ_FILE; return CURLE_FILE_COULDNT_READ_FILE;
} }
*done = TRUE; *done = TRUE;
@ -206,10 +209,10 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode file_done(struct connectdata *conn, static CURLcode file_done(struct Curl_easy *data,
CURLcode status, bool premature) CURLcode status, bool premature)
{ {
struct FILEPROTO *file = conn->data->req.p.file; struct FILEPROTO *file = data->req.p.file;
(void)status; /* not used */ (void)status; /* not used */
(void)premature; /* not used */ (void)premature; /* not used */
@ -224,11 +227,13 @@ static CURLcode file_done(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode file_disconnect(struct connectdata *conn, static CURLcode file_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection) bool dead_connection)
{ {
(void)dead_connection; /* not used */ (void)dead_connection; /* not used */
return file_done(conn, 0, 0); (void)conn;
return file_done(data, 0, 0);
} }
#ifdef DOS_FILESYSTEM #ifdef DOS_FILESYSTEM
@ -237,14 +242,13 @@ static CURLcode file_disconnect(struct connectdata *conn,
#define DIRSEP '/' #define DIRSEP '/'
#endif #endif
static CURLcode file_upload(struct connectdata *conn) static CURLcode file_upload(struct Curl_easy *data)
{ {
struct FILEPROTO *file = conn->data->req.p.file; struct FILEPROTO *file = data->req.p.file;
const char *dir = strchr(file->path, DIRSEP); const char *dir = strchr(file->path, DIRSEP);
int fd; int fd;
int mode; int mode;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer; char *buf = data->state.buffer;
curl_off_t bytecount = 0; curl_off_t bytecount = 0;
struct_stat file_stat; struct_stat file_stat;
@ -254,7 +258,7 @@ static CURLcode file_upload(struct connectdata *conn)
* Since FILE: doesn't do the full init, we need to provide some extra * Since FILE: doesn't do the full init, we need to provide some extra
* assignments here. * assignments here.
*/ */
conn->data->req.upload_fromhere = buf; data->req.upload_fromhere = buf;
if(!dir) if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
@ -273,7 +277,7 @@ static CURLcode file_upload(struct connectdata *conn)
else else
mode = MODE_DEFAULT|O_TRUNC; mode = MODE_DEFAULT|O_TRUNC;
fd = open(file->path, mode, conn->data->set.new_file_perms); fd = open(file->path, mode, data->set.new_file_perms);
if(fd < 0) { if(fd < 0) {
failf(data, "Can't open %s for writing", file->path); failf(data, "Can't open %s for writing", file->path);
return CURLE_WRITE_ERROR; return CURLE_WRITE_ERROR;
@ -297,7 +301,8 @@ static CURLcode file_upload(struct connectdata *conn)
size_t nread; size_t nread;
size_t nwrite; size_t nwrite;
size_t readcount; size_t readcount;
result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount); result = Curl_fillreadbuffer(data->conn, data->set.buffer_size,
&readcount);
if(result) if(result)
break; break;
@ -333,12 +338,12 @@ static CURLcode file_upload(struct connectdata *conn)
Curl_pgrsSetUploadCounter(data, bytecount); Curl_pgrsSetUploadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn)) if(Curl_pgrsUpdate(data->conn))
result = CURLE_ABORTED_BY_CALLBACK; result = CURLE_ABORTED_BY_CALLBACK;
else else
result = Curl_speedcheck(data, Curl_now()); result = Curl_speedcheck(data, Curl_now());
} }
if(!result && Curl_pgrsUpdate(conn)) if(!result && Curl_pgrsUpdate(data->conn))
result = CURLE_ABORTED_BY_CALLBACK; result = CURLE_ABORTED_BY_CALLBACK;
close(fd); close(fd);
@ -354,7 +359,7 @@ static CURLcode file_upload(struct connectdata *conn)
* opposed to sockets) we instead perform the whole do-operation in this * opposed to sockets) we instead perform the whole do-operation in this
* function. * function.
*/ */
static CURLcode file_do(struct connectdata *conn, bool *done) static CURLcode file_do(struct Curl_easy *data, bool *done)
{ {
/* This implementation ignores the host name in conformance with /* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system) RFC 1738. Only local files (reachable via the standard file system)
@ -368,7 +373,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
curl_off_t expected_size = -1; curl_off_t expected_size = -1;
bool size_known; bool size_known;
bool fstated = FALSE; bool fstated = FALSE;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
char *buf = data->state.buffer; char *buf = data->state.buffer;
curl_off_t bytecount = 0; curl_off_t bytecount = 0;
int fd; int fd;
@ -379,9 +384,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
Curl_pgrsStartNow(data); Curl_pgrsStartNow(data);
if(data->set.upload) if(data->set.upload)
return file_upload(conn); return file_upload(data);
file = conn->data->req.p.file; file = data->req.p.file;
/* get the fd from the connection phase */ /* get the fd from the connection phase */
fd = file->fd; fd = file->fd;
@ -411,12 +416,12 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
msnprintf(header, sizeof(header), msnprintf(header, sizeof(header),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
expected_size); expected_size);
result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
if(result) if(result)
return result; return result;
} }
result = Curl_client_write(conn, CLIENTWRITE_HEADER, result = Curl_client_write(data, CLIENTWRITE_HEADER,
(char *)"Accept-ranges: bytes\r\n", 0); (char *)"Accept-ranges: bytes\r\n", 0);
if(result) if(result)
return result; return result;
@ -437,7 +442,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
tm->tm_min, tm->tm_min,
tm->tm_sec, tm->tm_sec,
data->set.opt_no_body ? "": "\r\n"); data->set.opt_no_body ? "": "\r\n");
result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
if(result) if(result)
return result; return result;
/* set the file size to make it available post transfer */ /* set the file size to make it available post transfer */
@ -516,7 +521,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
if(size_known) if(size_known)
expected_size -= nread; expected_size -= nread;
result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); result = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
if(result) if(result)
return result; return result;

877
lib/ftp.c

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -31,7 +31,7 @@ extern const struct Curl_handler Curl_handler_ftp;
extern const struct Curl_handler Curl_handler_ftps; extern const struct Curl_handler Curl_handler_ftps;
#endif #endif
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, CURLcode Curl_GetFTPResponse(struct Curl_easy *data, ssize_t *nread,
int *ftpcode); int *ftpcode);
#endif /* CURL_DISABLE_FTP */ #endif /* CURL_DISABLE_FTP */

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -268,10 +268,11 @@ static int ftp_pl_get_permission(const char *str)
return permissions; return permissions;
} }
static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
struct fileinfo *infop) struct fileinfo *infop)
{ {
curl_fnmatch_callback compare; curl_fnmatch_callback compare;
struct connectdata *conn = data->conn;
struct WildcardData *wc = &conn->data->wildcard; struct WildcardData *wc = &conn->data->wildcard;
struct ftp_wc *ftpwc = wc->protdata; struct ftp_wc *ftpwc = wc->protdata;
struct Curl_llist *llist = &wc->filelist; struct Curl_llist *llist = &wc->filelist;
@ -327,8 +328,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr) void *connptr)
{ {
size_t bufflen = size*nmemb; size_t bufflen = size*nmemb;
struct connectdata *conn = (struct connectdata *)connptr; struct Curl_easy *data = (struct Curl_easy *)connptr;
struct ftp_wc *ftpwc = conn->data->wildcard.protdata; struct ftp_wc *ftpwc = data->wildcard.protdata;
struct ftp_parselist_data *parser = ftpwc->parser; struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop; struct fileinfo *infop;
struct curl_fileinfo *finfo; struct curl_fileinfo *finfo;
@ -728,7 +729,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset; parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE; parser->state.UNIX.main = PL_UNIX_FILETYPE;
result = ftp_pl_insert_finfo(conn, infop); result = ftp_pl_insert_finfo(data, infop);
if(result) { if(result) {
parser->error = result; parser->error = result;
goto fail; goto fail;
@ -740,7 +741,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset; parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE; parser->state.UNIX.main = PL_UNIX_FILETYPE;
result = ftp_pl_insert_finfo(conn, infop); result = ftp_pl_insert_finfo(data, infop);
if(result) { if(result) {
parser->error = result; parser->error = result;
goto fail; goto fail;
@ -835,7 +836,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
else if(c == '\n') { else if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset; parser->offsets.symlink_target = parser->item_offset;
result = ftp_pl_insert_finfo(conn, infop); result = ftp_pl_insert_finfo(data, infop);
if(result) { if(result) {
parser->error = result; parser->error = result;
goto fail; goto fail;
@ -847,7 +848,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
if(c == '\n') { if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset; parser->offsets.symlink_target = parser->item_offset;
result = ftp_pl_insert_finfo(conn, infop); result = ftp_pl_insert_finfo(data, infop);
if(result) { if(result) {
parser->error = result; parser->error = result;
goto fail; goto fail;
@ -967,7 +968,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
parser->offsets.filename = parser->item_offset; parser->offsets.filename = parser->item_offset;
finfo->b_data[finfo->b_used - 1] = 0; finfo->b_data[finfo->b_used - 1] = 0;
parser->offsets.filename = parser->item_offset; parser->offsets.filename = parser->item_offset;
result = ftp_pl_insert_finfo(conn, infop); result = ftp_pl_insert_finfo(data, infop);
if(result) { if(result) {
parser->error = result; parser->error = result;
goto fail; goto fail;
@ -979,7 +980,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
case PL_WINNT_FILENAME_WINEOL: case PL_WINNT_FILENAME_WINEOL:
if(c == '\n') { if(c == '\n') {
parser->offsets.filename = parser->item_offset; parser->offsets.filename = parser->item_offset;
result = ftp_pl_insert_finfo(conn, infop); result = ftp_pl_insert_finfo(data, infop);
if(result) { if(result) {
parser->error = result; parser->error = result;
goto fail; goto fail;

View file

@ -46,10 +46,10 @@
* Forward declarations. * Forward declarations.
*/ */
static CURLcode gopher_do(struct connectdata *conn, bool *done); static CURLcode gopher_do(struct Curl_easy *data, bool *done);
#ifdef USE_SSL #ifdef USE_SSL
static CURLcode gopher_connect(struct connectdata *conn, bool *done); static CURLcode gopher_connect(struct Curl_easy *data, bool *done);
static CURLcode gopher_connecting(struct connectdata *conn, bool *done); static CURLcode gopher_connecting(struct Curl_easy *data, bool *done);
#endif #endif
/* /*
@ -103,15 +103,16 @@ const struct Curl_handler Curl_handler_gophers = {
PROTOPT_SSL /* flags */ PROTOPT_SSL /* flags */
}; };
static CURLcode gopher_connect(struct connectdata *conn, bool *done) static CURLcode gopher_connect(struct Curl_easy *data, bool *done)
{ {
(void)conn; (void)data;
(void)done; (void)done;
return CURLE_OK; return CURLE_OK;
} }
static CURLcode gopher_connecting(struct connectdata *conn, bool *done) static CURLcode gopher_connecting(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
CURLcode result = Curl_ssl_connect(conn, FIRSTSOCKET); CURLcode result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(result) if(result)
connclose(conn, "Failed TLS connection"); connclose(conn, "Failed TLS connection");
@ -120,10 +121,10 @@ static CURLcode gopher_connecting(struct connectdata *conn, bool *done)
} }
#endif #endif
static CURLcode gopher_do(struct connectdata *conn, bool *done) static CURLcode gopher_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *gopherpath; char *gopherpath;
char *path = data->state.up.path; char *path = data->state.up.path;
@ -177,9 +178,9 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
if(strlen(sel) < 1) if(strlen(sel) < 1)
break; break;
result = Curl_write(conn, sockfd, sel, k, &amount); result = Curl_write(data, sockfd, sel, k, &amount);
if(!result) { /* Which may not have written it all! */ if(!result) { /* Which may not have written it all! */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount); result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
if(result) if(result)
break; break;
@ -219,12 +220,12 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
free(sel_org); free(sel_org);
if(!result) if(!result)
result = Curl_write(conn, sockfd, "\r\n", 2, &amount); result = Curl_write(data, sockfd, "\r\n", 2, &amount);
if(result) { if(result) {
failf(data, "Failed sending Gopher request"); failf(data, "Failed sending Gopher request");
return result; return result;
} }
result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2); result = Curl_client_write(data, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
if(result) if(result)
return result; return result;

View file

@ -565,7 +565,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(!addr) { if(!addr) {
/* Check what IP specifics the app has requested and if we can provide /* Check what IP specifics the app has requested and if we can provide
* it. If not, bail out. */ * it. If not, bail out. */
if(!Curl_ipvalid(conn)) if(!Curl_ipvalid(data, conn))
return CURLRESOLV_ERROR; return CURLRESOLV_ERROR;
if(allowDOH && data->set.doh && !ipnum) { if(allowDOH && data->set.doh && !ipnum) {

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -99,7 +99,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
/* /*
* Curl_ipv6works() returns TRUE if IPv6 seems to work. * Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/ */
bool Curl_ipv6works(struct connectdata *conn); bool Curl_ipv6works(struct Curl_easy *data);
#else #else
#define Curl_ipv6works(x) FALSE #define Curl_ipv6works(x) FALSE
#endif #endif
@ -108,7 +108,7 @@ bool Curl_ipv6works(struct connectdata *conn);
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK. * been set and returns TRUE if they are OK.
*/ */
bool Curl_ipvalid(struct connectdata *conn); bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn);
/* /*

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -61,8 +61,9 @@
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK. * been set and returns TRUE if they are OK.
*/ */
bool Curl_ipvalid(struct connectdata *conn) bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
{ {
(void)data;
if(conn->ip_version == CURL_IPRESOLVE_V6) if(conn->ip_version == CURL_IPRESOLVE_V6)
/* An IPv6 address was requested and we can't get/use one */ /* An IPv6 address was requested and we can't get/use one */
return FALSE; return FALSE;

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -62,16 +62,15 @@
/* /*
* Curl_ipv6works() returns TRUE if IPv6 seems to work. * Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/ */
bool Curl_ipv6works(struct connectdata *conn) bool Curl_ipv6works(struct Curl_easy *data)
{ {
if(conn) { if(data) {
/* the nature of most system is that IPv6 status doesn't come and go /* the nature of most system is that IPv6 status doesn't come and go
during a program's lifetime so we only probe the first time and then we during a program's lifetime so we only probe the first time and then we
have the info kept for fast re-use */ have the info kept for fast re-use */
DEBUGASSERT(conn); DEBUGASSERT(data);
DEBUGASSERT(conn->data); DEBUGASSERT(data->multi);
DEBUGASSERT(conn->data->multi); return data->multi->ipv6_works;
return conn->data->multi->ipv6_works;
} }
else { else {
int ipv6_works = -1; int ipv6_works = -1;
@ -82,7 +81,7 @@ bool Curl_ipv6works(struct connectdata *conn)
ipv6_works = 0; ipv6_works = 0;
else { else {
ipv6_works = 1; ipv6_works = 1;
Curl_closesocket(NULL, s); sclose(s);
} }
return (ipv6_works>0)?TRUE:FALSE; return (ipv6_works>0)?TRUE:FALSE;
} }
@ -92,10 +91,10 @@ bool Curl_ipv6works(struct connectdata *conn)
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK. * been set and returns TRUE if they are OK.
*/ */
bool Curl_ipvalid(struct connectdata *conn) bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
{ {
if(conn->ip_version == CURL_IPRESOLVE_V6) if(conn->ip_version == CURL_IPRESOLVE_V6)
return Curl_ipv6works(conn); return Curl_ipv6works(data);
return TRUE; return TRUE;
} }
@ -161,7 +160,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
break; break;
} }
if((pf != PF_INET) && !Curl_ipv6works(conn)) if((pf != PF_INET) && !Curl_ipv6works(data))
/* The stack seems to be a non-IPv6 one */ /* The stack seems to be a non-IPv6 one */
pf = PF_INET; pf = PF_INET;

View file

@ -94,22 +94,25 @@
* Forward declarations. * Forward declarations.
*/ */
static int http_getsock_do(struct connectdata *conn, static int http_getsock_do(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks); curl_socket_t *socks);
static bool http_should_fail(struct connectdata *conn); static bool http_should_fail(struct Curl_easy *data);
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct connectdata *conn); static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
#endif #endif
#ifdef USE_SSL #ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done); static CURLcode https_connecting(struct Curl_easy *data, bool *done);
static int https_getsock(struct connectdata *conn, static int https_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks); curl_socket_t *socks);
#else #else
#define https_connecting(x,y) CURLE_COULDNT_CONNECT #define https_connecting(x,y) CURLE_COULDNT_CONNECT
#endif #endif
static CURLcode http_setup_conn(struct connectdata *conn); static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn);
/* /*
* HTTP handler interface. * HTTP handler interface.
@ -165,19 +168,19 @@ const struct Curl_handler Curl_handler_https = {
}; };
#endif #endif
static CURLcode http_setup_conn(struct connectdata *conn) static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{ {
/* allocate the HTTP-specific struct for the Curl_easy, only to survive /* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */ during this request */
struct HTTP *http; struct HTTP *http;
struct Curl_easy *data = conn->data;
DEBUGASSERT(data->req.p.http == NULL); DEBUGASSERT(data->req.p.http == NULL);
http = calloc(1, sizeof(struct HTTP)); http = calloc(1, sizeof(struct HTTP));
if(!http) if(!http)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_mime_initpart(&http->form, conn->data); Curl_mime_initpart(&http->form, data);
data->req.p.http = http; data->req.p.http = http;
if(data->set.httpversion == CURL_HTTP_VERSION_3) { if(data->set.httpversion == CURL_HTTP_VERSION_3) {
@ -205,16 +208,16 @@ static CURLcode http_setup_conn(struct connectdata *conn)
* if proxy headers are not available, then it will lookup into http header * if proxy headers are not available, then it will lookup into http header
* link list * link list
* *
* It takes a connectdata struct as input instead of the Curl_easy simply to * It takes a connectdata struct as input to see if this is a proxy request or
* know if this is a proxy request or not, as it then might check a different * not, as it then might check a different header list. Provide the header
* header list. Provide the header prefix without colon!. * prefix without colon!
*/ */
char *Curl_checkProxyheaders(const struct connectdata *conn, char *Curl_checkProxyheaders(struct Curl_easy *data,
const struct connectdata *conn,
const char *thisheader) const char *thisheader)
{ {
struct curl_slist *head; struct curl_slist *head;
size_t thislen = strlen(thisheader); size_t thislen = strlen(thisheader);
struct Curl_easy *data = conn->data;
for(head = (conn->bits.proxy && data->set.sep_headers) ? for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers; data->set.proxyheaders : data->set.headers;
@ -228,7 +231,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
} }
#else #else
/* disabled */ /* disabled */
#define Curl_checkProxyheaders(x,y) NULL #define Curl_checkProxyheaders(x,y,z) NULL
#endif #endif
/* /*
@ -291,11 +294,11 @@ char *Curl_copy_header_value(const char *header)
* *
* Returns CURLcode. * Returns CURLcode.
*/ */
static CURLcode http_output_basic(struct connectdata *conn, bool proxy) static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
{ {
size_t size = 0; size_t size = 0;
char *authorization = NULL; char *authorization = NULL;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
char **userp; char **userp;
const char *user; const char *user;
const char *pwd; const char *pwd;
@ -351,16 +354,15 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
* *
* Returns CURLcode. * Returns CURLcode.
*/ */
static CURLcode http_output_bearer(struct connectdata *conn) static CURLcode http_output_bearer(struct Curl_easy *data)
{ {
char **userp; char **userp;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
userp = &data->state.aptr.userpwd; userp = &data->state.aptr.userpwd;
free(*userp); free(*userp);
*userp = aprintf("Authorization: Bearer %s\r\n", *userp = aprintf("Authorization: Bearer %s\r\n",
conn->data->set.str[STRING_BEARER]); data->set.str[STRING_BEARER]);
if(!*userp) { if(!*userp) {
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
@ -433,9 +435,9 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
* } * }
* } * }
*/ */
static CURLcode http_perhapsrewind(struct connectdata *conn) static CURLcode http_perhapsrewind(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.p.http; struct HTTP *http = data->req.p.http;
curl_off_t bytessent; curl_off_t bytessent;
curl_off_t expectsend = -1; /* default is unknown */ curl_off_t expectsend = -1; /* default is unknown */
@ -565,9 +567,9 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
* picked. * picked.
*/ */
CURLcode Curl_http_auth_act(struct connectdata *conn) CURLcode Curl_http_auth_act(struct Curl_easy *data)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
bool pickhost = FALSE; bool pickhost = FALSE;
bool pickproxy = FALSE; bool pickproxy = FALSE;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -593,7 +595,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
conn->httpversion > 11) { conn->httpversion > 11) {
infof(data, "Forcing HTTP/1.1 for NTLM"); infof(data, "Forcing HTTP/1.1 for NTLM");
connclose(conn, "Force HTTP/1.1 connection"); connclose(conn, "Force HTTP/1.1 connection");
conn->data->set.httpversion = CURL_HTTP_VERSION_1_1; data->set.httpversion = CURL_HTTP_VERSION_1_1;
} }
} }
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
@ -611,7 +613,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
if((data->state.httpreq != HTTPREQ_GET) && if((data->state.httpreq != HTTPREQ_GET) &&
(data->state.httpreq != HTTPREQ_HEAD) && (data->state.httpreq != HTTPREQ_HEAD) &&
!conn->bits.rewindaftersend) { !conn->bits.rewindaftersend) {
result = http_perhapsrewind(conn); result = http_perhapsrewind(data, conn);
if(result) if(result)
return result; return result;
} }
@ -638,7 +640,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
data->state.authhost.done = TRUE; data->state.authhost.done = TRUE;
} }
} }
if(http_should_fail(conn)) { if(http_should_fail(data)) {
failf(data, "The requested URL returned error: %d", failf(data, "The requested URL returned error: %d",
data->req.httpcode); data->req.httpcode);
result = CURLE_HTTP_RETURNED_ERROR; result = CURLE_HTTP_RETURNED_ERROR;
@ -653,7 +655,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
* and whether or not it is to a proxy. * and whether or not it is to a proxy.
*/ */
static CURLcode static CURLcode
output_auth_headers(struct connectdata *conn, output_auth_headers(struct Curl_easy *data,
struct connectdata *conn,
struct auth *authstatus, struct auth *authstatus,
const char *request, const char *request,
const char *path, const char *path,
@ -661,7 +664,6 @@ output_auth_headers(struct connectdata *conn,
{ {
const char *auth = NULL; const char *auth = NULL;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
#ifdef CURL_DISABLE_CRYPTO_AUTH #ifdef CURL_DISABLE_CRYPTO_AUTH
(void)request; (void)request;
@ -720,12 +722,12 @@ output_auth_headers(struct connectdata *conn,
if( if(
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
(proxy && conn->bits.proxy_user_passwd && (proxy && conn->bits.proxy_user_passwd &&
!Curl_checkProxyheaders(conn, "Proxy-authorization")) || !Curl_checkProxyheaders(data, conn, "Proxy-authorization")) ||
#endif #endif
(!proxy && conn->bits.user_passwd && (!proxy && conn->bits.user_passwd &&
!Curl_checkheaders(conn, "Authorization"))) { !Curl_checkheaders(data, "Authorization"))) {
auth = "Basic"; auth = "Basic";
result = http_output_basic(conn, proxy); result = http_output_basic(data, proxy);
if(result) if(result)
return result; return result;
} }
@ -737,9 +739,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_BEARER) { if(authstatus->picked == CURLAUTH_BEARER) {
/* Bearer */ /* Bearer */
if((!proxy && data->set.str[STRING_BEARER] && if((!proxy && data->set.str[STRING_BEARER] &&
!Curl_checkheaders(conn, "Authorization:"))) { !Curl_checkheaders(data, "Authorization:"))) {
auth = "Bearer"; auth = "Bearer";
result = http_output_bearer(conn); result = http_output_bearer(data);
if(result) if(result)
return result; return result;
} }
@ -770,7 +772,7 @@ output_auth_headers(struct connectdata *conn,
/** /**
* Curl_http_output_auth() setups the authentication headers for the * Curl_http_output_auth() setups the authentication headers for the
* host/proxy and the correct authentication * host/proxy and the correct authentication
* method. conn->data->state.authdone is set to TRUE when authentication is * method. data->state.authdone is set to TRUE when authentication is
* done. * done.
* *
* @param conn all information about the current connection * @param conn all information about the current connection
@ -782,7 +784,8 @@ output_auth_headers(struct connectdata *conn,
* @returns CURLcode * @returns CURLcode
*/ */
CURLcode CURLcode
Curl_http_output_auth(struct connectdata *conn, Curl_http_output_auth(struct Curl_easy *data,
struct connectdata *conn,
const char *request, const char *request,
Curl_HttpReq httpreq, Curl_HttpReq httpreq,
const char *path, const char *path,
@ -790,7 +793,6 @@ Curl_http_output_auth(struct connectdata *conn,
up the proxy tunnel */ up the proxy tunnel */
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct auth *authhost; struct auth *authhost;
struct auth *authproxy; struct auth *authproxy;
@ -827,7 +829,7 @@ Curl_http_output_auth(struct connectdata *conn,
/* Send proxy authentication header if needed */ /* Send proxy authentication header if needed */
if(conn->bits.httpproxy && if(conn->bits.httpproxy &&
(conn->bits.tunnel_proxy == (bit)proxytunnel)) { (conn->bits.tunnel_proxy == (bit)proxytunnel)) {
result = output_auth_headers(conn, authproxy, request, path, TRUE); result = output_auth_headers(data, conn, authproxy, request, path, TRUE);
if(result) if(result)
return result; return result;
} }
@ -846,7 +848,7 @@ Curl_http_output_auth(struct connectdata *conn,
!data->state.first_host || !data->state.first_host ||
data->set.allow_auth_to_other_hosts || data->set.allow_auth_to_other_hosts ||
strcasecompare(data->state.first_host, conn->host.name)) { strcasecompare(data->state.first_host, conn->host.name)) {
result = output_auth_headers(conn, authhost, request, path, FALSE); result = output_auth_headers(data, conn, authhost, request, path, FALSE);
} }
else else
authhost->done = TRUE; authhost->done = TRUE;
@ -887,14 +889,13 @@ Curl_http_output_auth(struct connectdata *conn,
* proxy CONNECT loop. * proxy CONNECT loop.
*/ */
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth) /* the first non-space */ const char *auth) /* the first non-space */
{ {
/* /*
* This resource requires authentication * This resource requires authentication
*/ */
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
#ifdef USE_SPNEGO #ifdef USE_SPNEGO
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state : curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state; &conn->http_negotiate_state;
@ -1062,14 +1063,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
* *
* @retval TRUE communications should not continue * @retval TRUE communications should not continue
*/ */
static bool http_should_fail(struct connectdata *conn) static bool http_should_fail(struct Curl_easy *data)
{ {
struct Curl_easy *data;
int httpcode; int httpcode;
DEBUGASSERT(conn);
data = conn->data;
DEBUGASSERT(data); DEBUGASSERT(data);
DEBUGASSERT(data->conn);
httpcode = data->req.httpcode; httpcode = data->req.httpcode;
@ -1116,10 +1114,10 @@ static bool http_should_fail(struct connectdata *conn)
** Either we're not authenticating, or we're supposed to ** Either we're not authenticating, or we're supposed to
** be authenticating something else. This is an error. ** be authenticating something else. This is an error.
*/ */
if((httpcode == 401) && !conn->bits.user_passwd) if((httpcode == 401) && !data->conn->bits.user_passwd)
return TRUE; return TRUE;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
if((httpcode == 407) && !conn->bits.proxy_user_passwd) if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
return TRUE; return TRUE;
#endif #endif
@ -1140,8 +1138,8 @@ static size_t readmoredata(char *buffer,
size_t nitems, size_t nitems,
void *userp) void *userp)
{ {
struct connectdata *conn = (struct connectdata *)userp; struct Curl_easy *data = (struct Curl_easy *)userp;
struct HTTP *http = conn->data->req.p.http; struct HTTP *http = data->req.p.http;
size_t fullsize = size * nitems; size_t fullsize = size * nitems;
if(!http->postsize) if(!http->postsize)
@ -1149,7 +1147,7 @@ static size_t readmoredata(char *buffer,
return 0; return 0;
/* make sure that a HTTP request is never sent away chunked! */ /* make sure that a HTTP request is never sent away chunked! */
conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(http->postsize <= (curl_off_t)fullsize) { if(http->postsize <= (curl_off_t)fullsize) {
memcpy(buffer, http->postdata, (size_t)http->postsize); memcpy(buffer, http->postdata, (size_t)http->postsize);
@ -1159,8 +1157,8 @@ static size_t readmoredata(char *buffer,
/* move backup data into focus and continue on that */ /* move backup data into focus and continue on that */
http->postdata = http->backup.postdata; http->postdata = http->backup.postdata;
http->postsize = http->backup.postsize; http->postsize = http->backup.postsize;
conn->data->state.fread_func = http->backup.fread_func; data->state.fread_func = http->backup.fread_func;
conn->data->state.in = http->backup.fread_in; data->state.in = http->backup.fread_in;
http->sending++; /* move one step up */ http->sending++; /* move one step up */
@ -1186,7 +1184,7 @@ static size_t readmoredata(char *buffer,
* Returns CURLcode * Returns CURLcode
*/ */
CURLcode Curl_buffer_send(struct dynbuf *in, CURLcode Curl_buffer_send(struct dynbuf *in,
struct connectdata *conn, struct Curl_easy *data,
/* add the number of sent bytes to this /* add the number of sent bytes to this
counter */ counter */
curl_off_t *bytes_written, curl_off_t *bytes_written,
@ -1198,7 +1196,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
CURLcode result; CURLcode result;
char *ptr; char *ptr;
size_t size; size_t size;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct HTTP *http = data->req.p.http; struct HTTP *http = data->req.p.http;
size_t sendsize; size_t sendsize;
curl_socket_t sockfd; curl_socket_t sockfd;
@ -1274,7 +1272,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
sendsize = size; sendsize = size;
} }
result = Curl_write(conn, sockfd, ptr, sendsize, &amount); result = Curl_write(data, sockfd, ptr, sendsize, &amount);
if(!result) { if(!result) {
/* /*
@ -1321,7 +1319,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
/* set the new pointers for the request-sending */ /* set the new pointers for the request-sending */
data->state.fread_func = (curl_read_callback)readmoredata; data->state.fread_func = (curl_read_callback)readmoredata;
data->state.in = (void *)conn; data->state.in = (void *)data;
http->postdata = ptr; http->postdata = ptr;
http->postsize = (curl_off_t)size; http->postsize = (curl_off_t)size;
@ -1421,9 +1419,10 @@ Curl_compareheader(const char *headerline, /* line to check */
* Curl_http_connect() performs HTTP stuff to do at connect-time, called from * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
* the generic Curl_connect(). * the generic Curl_connect().
*/ */
CURLcode Curl_http_connect(struct connectdata *conn, bool *done) CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
{ {
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
/* We default to persistent connections. We set this already in this connect /* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */ function to make the re-use checks properly be able to check this bit. */
@ -1446,9 +1445,9 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* nothing else to do except wait right now - we're not done here. */ /* nothing else to do except wait right now - we're not done here. */
return CURLE_OK; return CURLE_OK;
if(conn->data->set.haproxyprotocol) { if(data->set.haproxyprotocol) {
/* add HAProxy PROXY protocol header */ /* add HAProxy PROXY protocol header */
result = add_haproxy_protocol_header(conn); result = add_haproxy_protocol_header(data);
if(result) if(result)
return result; return result;
} }
@ -1456,7 +1455,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
if(conn->given->protocol & CURLPROTO_HTTPS) { if(conn->given->protocol & CURLPROTO_HTTPS) {
/* perform SSL initialization */ /* perform SSL initialization */
result = https_connecting(conn, done); result = https_connecting(data, done);
if(result) if(result)
return result; return result;
} }
@ -1469,24 +1468,27 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* this returns the socket to wait for in the DO and DOING state for the multi /* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */ the single socket to become writable only */
static int http_getsock_do(struct connectdata *conn, static int http_getsock_do(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks) curl_socket_t *socks)
{ {
/* write mode */ /* write mode */
(void)data;
socks[0] = conn->sock[FIRSTSOCKET]; socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0); return GETSOCK_WRITESOCK(0);
} }
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct connectdata *conn) static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
{ {
char proxy_header[128]; char proxy_header[128];
struct dynbuf req; struct dynbuf req;
CURLcode result; CURLcode result;
char tcp_version[5]; char tcp_version[5];
DEBUGASSERT(data->conn);
/* Emit the correct prefix for IPv6 */ /* Emit the correct prefix for IPv6 */
if(conn->bits.ipv6) { if(data->conn->bits.ipv6) {
strcpy(tcp_version, "TCP6"); strcpy(tcp_version, "TCP6");
} }
else { else {
@ -1497,10 +1499,10 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
sizeof(proxy_header), sizeof(proxy_header),
"PROXY %s %s %s %li %li\r\n", "PROXY %s %s %s %li %li\r\n",
tcp_version, tcp_version,
conn->data->info.conn_local_ip, data->info.conn_local_ip,
conn->data->info.conn_primary_ip, data->info.conn_primary_ip,
conn->data->info.conn_local_port, data->info.conn_local_port,
conn->data->info.conn_primary_port); data->info.conn_primary_port);
Curl_dyn_init(&req, DYN_HAXPROXY); Curl_dyn_init(&req, DYN_HAXPROXY);
@ -1508,7 +1510,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
if(result) if(result)
return result; return result;
result = Curl_buffer_send(&req, conn, &conn->data->info.request_size, result = Curl_buffer_send(&req, data, &data->info.request_size,
0, FIRSTSOCKET); 0, FIRSTSOCKET);
return result; return result;
@ -1516,10 +1518,11 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
#endif #endif
#ifdef USE_SSL #ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done) static CURLcode https_connecting(struct Curl_easy *data, bool *done)
{ {
CURLcode result; CURLcode result;
DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL)); struct connectdata *conn = data->conn;
DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));
#ifdef ENABLE_QUIC #ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC) { if(conn->transport == TRNSPRT_QUIC) {
@ -1536,9 +1539,11 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
return result; return result;
} }
static int https_getsock(struct connectdata *conn, static int https_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks) curl_socket_t *socks)
{ {
(void)data;
if(conn->handler->flags & PROTOPT_SSL) if(conn->handler->flags & PROTOPT_SSL)
return Curl_ssl_getsock(conn, socks); return Curl_ssl_getsock(conn, socks);
return GETSOCK_BLANK; return GETSOCK_BLANK;
@ -1550,10 +1555,10 @@ static int https_getsock(struct connectdata *conn,
* performed. * performed.
*/ */
CURLcode Curl_http_done(struct connectdata *conn, CURLcode Curl_http_done(struct Curl_easy *data,
CURLcode status, bool premature) CURLcode status, bool premature)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct HTTP *http = data->req.p.http; struct HTTP *http = data->req.p.http;
/* Clear multipass flag. If authentication isn't done yet, then it will get /* Clear multipass flag. If authentication isn't done yet, then it will get
@ -1653,7 +1658,7 @@ static CURLcode expect100(struct Curl_easy *data,
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */ operations (as there is one packet coming back from the web server) */
const char *ptr = Curl_checkheaders(conn, "Expect"); const char *ptr = Curl_checkheaders(data, "Expect");
if(ptr) { if(ptr) {
data->state.expect100header = data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue"); Curl_compareheader(ptr, "Expect:", "100-continue");
@ -1719,7 +1724,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
return result; return result;
} }
CURLcode Curl_add_custom_headers(struct connectdata *conn, CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect, bool is_connect,
#ifndef USE_HYPER #ifndef USE_HYPER
struct dynbuf *req struct dynbuf *req
@ -1728,11 +1733,11 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
#endif #endif
) )
{ {
struct connectdata *conn = data->conn;
char *ptr; char *ptr;
struct curl_slist *h[2]; struct curl_slist *h[2];
struct curl_slist *headers; struct curl_slist *headers;
int numlists = 1; /* by default */ int numlists = 1; /* by default */
struct Curl_easy *data = conn->data;
int i; int i;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
@ -1876,15 +1881,14 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
} }
#ifndef CURL_DISABLE_PARSEDATE #ifndef CURL_DISABLE_PARSEDATE
CURLcode Curl_add_timecondition(const struct connectdata *conn, CURLcode Curl_add_timecondition(struct Curl_easy *data,
#ifndef USE_HYPER #ifndef USE_HYPER
struct dynbuf *req struct dynbuf *req
#else #else
void *req void *req
#endif #endif
) )
{ {
struct Curl_easy *data = conn->data;
const struct tm *tm; const struct tm *tm;
struct tm keeptime; struct tm keeptime;
CURLcode result; CURLcode result;
@ -1917,7 +1921,7 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
break; break;
} }
if(Curl_checkheaders(conn, condp)) { if(Curl_checkheaders(data, condp)) {
/* A custom header was specified; it will be sent instead. */ /* A custom header was specified; it will be sent instead. */
return CURLE_OK; return CURLE_OK;
} }
@ -2000,13 +2004,13 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
*reqp = httpreq; *reqp = httpreq;
} }
CURLcode Curl_http_useragent(struct Curl_easy *data, struct connectdata *conn) CURLcode Curl_http_useragent(struct Curl_easy *data)
{ {
/* The User-Agent string might have been allocated in url.c already, because /* The User-Agent string might have been allocated in url.c already, because
it might have been used in the proxy connect, but if we have got a header it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string with the user-agent string specified, we erase the previously made string
here. */ here. */
if(Curl_checkheaders(conn, "User-Agent")) { if(Curl_checkheaders(data, "User-Agent")) {
free(data->state.aptr.uagent); free(data->state.aptr.uagent);
data->state.aptr.uagent = NULL; data->state.aptr.uagent = NULL;
} }
@ -2029,7 +2033,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
} }
Curl_safefree(data->state.aptr.host); Curl_safefree(data->state.aptr.host);
ptr = Curl_checkheaders(conn, "Host"); ptr = Curl_checkheaders(data, "Host");
if(ptr && (!data->state.this_is_a_follow || if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) { strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES) #if !defined(CURL_DISABLE_COOKIES)
@ -2245,7 +2249,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
#ifndef CURL_DISABLE_MIME #ifndef CURL_DISABLE_MIME
if(http->sendit) { if(http->sendit) {
const char *cthdr = Curl_checkheaders(conn, "Content-Type"); const char *cthdr = Curl_checkheaders(data, "Content-Type");
/* Read and seek body only. */ /* Read and seek body only. */
http->sendit->flags |= MIME_BODY_ONLY; http->sendit->flags |= MIME_BODY_ONLY;
@ -2270,7 +2274,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
} }
#endif #endif
ptr = Curl_checkheaders(conn, "Transfer-Encoding"); ptr = Curl_checkheaders(data, "Transfer-Encoding");
if(ptr) { if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */ /* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky = data->req.upload_chunky =
@ -2331,7 +2335,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
http->postsize = data->state.infilesize; http->postsize = data->state.infilesize;
if((http->postsize != -1) && !data->req.upload_chunky && if((http->postsize != -1) && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */ /* only add Content-Length if not uploading chunked */
result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", http->postsize); "\r\n", http->postsize);
@ -2354,7 +2358,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
result = Curl_buffer_send(r, conn, &data->info.request_size, 0, result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET); FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending PUT request"); failf(data, "Failed sending PUT request");
@ -2375,7 +2379,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
if(result) if(result)
return result; return result;
result = Curl_buffer_send(r, conn, &data->info.request_size, 0, result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET); FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending POST request"); failf(data, "Failed sending POST request");
@ -2391,7 +2395,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
we don't upload data chunked, as RFC2616 forbids us to set both we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */ kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if(http->postsize != -1 && !data->req.upload_chunky && if(http->postsize != -1 && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation, /* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */ although it isn't very wise to actually set your own */
result = Curl_dyn_addf(r, result = Curl_dyn_addf(r,
@ -2418,7 +2422,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
the somewhat bigger ones we allow the app to disable it. Just make the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value sure that the expect100header is always set to the preferred value
here. */ here. */
ptr = Curl_checkheaders(conn, "Expect"); ptr = Curl_checkheaders(data, "Expect");
if(ptr) { if(ptr) {
data->state.expect100header = data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue"); Curl_compareheader(ptr, "Expect:", "100-continue");
@ -2445,7 +2449,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
http->sending = HTTPSEND_BODY; http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
result = Curl_buffer_send(r, conn, &data->info.request_size, 0, result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET); FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending POST request"); failf(data, "Failed sending POST request");
@ -2471,7 +2475,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
we don't upload data chunked, as RFC2616 forbids us to set both we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */ kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if((http->postsize != -1) && !data->req.upload_chunky && if((http->postsize != -1) && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation, /* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */ although it isn't very wise to actually set your own */
result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
@ -2480,7 +2484,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result; return result;
} }
if(!Curl_checkheaders(conn, "Content-Type")) { if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_add(r, "Content-Type: application/" result = Curl_dyn_add(r, "Content-Type: application/"
"x-www-form-urlencoded\r\n"); "x-www-form-urlencoded\r\n");
if(result) if(result)
@ -2491,7 +2495,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
the somewhat bigger ones we allow the app to disable it. Just make the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value sure that the expect100header is always set to the preferred value
here. */ here. */
ptr = Curl_checkheaders(conn, "Expect"); ptr = Curl_checkheaders(data, "Expect");
if(ptr) { if(ptr) {
data->state.expect100header = data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue"); Curl_compareheader(ptr, "Expect:", "100-continue");
@ -2565,7 +2569,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
http->sending = HTTPSEND_BODY; http->sending = HTTPSEND_BODY;
data->state.fread_func = (curl_read_callback)readmoredata; data->state.fread_func = (curl_read_callback)readmoredata;
data->state.in = (void *)conn; data->state.in = (void *)data;
/* set the upload size to the progress meter */ /* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
@ -2604,7 +2608,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
} }
} }
/* issue the request */ /* issue the request */
result = Curl_buffer_send(r, conn, &data->info.request_size, result = Curl_buffer_send(r, data, &data->info.request_size,
(size_t)included_body, FIRSTSOCKET); (size_t)included_body, FIRSTSOCKET);
if(result) if(result)
@ -2620,7 +2624,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result; return result;
/* issue the request */ /* issue the request */
result = Curl_buffer_send(r, conn, &data->info.request_size, 0, result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET); FIRSTSOCKET);
if(result) if(result)
@ -2640,7 +2644,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
char *addcookies = NULL; char *addcookies = NULL;
if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie")) if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie"))
addcookies = data->set.str[STRING_COOKIE]; addcookies = data->set.str[STRING_COOKIE];
if(data->cookies || addcookies) { if(data->cookies || addcookies) {
@ -2697,7 +2701,6 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
#endif #endif
CURLcode Curl_http_range(struct Curl_easy *data, CURLcode Curl_http_range(struct Curl_easy *data,
struct connectdata *conn,
Curl_HttpReq httpreq) Curl_HttpReq httpreq)
{ {
if(data->state.use_range) { if(data->state.use_range) {
@ -2707,14 +2710,14 @@ CURLcode Curl_http_range(struct Curl_easy *data,
* ones if any such are specified. * ones if any such are specified.
*/ */
if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
!Curl_checkheaders(conn, "Range")) { !Curl_checkheaders(data, "Range")) {
/* if a line like this was already allocated, free the previous one */ /* if a line like this was already allocated, free the previous one */
free(data->state.aptr.rangeline); free(data->state.aptr.rangeline);
data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n", data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range); data->state.range);
} }
else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) && else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
!Curl_checkheaders(conn, "Content-Range")) { !Curl_checkheaders(data, "Content-Range")) {
/* if a line like this was already allocated, free the previous one */ /* if a line like this was already allocated, free the previous one */
free(data->state.aptr.rangeline); free(data->state.aptr.rangeline);
@ -2902,9 +2905,9 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
* request is to be performed. This creates and sends a properly constructed * request is to be performed. This creates and sends a properly constructed
* HTTP request. * HTTP request.
*/ */
CURLcode Curl_http(struct connectdata *conn, bool *done) CURLcode Curl_http(struct Curl_easy *data, bool *done)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct HTTP *http; struct HTTP *http;
Curl_HttpReq httpreq; Curl_HttpReq httpreq;
@ -2927,7 +2930,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
case CURL_HTTP_VERSION_2: case CURL_HTTP_VERSION_2:
conn->httpversion = 20; /* we know we're on HTTP/2 now */ conn->httpversion = 20; /* we know we're on HTTP/2 now */
result = Curl_http2_switched(conn, NULL, 0); result = Curl_http2_switched(data, NULL, 0);
if(result) if(result)
return result; return result;
break; break;
@ -2937,8 +2940,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
default: default:
/* Check if user wants to use HTTP/2 with clear TCP*/ /* Check if user wants to use HTTP/2 with clear TCP*/
#ifdef USE_NGHTTP2 #ifdef USE_NGHTTP2
if(conn->data->set.httpversion == if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
/* We don't support HTTP/2 proxies yet. Also it's debatable /* We don't support HTTP/2 proxies yet. Also it's debatable
@ -2950,7 +2952,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
DEBUGF(infof(data, "HTTP/2 over clean TCP\n")); DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
conn->httpversion = 20; conn->httpversion = 20;
result = Curl_http2_switched(conn, NULL, 0); result = Curl_http2_switched(data, NULL, 0);
if(result) if(result)
return result; return result;
} }
@ -2960,7 +2962,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
else { else {
/* prepare for a http2 request */ /* prepare for a http2 request */
result = Curl_http2_setup(conn); result = Curl_http2_setup(data, conn);
if(result) if(result)
return result; return result;
} }
@ -2972,7 +2974,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result) if(result)
return result; return result;
result = Curl_http_useragent(data, conn); result = Curl_http_useragent(data);
if(result) if(result)
return result; return result;
@ -2986,7 +2988,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!pq) if(!pq)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
result = Curl_http_output_auth(conn, request, httpreq, result = Curl_http_output_auth(data, conn, request, httpreq,
(pq ? pq : data->state.up.path), FALSE); (pq ? pq : data->state.up.path), FALSE);
free(pq); free(pq);
if(result) if(result)
@ -2994,13 +2996,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
Curl_safefree(data->state.aptr.ref); Curl_safefree(data->state.aptr.ref);
if(data->change.referer && !Curl_checkheaders(conn, "Referer")) { if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
if(!data->state.aptr.ref) if(!data->state.aptr.ref)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(!Curl_checkheaders(conn, "Accept-Encoding") && if(!Curl_checkheaders(data, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) { data->set.str[STRING_ENCODING]) {
Curl_safefree(data->state.aptr.accept_encoding); Curl_safefree(data->state.aptr.accept_encoding);
data->state.aptr.accept_encoding = data->state.aptr.accept_encoding =
@ -3016,14 +3018,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */ /* we only consider transfer-encoding magic if libz support is built-in */
if(!Curl_checkheaders(conn, "TE") && if(!Curl_checkheaders(data, "TE") &&
data->set.http_transfer_encoding) { data->set.http_transfer_encoding) {
/* When we are to insert a TE: header in the request, we must also insert /* When we are to insert a TE: header in the request, we must also insert
TE in a Connection: header, so we need to merge the custom provided TE in a Connection: header, so we need to merge the custom provided
Connection: header and prevent the original to get sent. Note that if Connection: header and prevent the original to get sent. Note that if
the user has inserted his/her own TE: header we don't do this magic the user has inserted his/her own TE: header we don't do this magic
but then assume that the user will handle it all! */ but then assume that the user will handle it all! */
char *cptr = Curl_checkheaders(conn, "Connection"); char *cptr = Curl_checkheaders(data, "Connection");
#define TE_HEADER "TE: gzip\r\n" #define TE_HEADER "TE: gzip\r\n"
Curl_safefree(data->state.aptr.te); Curl_safefree(data->state.aptr.te);
@ -3048,13 +3050,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result) if(result)
return result; return result;
p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n"; p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
result = Curl_http_resume(data, conn, httpreq); result = Curl_http_resume(data, conn, httpreq);
if(result) if(result)
return result; return result;
result = Curl_http_range(data, conn, httpreq); result = Curl_http_range(data, httpreq);
if(result) if(result)
return result; return result;
@ -3074,7 +3076,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
#ifndef CURL_DISABLE_ALTSVC #ifndef CURL_DISABLE_ALTSVC
if(conn->bits.altused && !Curl_checkheaders(conn, "Alt-Used")) { if(conn->bits.altused && !Curl_checkheaders(data, "Alt-Used")) {
altused = aprintf("Alt-Used: %s:%d\r\n", altused = aprintf("Alt-Used: %s:%d\r\n",
conn->conn_to_host.name, conn->conn_to_port); conn->conn_to_host.name, conn->conn_to_port);
if(!altused) { if(!altused) {
@ -3121,7 +3123,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
(conn->bits.httpproxy && (conn->bits.httpproxy &&
!conn->bits.tunnel_proxy && !conn->bits.tunnel_proxy &&
!Curl_checkProxyheaders(conn, "Proxy-Connection"))? !Curl_checkProxyheaders(data, conn, "Proxy-Connection"))?
"Proxy-Connection: Keep-Alive\r\n":"", "Proxy-Connection: Keep-Alive\r\n":"",
#else #else
"", "",
@ -3155,9 +3157,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
result = Curl_http_cookies(data, conn, &req); result = Curl_http_cookies(data, conn, &req);
if(!result) if(!result)
result = Curl_add_timecondition(conn, &req); result = Curl_add_timecondition(data, &req);
if(!result) if(!result)
result = Curl_add_custom_headers(conn, FALSE, &req); result = Curl_add_custom_headers(data, FALSE, &req);
if(!result) { if(!result) {
http->postdata = NULL; /* nothing to post at this point */ http->postdata = NULL; /* nothing to post at this point */
@ -3515,7 +3517,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
if(!auth) if(!auth)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
result = Curl_http_input_auth(conn, proxy, auth); result = Curl_http_input_auth(data, proxy, auth);
free(auth); free(auth);
@ -3560,7 +3562,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
/* some cases of POST and PUT etc needs to rewind the data /* some cases of POST and PUT etc needs to rewind the data
stream at this point */ stream at this point */
result = http_perhapsrewind(conn); result = http_perhapsrewind(data, conn);
if(result) if(result)
return result; return result;
} }
@ -3849,7 +3851,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* switch to http2 now. The bytes after response headers /* switch to http2 now. The bytes after response headers
are also processed here, otherwise they are lost. */ are also processed here, otherwise they are lost. */
result = Curl_http2_switched(conn, k->str, *nread); result = Curl_http2_switched(data, k->str, *nread);
if(result) if(result)
return result; return result;
*nread = 0; *nread = 0;
@ -3923,7 +3925,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
headerlen = Curl_dyn_len(&data->state.headerb); headerlen = Curl_dyn_len(&data->state.headerb);
result = Curl_client_write(conn, writetype, result = Curl_client_write(data, writetype,
Curl_dyn_ptr(&data->state.headerb), Curl_dyn_ptr(&data->state.headerb),
headerlen); headerlen);
if(result) if(result)
@ -3936,7 +3938,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* When all the headers have been parsed, see if we should give * When all the headers have been parsed, see if we should give
* up and return an error. * up and return an error.
*/ */
if(http_should_fail(conn)) { if(http_should_fail(data)) {
failf(data, "The requested URL returned error: %d", failf(data, "The requested URL returned error: %d",
k->httpcode); k->httpcode);
return CURLE_HTTP_RETURNED_ERROR; return CURLE_HTTP_RETURNED_ERROR;
@ -3948,7 +3950,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* Curl_http_auth_act() checks what authentication methods /* Curl_http_auth_act() checks what authentication methods
* that are available and decides which one (if any) to * that are available and decides which one (if any) to
* use. It will set 'newurl' if an auth method was picked. */ * use. It will set 'newurl' if an auth method was picked. */
result = Curl_http_auth_act(conn); result = Curl_http_auth_act(data);
if(result) if(result)
return result; return result;
@ -3986,8 +3988,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
infof(data, "Got 417 while waiting for a 100\n"); infof(data, "Got 417 while waiting for a 100\n");
data->state.disableexpect = TRUE; data->state.disableexpect = TRUE;
DEBUGASSERT(!data->req.newurl); DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(conn->data->change.url); data->req.newurl = strdup(data->change.url);
Curl_done_sending(conn, k); Curl_done_sending(data, k);
} }
else if(data->set.http_keep_sending_on_error) { else if(data->set.http_keep_sending_on_error) {
infof(data, "HTTP error before end of send, keep sending\n"); infof(data, "HTTP error before end of send, keep sending\n");
@ -3999,7 +4001,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
else { else {
infof(data, "HTTP error before end of send, stop sending\n"); infof(data, "HTTP error before end of send, stop sending\n");
streamclose(conn, "Stop sending data before everything sent"); streamclose(conn, "Stop sending data before everything sent");
result = Curl_done_sending(conn, k); result = Curl_done_sending(data, k);
if(result) if(result)
return result; return result;
k->upload_done = TRUE; k->upload_done = TRUE;
@ -4237,7 +4239,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
Curl_debug(data, CURLINFO_HEADER_IN, headp, Curl_debug(data, CURLINFO_HEADER_IN, headp,
Curl_dyn_len(&data->state.headerb)); Curl_dyn_len(&data->state.headerb));
result = Curl_client_write(conn, writetype, headp, result = Curl_client_write(data, writetype, headp,
Curl_dyn_len(&data->state.headerb)); Curl_dyn_len(&data->state.headerb));
if(result) if(result)
return result; return result;

View file

@ -51,11 +51,12 @@ bool Curl_compareheader(const char *headerline, /* line to check */
char *Curl_copy_header_value(const char *header); char *Curl_copy_header_value(const char *header);
char *Curl_checkProxyheaders(const struct connectdata *conn, char *Curl_checkProxyheaders(struct Curl_easy *data,
const struct connectdata *conn,
const char *thisheader); const char *thisheader);
#ifndef USE_HYPER #ifndef USE_HYPER
CURLcode Curl_buffer_send(struct dynbuf *in, CURLcode Curl_buffer_send(struct dynbuf *in,
struct connectdata *conn, struct Curl_easy *data,
curl_off_t *bytes_written, curl_off_t *bytes_written,
size_t included_body_bytes, size_t included_body_bytes,
int socketindex); int socketindex);
@ -63,14 +64,14 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
#define Curl_buffer_send(a,b,c,d,e) CURLE_OK #define Curl_buffer_send(a,b,c,d,e) CURLE_OK
#endif #endif
CURLcode Curl_add_timecondition(const struct connectdata *conn, CURLcode Curl_add_timecondition(struct Curl_easy *data,
#ifndef USE_HYPER #ifndef USE_HYPER
struct dynbuf *req struct dynbuf *req
#else #else
void *headers void *headers
#endif #endif
); );
CURLcode Curl_add_custom_headers(struct connectdata *conn, CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect, bool is_connect,
#ifndef USE_HYPER #ifndef USE_HYPER
struct dynbuf *req struct dynbuf *req
@ -84,7 +85,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
const char **method, Curl_HttpReq *); const char **method, Curl_HttpReq *);
CURLcode Curl_http_useragent(struct Curl_easy *data, struct connectdata *conn); CURLcode Curl_http_useragent(struct Curl_easy *data);
CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn); CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn, CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn,
struct dynbuf *req); struct dynbuf *req);
@ -108,21 +109,20 @@ CURLcode Curl_http_resume(struct Curl_easy *data,
struct connectdata *conn, struct connectdata *conn,
Curl_HttpReq httpreq); Curl_HttpReq httpreq);
CURLcode Curl_http_range(struct Curl_easy *data, CURLcode Curl_http_range(struct Curl_easy *data,
struct connectdata *conn,
Curl_HttpReq httpreq); Curl_HttpReq httpreq);
CURLcode Curl_http_firstwrite(struct Curl_easy *data, CURLcode Curl_http_firstwrite(struct Curl_easy *data,
struct connectdata *conn, struct connectdata *conn,
bool *done); bool *done);
/* protocol-specific functions set up to be called by the main engine */ /* protocol-specific functions set up to be called by the main engine */
CURLcode Curl_http(struct connectdata *conn, bool *done); CURLcode Curl_http(struct Curl_easy *data, bool *done);
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
CURLcode Curl_http_connect(struct connectdata *conn, bool *done); CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);
/* These functions are in http.c */ /* These functions are in http.c */
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth); const char *auth);
CURLcode Curl_http_auth_act(struct connectdata *conn); CURLcode Curl_http_auth_act(struct Curl_easy *data);
/* If only the PICKNONE bit is set, there has been a round-trip and we /* If only the PICKNONE bit is set, there has been a round-trip and we
selected to use no auth at all. Ie, we actively select no auth, as opposed selected to use no auth at all. Ie, we actively select no auth, as opposed
@ -301,7 +301,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* @returns CURLcode * @returns CURLcode
*/ */
CURLcode CURLcode
Curl_http_output_auth(struct connectdata *conn, Curl_http_output_auth(struct Curl_easy *data,
struct connectdata *conn,
const char *request, const char *request,
Curl_HttpReq httpreq, Curl_HttpReq httpreq,
const char *path, const char *path,

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -65,12 +65,13 @@
#endif #endif
static ssize_t http2_recv(struct connectdata *conn, int sockindex, static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err); char *mem, size_t len, CURLcode *err);
static bool http2_connisdead(struct connectdata *conn); static bool http2_connisdead(struct Curl_easy *data,
struct connectdata *conn);
static int h2_session_send(struct Curl_easy *data, static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2); nghttp2_session *h2);
static int h2_process_pending_input(struct connectdata *conn, static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc, struct http_conn *httpc,
CURLcode *err); CURLcode *err);
@ -92,11 +93,12 @@ void Curl_http2_init_userset(struct UserDefined *set)
set->stream_weight = NGHTTP2_DEFAULT_WEIGHT; set->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
} }
static int http2_perform_getsock(const struct connectdata *conn, static int http2_getsock(struct Curl_easy *data,
curl_socket_t *sock) struct connectdata *conn,
curl_socket_t *sock)
{ {
const struct http_conn *c = &conn->proto.httpc; const struct http_conn *c = &conn->proto.httpc;
struct SingleRequest *k = &conn->data->req; struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK; int bitmap = GETSOCK_BLANK;
sock[0] = conn->sock[FIRSTSOCKET]; sock[0] = conn->sock[FIRSTSOCKET];
@ -114,12 +116,6 @@ static int http2_perform_getsock(const struct connectdata *conn,
return bitmap; return bitmap;
} }
static int http2_getsock(struct connectdata *conn,
curl_socket_t *socks)
{
return http2_perform_getsock(conn, socks);
}
/* /*
* http2_stream_free() free HTTP2 stream related data * http2_stream_free() free HTTP2 stream related data
*/ */
@ -140,18 +136,22 @@ static void http2_stream_free(struct HTTP *http)
* connection cache and not the "main" one. Don't touch the easy handle! * connection cache and not the "main" one. Don't touch the easy handle!
*/ */
static CURLcode http2_disconnect(struct connectdata *conn, static CURLcode http2_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection) bool dead_connection)
{ {
struct http_conn *c = &conn->proto.httpc; struct http_conn *c = &conn->proto.httpc;
(void)dead_connection; (void)dead_connection;
#ifndef DEBUG_HTTP2
(void)data;
#endif
H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2); nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf); Curl_safefree(c->inbuf);
H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n"));
return CURLE_OK; return CURLE_OK;
} }
@ -163,7 +163,7 @@ static CURLcode http2_disconnect(struct connectdata *conn,
* Instead, if it is readable, run Curl_connalive() to peek at the socket * Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data. * and distinguish between closed and data.
*/ */
static bool http2_connisdead(struct connectdata *conn) static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
{ {
int sval; int sval;
bool dead = TRUE; bool dead = TRUE;
@ -193,14 +193,14 @@ static bool http2_connisdead(struct connectdata *conn)
if(httpc->recv_underlying) if(httpc->recv_underlying)
/* if called "too early", this pointer isn't setup yet! */ /* if called "too early", this pointer isn't setup yet! */
nread = ((Curl_recv *)httpc->recv_underlying)( nread = ((Curl_recv *)httpc->recv_underlying)(
conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
if(nread != -1) { if(nread != -1) {
infof(conn->data, infof(data,
"%d bytes stray data read before trying h2 connection\n", "%d bytes stray data read before trying h2 connection\n",
(int)nread); (int)nread);
httpc->nread_inbuf = 0; httpc->nread_inbuf = 0;
httpc->inbuflen = nread; httpc->inbuflen = nread;
(void)h2_process_pending_input(conn, httpc, &result); (void)h2_process_pending_input(data, httpc, &result);
} }
else else
/* the read failed so let's say this is dead anyway */ /* the read failed so let's say this is dead anyway */
@ -211,24 +211,25 @@ static bool http2_connisdead(struct connectdata *conn)
return dead; return dead;
} }
static unsigned int http2_conncheck(struct connectdata *check, static unsigned int http2_conncheck(struct Curl_easy *data,
struct connectdata *conn,
unsigned int checks_to_perform) unsigned int checks_to_perform)
{ {
unsigned int ret_val = CONNRESULT_NONE; unsigned int ret_val = CONNRESULT_NONE;
struct http_conn *c = &check->proto.httpc; struct http_conn *c = &conn->proto.httpc;
int rc; int rc;
bool send_frames = false; bool send_frames = false;
if(checks_to_perform & CONNCHECK_ISDEAD) { if(checks_to_perform & CONNCHECK_ISDEAD) {
if(http2_connisdead(check)) if(http2_connisdead(data, conn))
ret_val |= CONNRESULT_DEAD; ret_val |= CONNRESULT_DEAD;
} }
if(checks_to_perform & CONNCHECK_KEEPALIVE) { if(checks_to_perform & CONNCHECK_KEEPALIVE) {
struct curltime now = Curl_now(); struct curltime now = Curl_now();
timediff_t elapsed = Curl_timediff(now, check->keepalive); timediff_t elapsed = Curl_timediff(now, conn->keepalive);
if(elapsed > check->upkeep_interval_ms) { if(elapsed > conn->upkeep_interval_ms) {
/* Perform an HTTP/2 PING */ /* Perform an HTTP/2 PING */
rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL); rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
if(!rc) { if(!rc) {
@ -237,18 +238,18 @@ static unsigned int http2_conncheck(struct connectdata *check,
send_frames = true; send_frames = true;
} }
else { else {
failf(check->data, "nghttp2_submit_ping() failed: %s(%d)", failf(data, "nghttp2_submit_ping() failed: %s(%d)",
nghttp2_strerror(rc), rc); nghttp2_strerror(rc), rc);
} }
check->keepalive = now; conn->keepalive = now;
} }
} }
if(send_frames) { if(send_frames) {
rc = nghttp2_session_send(c->h2); rc = nghttp2_session_send(c->h2);
if(rc) if(rc)
failf(check->data, "nghttp2_session_send() failed: %s(%d)", failf(data, "nghttp2_session_send() failed: %s(%d)",
nghttp2_strerror(rc), rc); nghttp2_strerror(rc), rc);
} }
@ -295,7 +296,7 @@ static const struct Curl_handler Curl_handler_http2 = {
http2_getsock, /* proto_getsock */ http2_getsock, /* proto_getsock */
http2_getsock, /* doing_getsock */ http2_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
http2_perform_getsock, /* perform_getsock */ http2_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */ http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */ http2_conncheck, /* connection_check */
@ -317,7 +318,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
http2_getsock, /* proto_getsock */ http2_getsock, /* proto_getsock */
http2_getsock, /* doing_getsock */ http2_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
http2_perform_getsock, /* perform_getsock */ http2_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */ http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */ http2_conncheck, /* connection_check */
@ -343,7 +344,7 @@ int Curl_http2_ver(char *p, size_t len)
* written. See the documentation of nghttp2_send_callback for the details. * written. See the documentation of nghttp2_send_callback for the details.
*/ */
static ssize_t send_callback(nghttp2_session *h2, static ssize_t send_callback(nghttp2_session *h2,
const uint8_t *data, size_t length, int flags, const uint8_t *mem, size_t length, int flags,
void *userp) void *userp)
{ {
struct connectdata *conn = (struct connectdata *)userp; struct connectdata *conn = (struct connectdata *)userp;
@ -358,8 +359,8 @@ static ssize_t send_callback(nghttp2_session *h2,
/* called before setup properly! */ /* called before setup properly! */
return NGHTTP2_ERR_CALLBACK_FAILURE; return NGHTTP2_ERR_CALLBACK_FAILURE;
written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET, written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET,
data, length, &result); mem, length, &result);
if(result == CURLE_AGAIN) { if(result == CURLE_AGAIN) {
return NGHTTP2_ERR_WOULDBLOCK; return NGHTTP2_ERR_WOULDBLOCK;
@ -1215,7 +1216,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
/* /*
* Initialize nghttp2 for a Curl connection * Initialize nghttp2 for a Curl connection
*/ */
static CURLcode http2_init(struct connectdata *conn) static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
{ {
if(!conn->proto.httpc.h2) { if(!conn->proto.httpc.h2) {
int rc; int rc;
@ -1228,7 +1229,7 @@ static CURLcode http2_init(struct connectdata *conn)
rc = nghttp2_session_callbacks_new(&callbacks); rc = nghttp2_session_callbacks_new(&callbacks);
if(rc) { if(rc) {
failf(conn->data, "Couldn't initialize nghttp2 callbacks!"); failf(data, "Couldn't initialize nghttp2 callbacks!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */ return CURLE_OUT_OF_MEMORY; /* most likely at least */
} }
@ -1257,7 +1258,7 @@ static CURLcode http2_init(struct connectdata *conn)
nghttp2_session_callbacks_del(callbacks); nghttp2_session_callbacks_del(callbacks);
if(rc) { if(rc) {
failf(conn->data, "Couldn't initialize nghttp2!"); failf(data, "Couldn't initialize nghttp2!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */ return CURLE_OUT_OF_MEMORY; /* most likely at least */
} }
} }
@ -1274,7 +1275,8 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
ssize_t binlen; ssize_t binlen;
char *base64; char *base64;
size_t blen; size_t blen;
struct SingleRequest *k = &conn->data->req; struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
uint8_t *binsettings = conn->proto.httpc.binsettings; uint8_t *binsettings = conn->proto.httpc.binsettings;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
@ -1285,13 +1287,13 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
httpc->local_settings, httpc->local_settings,
httpc->local_settings_num); httpc->local_settings_num);
if(binlen <= 0) { if(binlen <= 0) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
Curl_dyn_free(req); Curl_dyn_free(req);
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
} }
conn->proto.httpc.binlen = binlen; conn->proto.httpc.binlen = binlen;
result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen, result = Curl_base64url_encode(data, (const char *)binsettings, binlen,
&base64, &blen); &base64, &blen);
if(result) { if(result) {
Curl_dyn_free(req); Curl_dyn_free(req);
@ -1325,14 +1327,13 @@ static int should_close_session(struct http_conn *httpc)
* This function returns 0 if it succeeds, or -1 and error code will * This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err. * be assigned to *err.
*/ */
static int h2_process_pending_input(struct connectdata *conn, static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc, struct http_conn *httpc,
CURLcode *err) CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
char *inbuf; char *inbuf;
ssize_t rv; ssize_t rv;
struct Curl_easy *data = conn->data;
nread = httpc->inbuflen - httpc->nread_inbuf; nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf; inbuf = httpc->inbuf + httpc->nread_inbuf;
@ -1372,7 +1373,7 @@ static int h2_process_pending_input(struct connectdata *conn,
the connection may not be reused. This is set when a the connection may not be reused. This is set when a
GOAWAY frame has been received or when the limit of stream GOAWAY frame has been received or when the limit of stream
identifiers has been reached. */ identifiers has been reached. */
connclose(conn, "http/2: No new requests allowed"); connclose(data->conn, "http/2: No new requests allowed");
} }
if(should_close_session(httpc)) { if(should_close_session(httpc)) {
@ -1382,7 +1383,7 @@ static int h2_process_pending_input(struct connectdata *conn,
*err = CURLE_HTTP2; *err = CURLE_HTTP2;
else { else {
/* not an error per se, but should still close the connection */ /* not an error per se, but should still close the connection */
connclose(conn, "GOAWAY received"); connclose(data->conn, "GOAWAY received");
*err = CURLE_OK; *err = CURLE_OK;
} }
return -1; return -1;
@ -1393,7 +1394,8 @@ static int h2_process_pending_input(struct connectdata *conn,
/* /*
* Called from transfer.c:done_sending when we stop uploading. * Called from transfer.c:done_sending when we stop uploading.
*/ */
CURLcode Curl_http2_done_sending(struct connectdata *conn) CURLcode Curl_http2_done_sending(struct Curl_easy *data,
struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1401,7 +1403,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
(conn->handler == &Curl_handler_http2)) { (conn->handler == &Curl_handler_http2)) {
/* make sure this is only attempted for HTTP/2 transfers */ /* make sure this is only attempted for HTTP/2 transfers */
struct HTTP *stream = conn->data->req.p.http; struct HTTP *stream = data->req.p.http;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
nghttp2_session *h2 = httpc->h2; nghttp2_session *h2 = httpc->h2;
@ -1414,13 +1416,11 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
/* resume sending here to trigger the callback to get called again so /* resume sending here to trigger the callback to get called again so
that it can signal EOF to nghttp2 */ that it can signal EOF to nghttp2 */
(void)nghttp2_session_resume_data(h2, stream->stream_id); (void)nghttp2_session_resume_data(h2, stream->stream_id);
(void)h2_process_pending_input(data, httpc, &result);
(void)h2_process_pending_input(conn, httpc, &result);
} }
/* If nghttp2 still has pending frames unsent */ /* If nghttp2 still has pending frames unsent */
if(nghttp2_session_want_write(h2)) { if(nghttp2_session_want_write(h2)) {
struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
int rv; int rv;
@ -1451,7 +1451,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
drained_transfer(data, httpc); drained_transfer(data, httpc);
if(httpc->pause_stream_id == 0) { if(httpc->pause_stream_id == 0) {
if(h2_process_pending_input(conn, httpc, err) != 0) { if(h2_process_pending_input(data, httpc, err) != 0) {
return -1; return -1;
} }
} }
@ -1499,7 +1499,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
Curl_debug(data, CURLINFO_HEADER_IN, trailp, len); Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
/* pass the trailers one by one to the callback */ /* pass the trailers one by one to the callback */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len); result = Curl_client_write(data, CLIENTWRITE_HEADER, trailp, len);
if(result) { if(result) {
*err = result; *err = result;
return -1; return -1;
@ -1563,12 +1563,12 @@ static int h2_session_send(struct Curl_easy *data,
return nghttp2_session_send(h2); return nghttp2_session_send(h2);
} }
static ssize_t http2_recv(struct connectdata *conn, int sockindex, static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err) char *mem, size_t len, CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
struct Curl_easy *data = conn->data;
struct HTTP *stream = data->req.p.http; struct HTTP *stream = data->req.p.http;
(void)sockindex; /* we always do HTTP2 on sockindex 0 */ (void)sockindex; /* we always do HTTP2 on sockindex 0 */
@ -1632,7 +1632,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
/* We have paused nghttp2, but we have no pause data (see /* We have paused nghttp2, but we have no pause data (see
on_data_chunk_recv). */ on_data_chunk_recv). */
httpc->pause_stream_id = 0; httpc->pause_stream_id = 0;
if(h2_process_pending_input(conn, httpc, err) != 0) { if(h2_process_pending_input(data, httpc, err) != 0) {
return -1; return -1;
} }
} }
@ -1660,7 +1660,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
frames, then we have to call it again with 0-length data. frames, then we have to call it again with 0-length data.
Without this, on_stream_close callback will not be called, Without this, on_stream_close callback will not be called,
and stream could be hanged. */ and stream could be hanged. */
if(h2_process_pending_input(conn, httpc, err) != 0) { if(h2_process_pending_input(data, httpc, err) != 0) {
return -1; return -1;
} }
} }
@ -1694,7 +1694,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
if(httpc->inbuflen == 0) { if(httpc->inbuflen == 0) {
nread = ((Curl_recv *)httpc->recv_underlying)( nread = ((Curl_recv *)httpc->recv_underlying)(
conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err); data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err);
if(nread == -1) { if(nread == -1) {
if(*err != CURLE_AGAIN) if(*err != CURLE_AGAIN)
@ -1725,7 +1725,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
nread)); nread));
} }
if(h2_process_pending_input(conn, httpc, err) != 0) if(h2_process_pending_input(data, httpc, err) != 0)
return -1; return -1;
} }
if(stream->memlen) { if(stream->memlen) {
@ -1831,7 +1831,7 @@ static header_instruction inspect_header(const char *name, size_t namelen,
} }
} }
static ssize_t http2_send(struct connectdata *conn, int sockindex, static ssize_t http2_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err) const void *mem, size_t len, CURLcode *err)
{ {
/* /*
@ -1840,8 +1840,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
* request. * request.
*/ */
int rv; int rv;
struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.p.http; struct HTTP *stream = data->req.p.http;
nghttp2_nv *nva = NULL; nghttp2_nv *nva = NULL;
size_t nheader; size_t nheader;
size_t i; size_t i;
@ -1855,16 +1856,16 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
(void)sockindex; (void)sockindex;
H2BUGF(infof(conn->data, "http2_send len=%zu\n", len)); H2BUGF(infof(data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) { if(stream->stream_id != -1) {
if(stream->close_handled) { if(stream->close_handled) {
infof(conn->data, "stream %d closed\n", stream->stream_id); infof(data, "stream %d closed\n", stream->stream_id);
*err = CURLE_HTTP2_STREAM; *err = CURLE_HTTP2_STREAM;
return -1; return -1;
} }
else if(stream->closed) { else if(stream->closed) {
return http2_handle_stream_close(conn, conn->data, stream, err); return http2_handle_stream_close(conn, data, stream, err);
} }
/* If stream_id != -1, we have dispatched request HEADERS, and now /* If stream_id != -1, we have dispatched request HEADERS, and now
are going to send or sending request body in DATA frame */ are going to send or sending request body in DATA frame */
@ -1875,7 +1876,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
return -1; return -1;
} }
rv = h2_session_send(conn->data, h2); rv = h2_session_send(data, h2);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
return -1; return -1;
@ -1888,7 +1889,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
stream->upload_len = 0; stream->upload_len = 0;
if(should_close_session(httpc)) { if(should_close_session(httpc)) {
H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2; *err = CURLE_HTTP2;
return -1; return -1;
} }
@ -1901,7 +1902,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nghttp2_session_resume_data(h2, stream->stream_id); nghttp2_session_resume_data(h2, stream->stream_id);
} }
H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len, H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len,
stream->stream_id)); stream->stream_id));
return len; return len;
} }
@ -1945,7 +1946,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[0].valuelen = (size_t)(end - hdbuf); nva[0].valuelen = (size_t)(end - hdbuf);
nva[0].flags = NGHTTP2_NV_FLAG_NONE; nva[0].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[0])) { if(HEADER_OVERFLOW(nva[0])) {
failf(conn->data, "Failed sending HTTP request: Header overflow"); failf(data, "Failed sending HTTP request: Header overflow");
goto fail; goto fail;
} }
@ -1967,7 +1968,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[1].valuelen = (size_t)(end - hdbuf); nva[1].valuelen = (size_t)(end - hdbuf);
nva[1].flags = NGHTTP2_NV_FLAG_NONE; nva[1].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[1])) { if(HEADER_OVERFLOW(nva[1])) {
failf(conn->data, "Failed sending HTTP request: Header overflow"); failf(data, "Failed sending HTTP request: Header overflow");
goto fail; goto fail;
} }
@ -1980,7 +1981,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[2].valuelen = strlen((char *)nva[2].value); nva[2].valuelen = strlen((char *)nva[2].value);
nva[2].flags = NGHTTP2_NV_FLAG_NONE; nva[2].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[2])) { if(HEADER_OVERFLOW(nva[2])) {
failf(conn->data, "Failed sending HTTP request: Header overflow"); failf(data, "Failed sending HTTP request: Header overflow");
goto fail; goto fail;
} }
@ -2040,7 +2041,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[i].flags = NGHTTP2_NV_FLAG_NONE; nva[i].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[i])) { if(HEADER_OVERFLOW(nva[i])) {
failf(conn->data, "Failed sending HTTP request: Header overflow"); failf(data, "Failed sending HTTP request: Header overflow");
goto fail; goto fail;
} }
++i; ++i;
@ -2064,30 +2065,30 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
for(i = 0; i < nheader; ++i) { for(i = 0; i < nheader; ++i) {
acc += nva[i].namelen + nva[i].valuelen; acc += nva[i].namelen + nva[i].valuelen;
H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n", H2BUGF(infof(data, "h2 header: %.*s:%.*s\n",
nva[i].namelen, nva[i].name, nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value)); nva[i].valuelen, nva[i].value));
} }
if(acc > MAX_ACC) { if(acc > MAX_ACC) {
infof(conn->data, "http2_send: Warning: The cumulative length of all " infof(data, "http2_send: Warning: The cumulative length of all "
"headers exceeds %d bytes and that could cause the " "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC); "stream to be rejected.\n", MAX_ACC);
} }
} }
h2_pri_spec(conn->data, &pri_spec); h2_pri_spec(data, &pri_spec);
H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n", H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n",
nghttp2_session_check_request_allowed(h2), (void *)conn->data)); nghttp2_session_check_request_allowed(h2), (void *)data));
switch(conn->data->state.httpreq) { switch(data->state.httpreq) {
case HTTPREQ_POST: case HTTPREQ_POST:
case HTTPREQ_POST_FORM: case HTTPREQ_POST_FORM:
case HTTPREQ_POST_MIME: case HTTPREQ_POST_MIME:
case HTTPREQ_PUT: case HTTPREQ_PUT:
if(conn->data->state.infilesize != -1) if(data->state.infilesize != -1)
stream->upload_left = conn->data->state.infilesize; stream->upload_left = data->state.infilesize;
else else
/* data sending without specifying the data amount up front */ /* data sending without specifying the data amount up front */
stream->upload_left = -1; /* unknown, but not zero */ stream->upload_left = -1; /* unknown, but not zero */
@ -2095,32 +2096,32 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
data_prd.read_callback = data_source_read_callback; data_prd.read_callback = data_source_read_callback;
data_prd.source.ptr = NULL; data_prd.source.ptr = NULL;
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
&data_prd, conn->data); &data_prd, data);
break; break;
default: default:
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
NULL, conn->data); NULL, data);
} }
Curl_safefree(nva); Curl_safefree(nva);
if(stream_id < 0) { if(stream_id < 0) {
H2BUGF(infof(conn->data, H2BUGF(infof(data,
"http2_send() nghttp2_submit_request error (%s)%d\n", "http2_send() nghttp2_submit_request error (%s)%d\n",
nghttp2_strerror(stream_id), stream_id)); nghttp2_strerror(stream_id), stream_id));
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
return -1; return -1;
} }
infof(conn->data, "Using Stream ID: %x (easy handle %p)\n", infof(data, "Using Stream ID: %x (easy handle %p)\n",
stream_id, (void *)conn->data); stream_id, (void *)data);
stream->stream_id = stream_id; stream->stream_id = stream_id;
/* this does not call h2_session_send() since there can not have been any /* this does not call h2_session_send() since there can not have been any
* priority update since the nghttp2_submit_request() call above */ * priority update since the nghttp2_submit_request() call above */
rv = nghttp2_session_send(h2); rv = nghttp2_session_send(h2);
if(rv != 0) { if(rv != 0) {
H2BUGF(infof(conn->data, H2BUGF(infof(data,
"http2_send() nghttp2_session_send error (%s)%d\n", "http2_send() nghttp2_session_send error (%s)%d\n",
nghttp2_strerror(rv), rv)); nghttp2_strerror(rv), rv));
@ -2129,7 +2130,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
} }
if(should_close_session(httpc)) { if(should_close_session(httpc)) {
H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2; *err = CURLE_HTTP2;
return -1; return -1;
} }
@ -2151,13 +2152,14 @@ fail:
return -1; return -1;
} }
CURLcode Curl_http2_setup(struct connectdata *conn) CURLcode Curl_http2_setup(struct Curl_easy *data,
struct connectdata *conn)
{ {
CURLcode result; CURLcode result;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.p.http; struct HTTP *stream = data->req.p.http;
DEBUGASSERT(conn->data->state.buffer); DEBUGASSERT(data->state.buffer);
stream->stream_id = -1; stream->stream_id = -1;
@ -2173,18 +2175,18 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
else else
conn->handler = &Curl_handler_http2; conn->handler = &Curl_handler_http2;
result = http2_init(conn); result = http2_init(data, conn);
if(result) { if(result) {
Curl_dyn_free(&stream->header_recvbuf); Curl_dyn_free(&stream->header_recvbuf);
return result; return result;
} }
infof(conn->data, "Using HTTP2, server supports multi-use\n"); infof(data, "Using HTTP2, server supports multi-use\n");
stream->upload_left = 0; stream->upload_left = 0;
stream->upload_mem = NULL; stream->upload_mem = NULL;
stream->upload_len = 0; stream->upload_len = 0;
stream->mem = conn->data->state.buffer; stream->mem = data->state.buffer;
stream->len = conn->data->set.buffer_size; stream->len = data->set.buffer_size;
httpc->inbuflen = 0; httpc->inbuflen = 0;
httpc->nread_inbuf = 0; httpc->nread_inbuf = 0;
@ -2196,22 +2198,22 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
conn->httpversion = 20; conn->httpversion = 20;
conn->bundle->multiuse = BUNDLE_MULTIPLEX; conn->bundle->multiuse = BUNDLE_MULTIPLEX;
infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); infof(data, "Connection state changed (HTTP/2 confirmed)\n");
multi_connchanged(conn->data->multi); multi_connchanged(data->multi);
return CURLE_OK; return CURLE_OK;
} }
CURLcode Curl_http2_switched(struct connectdata *conn, CURLcode Curl_http2_switched(struct Curl_easy *data,
const char *mem, size_t nread) const char *mem, size_t nread)
{ {
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
int rv; int rv;
struct Curl_easy *data = conn->data; struct HTTP *stream = data->req.p.http;
struct HTTP *stream = conn->data->req.p.http;
result = Curl_http2_setup(conn); result = Curl_http2_setup(data, conn);
if(result) if(result)
return result; return result;
@ -2220,7 +2222,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
conn->recv[FIRSTSOCKET] = http2_recv; conn->recv[FIRSTSOCKET] = http2_recv;
conn->send[FIRSTSOCKET] = http2_send; conn->send[FIRSTSOCKET] = http2_send;
if(conn->data->req.upgr101 == UPGR101_RECEIVED) { if(data->req.upgr101 == UPGR101_RECEIVED) {
/* stream 1 is opened implicitly on upgrade */ /* stream 1 is opened implicitly on upgrade */
stream->stream_id = 1; stream->stream_id = 1;
/* queue SETTINGS frame (again) */ /* queue SETTINGS frame (again) */
@ -2270,13 +2272,13 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
data into stream->mem, overwriting data already there. */ data into stream->mem, overwriting data already there. */
if(H2_BUFSIZE < nread) { if(H2_BUFSIZE < nread) {
failf(data, "connection buffer size is too small to store data following " failf(data, "connection buffer size is too small to store data following "
"HTTP Upgrade response header: buflen=%d, datalen=%zu", "HTTP Upgrade response header: buflen=%d, datalen=%zu",
H2_BUFSIZE, nread); H2_BUFSIZE, nread);
return CURLE_HTTP2; return CURLE_HTTP2;
} }
infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer" infof(data, "Copying HTTP/2 data in stream buffer to connection buffer"
" after upgrade: len=%zu\n", " after upgrade: len=%zu\n",
nread); nread);
if(nread) if(nread)
@ -2286,7 +2288,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
DEBUGASSERT(httpc->nread_inbuf == 0); DEBUGASSERT(httpc->nread_inbuf == 0);
if(-1 == h2_process_pending_input(conn, httpc, &result)) if(-1 == h2_process_pending_input(data, httpc, &result))
return CURLE_HTTP2; return CURLE_HTTP2;
return CURLE_OK; return CURLE_OK;

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -44,14 +44,15 @@ void Curl_http2_init_state(struct UrlState *state);
void Curl_http2_init_userset(struct UserDefined *set); void Curl_http2_init_userset(struct UserDefined *set);
CURLcode Curl_http2_request_upgrade(struct dynbuf *req, CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct connectdata *conn); struct connectdata *conn);
CURLcode Curl_http2_setup(struct connectdata *conn); CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_http2_switched(struct connectdata *conn, CURLcode Curl_http2_switched(struct Curl_easy *data,
const char *data, size_t nread); const char *ptr, size_t nread);
/* called from http_setup_conn */ /* called from http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn); void Curl_http2_setup_conn(struct connectdata *conn);
void Curl_http2_setup_req(struct Curl_easy *data); void Curl_http2_setup_req(struct Curl_easy *data);
void Curl_http2_done(struct Curl_easy *data, bool premature); void Curl_http2_done(struct Curl_easy *data, bool premature);
CURLcode Curl_http2_done_sending(struct connectdata *conn); CURLcode Curl_http2_done_sending(struct Curl_easy *data,
struct connectdata *conn);
CURLcode Curl_http2_add_child(struct Curl_easy *parent, CURLcode Curl_http2_add_child(struct Curl_easy *parent,
struct Curl_easy *child, struct Curl_easy *child,
bool exclusive); bool exclusive);
@ -64,14 +65,14 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
bool Curl_h2_http_1_1_error(struct connectdata *conn); bool Curl_h2_http_1_1_error(struct connectdata *conn);
#else /* USE_NGHTTP2 */ #else /* USE_NGHTTP2 */
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup_conn(x) Curl_nop_stmt #define Curl_http2_setup_conn(x) Curl_nop_stmt
#define Curl_http2_setup_req(x) #define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x) #define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x) #define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y) #define Curl_http2_done(x,y)
#define Curl_http2_done_sending(x) #define Curl_http2_done_sending(x,y)
#define Curl_http2_add_child(x, y, z) #define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y) #define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x) #define Curl_http2_cleanup_dependencies(x)

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -96,7 +96,7 @@ CURLcode Curl_output_aws_sigv4(struct connectdata *conn, bool proxy)
char date_str[64]; char date_str[64];
const char *post_data = data->set.postfields ? const char *post_data = data->set.postfields ?
data->set.postfields : ""; data->set.postfields : "";
const char *content_type = Curl_checkheaders(conn, "Content-Type"); const char *content_type = Curl_checkheaders(data, "Content-Type");
unsigned char sha_d[32]; unsigned char sha_d[32];
char sha_hex[65]; char sha_hex[65];
char *cred_scope = NULL; char *cred_scope = NULL;
@ -116,7 +116,7 @@ CURLcode Curl_output_aws_sigv4(struct connectdata *conn, bool proxy)
DEBUGASSERT(!proxy); DEBUGASSERT(!proxy);
(void)proxy; (void)proxy;
if(Curl_checkheaders(conn, "Authorization")) { if(Curl_checkheaders(data, "Authorization")) {
/* Authorization already present, Bailing out */ /* Authorization already present, Bailing out */
return CURLE_OK; return CURLE_OK;
} }

View file

@ -126,7 +126,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* the original data is written to the client, but we go on with the /* the original data is written to the client, but we go on with the
chunk read process, to properly calculate the content length*/ chunk read process, to properly calculate the content length*/
if(data->set.http_te_skip && !k->ignorebody) { if(data->set.http_te_skip && !k->ignorebody) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
if(result) { if(result) {
*extrap = result; *extrap = result;
return CHUNKE_PASSTHRU_ERROR; return CHUNKE_PASSTHRU_ERROR;
@ -198,7 +198,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
if(!conn->data->set.http_ce_skip && k->writer_stack) if(!conn->data->set.http_ce_skip && k->writer_stack)
result = Curl_unencode_write(conn, k->writer_stack, datap, piece); result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
else else
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece); result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
if(result) { if(result) {
*extrap = result; *extrap = result;
@ -249,7 +249,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
return CHUNKE_BAD_CHUNK; return CHUNKE_BAD_CHUNK;
if(!data->set.http_te_skip) { if(!data->set.http_te_skip) {
result = Curl_client_write(conn, CLIENTWRITE_HEADER, tr, trlen); result = Curl_client_write(data, CLIENTWRITE_HEADER, tr, trlen);
if(result) { if(result) {
*extrap = result; *extrap = result;
return CHUNKE_PASSTHRU_ERROR; return CHUNKE_PASSTHRU_ERROR;

View file

@ -184,7 +184,8 @@ static void connect_done(struct connectdata *conn)
infof(conn->data, "CONNECT phase completed!\n"); infof(conn->data, "CONNECT phase completed!\n");
} }
static CURLcode CONNECT_host(struct connectdata *conn, static CURLcode CONNECT_host(struct Curl_easy *data,
struct connectdata *conn,
const char *hostname, const char *hostname,
int remote_port, int remote_port,
char **connecthostp, char **connecthostp,
@ -203,7 +204,7 @@ static CURLcode CONNECT_host(struct connectdata *conn,
if(!hostheader) if(!hostheader)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
if(!Curl_checkProxyheaders(conn, "Host")) { if(!Curl_checkProxyheaders(data, conn, "Host")) {
host = aprintf("Host: %s\r\n", hostheader); host = aprintf("Host: %s\r\n", hostheader);
if(!host) { if(!host) {
free(hostheader); free(hostheader);
@ -258,12 +259,13 @@ static CURLcode CONNECT(struct connectdata *conn,
/* initialize a dynamic send-buffer */ /* initialize a dynamic send-buffer */
Curl_dyn_init(&req, DYN_HTTP_REQUEST); Curl_dyn_init(&req, DYN_HTTP_REQUEST);
result = CONNECT_host(conn, hostname, remote_port, &hostheader, &host); result = CONNECT_host(data, conn,
hostname, remote_port, &hostheader, &host);
if(result) if(result)
return result; return result;
/* Setup the proxy-authorization header, if any */ /* Setup the proxy-authorization header, if any */
result = Curl_http_output_auth(conn, "CONNECT", HTTPREQ_GET, result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
hostheader, TRUE); hostheader, TRUE);
if(!result) { if(!result) {
@ -272,10 +274,10 @@ static CURLcode CONNECT(struct connectdata *conn,
const char *httpv = const char *httpv =
(conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1"; (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
if(!Curl_checkProxyheaders(conn, "Proxy-Connection")) if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n"; proxyconn = "Proxy-Connection: Keep-Alive\r\n";
if(!Curl_checkProxyheaders(conn, "User-Agent") && if(!Curl_checkProxyheaders(data, conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) data->set.str[STRING_USERAGENT])
useragent = data->state.aptr.uagent; useragent = data->state.aptr.uagent;
@ -295,7 +297,7 @@ static CURLcode CONNECT(struct connectdata *conn,
proxyconn); proxyconn);
if(!result) if(!result)
result = Curl_add_custom_headers(conn, TRUE, &req); result = Curl_add_custom_headers(data, TRUE, &req);
if(!result) if(!result)
/* CRLF terminate the request */ /* CRLF terminate the request */
@ -304,7 +306,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!result) { if(!result) {
/* Send the connect request to the proxy */ /* Send the connect request to the proxy */
/* BLOCKING */ /* BLOCKING */
result = Curl_buffer_send(&req, conn, &data->info.request_size, 0, result = Curl_buffer_send(&req, data, &data->info.request_size, 0,
sockindex); sockindex);
} }
if(result) if(result)
@ -340,7 +342,7 @@ static CURLcode CONNECT(struct connectdata *conn,
/* Read one byte at a time to avoid a race condition. Wait at most one /* Read one byte at a time to avoid a race condition. Wait at most one
second before looping to ensure continuous pgrsUpdates. */ second before looping to ensure continuous pgrsUpdates. */
result = Curl_read(conn, tunnelsocket, &byte, 1, &gotbytes); result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
if(result == CURLE_AGAIN) if(result == CURLE_AGAIN)
/* socket buffer drained, return */ /* socket buffer drained, return */
return CURLE_OK; return CURLE_OK;
@ -428,7 +430,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(data->set.include_header) if(data->set.include_header)
writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
result = Curl_client_write(conn, writetype, linep, perline); result = Curl_client_write(data, writetype, linep, perline);
if(result) if(result)
return result; return result;
} }
@ -508,7 +510,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!auth) if(!auth)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
result = Curl_http_input_auth(conn, proxy, auth); result = Curl_http_input_auth(data, proxy, auth);
free(auth); free(auth);
@ -567,7 +569,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(data->info.httpproxycode/100 != 2) { if(data->info.httpproxycode/100 != 2) {
/* Deal with the possibly already received authenticate /* Deal with the possibly already received authenticate
headers. 'newurl' is set to a new URL if we must loop. */ headers. 'newurl' is set to a new URL if we must loop. */
result = Curl_http_auth_act(conn); result = Curl_http_auth_act(data);
if(result) if(result)
return result; return result;
@ -580,7 +582,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(s->close_connection && data->req.newurl) { if(s->close_connection && data->req.newurl) {
/* Connection closed by server. Don't use it anymore */ /* Connection closed by server. Don't use it anymore */
Curl_closesocket(conn, conn->sock[sockindex]); Curl_closesocket(data, conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD; conn->sock[sockindex] = CURL_SOCKET_BAD;
break; break;
} }
@ -606,7 +608,7 @@ static CURLcode CONNECT(struct connectdata *conn,
data->req.newurl = NULL; data->req.newurl = NULL;
/* failure, close this connection to avoid re-use */ /* failure, close this connection to avoid re-use */
streamclose(conn, "proxy CONNECT failure"); streamclose(conn, "proxy CONNECT failure");
Curl_closesocket(conn, conn->sock[sockindex]); Curl_closesocket(data, conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD; conn->sock[sockindex] = CURL_SOCKET_BAD;
} }
@ -733,7 +735,8 @@ static CURLcode CONNECT(struct connectdata *conn,
goto error; goto error;
} }
result = CONNECT_host(conn, hostname, remote_port, &hostheader, &host); result = CONNECT_host(data, conn, hostname, remote_port,
&hostheader, &host);
if(result) if(result)
goto error; goto error;
@ -743,7 +746,7 @@ static CURLcode CONNECT(struct connectdata *conn,
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
} }
/* Setup the proxy-authorization header, if any */ /* Setup the proxy-authorization header, if any */
result = Curl_http_output_auth(conn, "CONNECT", HTTPREQ_GET, result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
hostheader, TRUE); hostheader, TRUE);
if(result) if(result)
goto error; goto error;
@ -776,7 +779,7 @@ static CURLcode CONNECT(struct connectdata *conn,
Curl_hyper_header(data, headers, data->state.aptr.uagent)) Curl_hyper_header(data, headers, data->state.aptr.uagent))
goto error; goto error;
if(!Curl_checkProxyheaders(conn, "Proxy-Connection") && if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection") &&
Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive")) Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
goto error; goto error;

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
* *
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden). * (Royal Institute of Technology, Stockholm, Sweden).
* Copyright (c) 2004 - 2020 Daniel Stenberg * Copyright (c) 2004 - 2021 Daniel Stenberg
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -89,7 +89,7 @@ static CURLcode ftpsend(struct connectdata *conn, const char *cmd)
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD; conn->data_prot = PROT_CMD;
#endif #endif
result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, result = Curl_write(conn->data, conn->sock[FIRSTSOCKET], sptr, write_len,
&bytes_written); &bytes_written);
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
@ -246,7 +246,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
if(result) if(result)
return -2; return -2;
if(Curl_GetFTPResponse(&nread, conn, NULL)) if(Curl_GetFTPResponse(data, &nread, NULL))
return -1; return -1;
if(data->state.buffer[0] != '3') if(data->state.buffer[0] != '3')
@ -331,7 +331,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
break; break;
} }
if(Curl_GetFTPResponse(&nread, conn, NULL)) { if(Curl_GetFTPResponse(data, &nread, NULL)) {
ret = -1; ret = -1;
break; break;
} }
@ -443,7 +443,7 @@ static char level_to_char(int level)
/* Send an FTP command defined by |message| and the optional arguments. The /* Send an FTP command defined by |message| and the optional arguments. The
function returns the ftp_code. If an error occurs, -1 is returned. */ function returns the ftp_code. If an error occurs, -1 is returned. */
static int ftp_send_command(struct connectdata *conn, const char *message, ...) static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
{ {
int ftp_code; int ftp_code;
ssize_t nread = 0; ssize_t nread = 0;
@ -454,11 +454,11 @@ static int ftp_send_command(struct connectdata *conn, const char *message, ...)
mvsnprintf(print_buffer, sizeof(print_buffer), message, args); mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
va_end(args); va_end(args);
if(ftpsend(conn, print_buffer)) { if(ftpsend(data->conn, print_buffer)) {
ftp_code = -1; ftp_code = -1;
} }
else { else {
if(Curl_GetFTPResponse(&nread, conn, &ftp_code)) if(Curl_GetFTPResponse(data, &nread, &ftp_code))
ftp_code = -1; ftp_code = -1;
} }
@ -503,7 +503,7 @@ socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
ssize_t written; ssize_t written;
while(len > 0) { while(len > 0) {
result = Curl_write_plain(conn, fd, to_p, len, &written); result = Curl_write_plain(conn->data, fd, to_p, len, &written);
if(!result) { if(!result) {
len -= written; len -= written;
to_p += written; to_p += written;
@ -556,18 +556,19 @@ buffer_read(struct krb5buffer *buf, void *data, size_t len)
} }
/* Matches Curl_recv signature */ /* Matches Curl_recv signature */
static ssize_t sec_recv(struct connectdata *conn, int sockindex, static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
char *buffer, size_t len, CURLcode *err) char *buffer, size_t len, CURLcode *err)
{ {
size_t bytes_read; size_t bytes_read;
size_t total_read = 0; size_t total_read = 0;
struct connectdata *conn = data->conn;
curl_socket_t fd = conn->sock[sockindex]; curl_socket_t fd = conn->sock[sockindex];
*err = CURLE_OK; *err = CURLE_OK;
/* Handle clear text response. */ /* Handle clear text response. */
if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
return sread(fd, buffer, len); return sread(fd, buffer, len);
if(conn->in_buffer.eof_flag) { if(conn->in_buffer.eof_flag) {
conn->in_buffer.eof_flag = 0; conn->in_buffer.eof_flag = 0;
@ -673,9 +674,10 @@ static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd,
} }
/* Matches Curl_send signature */ /* Matches Curl_send signature */
static ssize_t sec_send(struct connectdata *conn, int sockindex, static ssize_t sec_send(struct Curl_easy *data, int sockindex,
const void *buffer, size_t len, CURLcode *err) const void *buffer, size_t len, CURLcode *err)
{ {
struct connectdata *conn = data->conn;
curl_socket_t fd = conn->sock[sockindex]; curl_socket_t fd = conn->sock[sockindex];
*err = CURLE_OK; *err = CURLE_OK;
return sec_write(conn, fd, buffer, len); return sec_write(conn, fd, buffer, len);
@ -736,9 +738,10 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
return ret_code; return ret_code;
} }
static int sec_set_protection_level(struct connectdata *conn) static int sec_set_protection_level(struct Curl_easy *data)
{ {
int code; int code;
struct connectdata *conn = data->conn;
enum protection_level level = conn->request_data_prot; enum protection_level level = conn->request_data_prot;
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
@ -757,7 +760,7 @@ static int sec_set_protection_level(struct connectdata *conn)
char *pbsz; char *pbsz;
static unsigned int buffer_size = 1 << 20; /* 1048576 */ static unsigned int buffer_size = 1 << 20; /* 1048576 */
code = ftp_send_command(conn, "PBSZ %u", buffer_size); code = ftp_send_command(data, "PBSZ %u", buffer_size);
if(code < 0) if(code < 0)
return -1; return -1;
@ -767,7 +770,7 @@ static int sec_set_protection_level(struct connectdata *conn)
} }
conn->buffer_size = buffer_size; conn->buffer_size = buffer_size;
pbsz = strstr(conn->data->state.buffer, "PBSZ="); pbsz = strstr(data->state.buffer, "PBSZ=");
if(pbsz) { if(pbsz) {
/* ignore return code, use default value if it fails */ /* ignore return code, use default value if it fails */
(void)sscanf(pbsz, "PBSZ=%u", &buffer_size); (void)sscanf(pbsz, "PBSZ=%u", &buffer_size);
@ -776,8 +779,8 @@ static int sec_set_protection_level(struct connectdata *conn)
} }
} }
/* Now try to negotiate the protection level. */ /* Now try to negiociate the protection level. */
code = ftp_send_command(conn, "PROT %c", level_to_char(level)); code = ftp_send_command(data, "PROT %c", level_to_char(level));
if(code < 0) if(code < 0)
return -1; return -1;
@ -830,7 +833,7 @@ static CURLcode choose_mech(struct connectdata *conn)
} }
infof(data, "Trying mechanism %s...\n", mech->name); infof(data, "Trying mechanism %s...\n", mech->name);
ret = ftp_send_command(conn, "AUTH %s", mech->name); ret = ftp_send_command(data, "AUTH %s", mech->name);
if(ret < 0) if(ret < 0)
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
@ -873,7 +876,7 @@ static CURLcode choose_mech(struct connectdata *conn)
conn->command_prot = PROT_SAFE; conn->command_prot = PROT_SAFE;
/* Set the requested protection level */ /* Set the requested protection level */
/* BLOCKING */ /* BLOCKING */
(void)sec_set_protection_level(conn); (void)sec_set_protection_level(data);
} }
return CURLE_OK; return CURLE_OK;

View file

@ -126,7 +126,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp);
#endif #endif
static CURLcode ldap_do(struct connectdata *conn, bool *done); static CURLcode ldap_do(struct Curl_easy *data, bool *done);
/* /*
* LDAP protocol handler. * LDAP protocol handler.
@ -266,7 +266,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
#endif #endif
static CURLcode ldap_do(struct connectdata *conn, bool *done) static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
int rc = 0; int rc = 0;
@ -275,7 +275,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
LDAPMessage *ldapmsg = NULL; LDAPMessage *ldapmsg = NULL;
LDAPMessage *entryIterator; LDAPMessage *entryIterator;
int num = 0; int num = 0;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
int ldap_proto = LDAP_VERSION3; int ldap_proto = LDAP_VERSION3;
int ldap_ssl = 0; int ldap_ssl = 0;
char *val_b64 = NULL; char *val_b64 = NULL;
@ -536,14 +536,14 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
#endif #endif
name_len = strlen(name); name_len = strlen(name);
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(result) { if(result) {
FREE_ON_WINLDAP(name); FREE_ON_WINLDAP(name);
ldap_memfree(dn); ldap_memfree(dn);
goto quit; goto quit;
} }
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name, result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) name,
name_len); name_len);
if(result) { if(result) {
FREE_ON_WINLDAP(name); FREE_ON_WINLDAP(name);
@ -551,7 +551,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
goto quit; goto quit;
} }
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) { if(result) {
FREE_ON_WINLDAP(name); FREE_ON_WINLDAP(name);
ldap_memfree(dn); ldap_memfree(dn);
@ -589,7 +589,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
vals = ldap_get_values_len(server, entryIterator, attribute); vals = ldap_get_values_len(server, entryIterator, attribute);
if(vals != NULL) { if(vals != NULL) {
for(i = 0; (vals[i] != NULL); i++) { for(i = 0; (vals[i] != NULL); i++) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
FREE_ON_WINLDAP(attr); FREE_ON_WINLDAP(attr);
@ -600,7 +600,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
goto quit; goto quit;
} }
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *) attr, attr_len); (char *) attr, attr_len);
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
@ -612,7 +612,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
goto quit; goto quit;
} }
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
FREE_ON_WINLDAP(attr); FREE_ON_WINLDAP(attr);
@ -644,7 +644,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
} }
if(val_b64_sz > 0) { if(val_b64_sz > 0) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, result = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
val_b64_sz); val_b64_sz);
free(val_b64); free(val_b64);
if(result) { if(result) {
@ -661,7 +661,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
} }
} }
else { else {
result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val, result = Curl_client_write(data, CLIENTWRITE_BODY, vals[i]->bv_val,
vals[i]->bv_len); vals[i]->bv_len);
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
@ -676,7 +676,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
dlsize += vals[i]->bv_len; dlsize += vals[i]->bv_len;
} }
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
FREE_ON_WINLDAP(attr); FREE_ON_WINLDAP(attr);
@ -698,7 +698,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
FREE_ON_WINLDAP(attr); FREE_ON_WINLDAP(attr);
ldap_memfree(attribute); ldap_memfree(attribute);
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) if(result)
goto quit; goto quit;
dlsize++; dlsize++;

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2019, Björn Stenberg, <bjorn@haxx.se> * Copyright (C) 2019, Björn Stenberg, <bjorn@haxx.se>
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
@ -59,10 +59,12 @@
* Forward declarations. * Forward declarations.
*/ */
static CURLcode mqtt_do(struct connectdata *conn, bool *done); static CURLcode mqtt_do(struct Curl_easy *data, bool *done);
static CURLcode mqtt_doing(struct connectdata *conn, bool *done); static CURLcode mqtt_doing(struct Curl_easy *data, bool *done);
static int mqtt_getsock(struct connectdata *conn, curl_socket_t *sock); static int mqtt_getsock(struct Curl_easy *data, struct connectdata *conn,
static CURLcode mqtt_setup_conn(struct connectdata *conn); curl_socket_t *sock);
static CURLcode mqtt_setup_conn(struct Curl_easy *data,
struct connectdata *conn);
/* /*
* MQTT protocol handler. * MQTT protocol handler.
@ -90,12 +92,13 @@ const struct Curl_handler Curl_handler_mqtt = {
PROTOPT_NONE /* flags */ PROTOPT_NONE /* flags */
}; };
static CURLcode mqtt_setup_conn(struct connectdata *conn) static CURLcode mqtt_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{ {
/* allocate the HTTP-specific struct for the Curl_easy, only to survive /* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */ during this request */
struct MQTT *mq; struct MQTT *mq;
struct Curl_easy *data = conn->data; (void)conn;
DEBUGASSERT(data->req.p.mqtt == NULL); DEBUGASSERT(data->req.p.mqtt == NULL);
mq = calloc(1, sizeof(struct MQTT)); mq = calloc(1, sizeof(struct MQTT));
@ -105,15 +108,15 @@ static CURLcode mqtt_setup_conn(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode mqtt_send(struct connectdata *conn, static CURLcode mqtt_send(struct Curl_easy *data,
char *buf, size_t len) char *buf, size_t len)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
struct Curl_easy *data = conn->data;
struct MQTT *mq = data->req.p.mqtt; struct MQTT *mq = data->req.p.mqtt;
ssize_t n; ssize_t n;
result = Curl_write(conn, sockfd, buf, len, &n); result = Curl_write(data, sockfd, buf, len, &n);
if(!result) if(!result)
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n); Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
if(len != (size_t)n) { if(len != (size_t)n) {
@ -130,14 +133,16 @@ static CURLcode mqtt_send(struct connectdata *conn,
/* Generic function called by the multi interface to figure out what socket(s) /* Generic function called by the multi interface to figure out what socket(s)
to wait for and for what actions during the DOING and PROTOCONNECT to wait for and for what actions during the DOING and PROTOCONNECT
states */ states */
static int mqtt_getsock(struct connectdata *conn, static int mqtt_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *sock) curl_socket_t *sock)
{ {
(void)data;
sock[0] = conn->sock[FIRSTSOCKET]; sock[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(FIRSTSOCKET); return GETSOCK_READSOCK(FIRSTSOCKET);
} }
static CURLcode mqtt_connect(struct connectdata *conn) static CURLcode mqtt_connect(struct Curl_easy *data)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
const size_t client_id_offset = 14; const size_t client_id_offset = 14;
@ -157,31 +162,31 @@ static CURLcode mqtt_connect(struct connectdata *conn)
packet[1] = (packetlen - 2) & 0x7f; packet[1] = (packetlen - 2) & 0x7f;
packet[client_id_offset - 1] = MQTT_CLIENTID_LEN; packet[client_id_offset - 1] = MQTT_CLIENTID_LEN;
result = Curl_rand_hex(conn->data, (unsigned char *)&client_id[clen], result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
MQTT_CLIENTID_LEN - clen + 1); MQTT_CLIENTID_LEN - clen + 1);
memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN); memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN);
infof(conn->data, "Using client id '%s'\n", client_id); infof(data, "Using client id '%s'\n", client_id);
if(!result) if(!result)
result = mqtt_send(conn, packet, packetlen); result = mqtt_send(data, packet, packetlen);
return result; return result;
} }
static CURLcode mqtt_disconnect(struct connectdata *conn) static CURLcode mqtt_disconnect(struct Curl_easy *data)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
result = mqtt_send(conn, (char *)"\xe0\x00", 2); result = mqtt_send(data, (char *)"\xe0\x00", 2);
return result; return result;
} }
static CURLcode mqtt_verify_connack(struct connectdata *conn) static CURLcode mqtt_verify_connack(struct Curl_easy *data)
{ {
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char readbuf[MQTT_CONNACK_LEN]; unsigned char readbuf[MQTT_CONNACK_LEN];
ssize_t nread; ssize_t nread;
struct Curl_easy *data = conn->data;
result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread); result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
if(result) if(result)
goto fail; goto fail;
@ -204,18 +209,18 @@ fail:
return result; return result;
} }
static CURLcode mqtt_get_topic(struct connectdata *conn, static CURLcode mqtt_get_topic(struct Curl_easy *data,
char **topic, size_t *topiclen) char **topic, size_t *topiclen)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
char *path = conn->data->state.up.path; char *path = data->state.up.path;
if(strlen(path) > 1) { if(strlen(path) > 1) {
result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen, result = Curl_urldecode(data, path + 1, 0, topic, topiclen,
REJECT_NADA); REJECT_NADA);
} }
else { else {
failf(conn->data, "Error: No topic specified."); failf(data, "Error: No topic specified.");
result = CURLE_URL_MALFORMAT; result = CURLE_URL_MALFORMAT;
} }
return result; return result;
@ -238,7 +243,7 @@ static int mqtt_encode_len(char *buf, size_t len)
return i; return i;
} }
static CURLcode mqtt_subscribe(struct connectdata *conn) static CURLcode mqtt_subscribe(struct Curl_easy *data)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
char *topic = NULL; char *topic = NULL;
@ -247,8 +252,9 @@ static CURLcode mqtt_subscribe(struct connectdata *conn)
size_t packetlen; size_t packetlen;
char encodedsize[4]; char encodedsize[4];
size_t n; size_t n;
struct connectdata *conn = data->conn;
result = mqtt_get_topic(conn, &topic, &topiclen); result = mqtt_get_topic(data, &topic, &topiclen);
if(result) if(result)
goto fail; goto fail;
@ -274,7 +280,7 @@ static CURLcode mqtt_subscribe(struct connectdata *conn)
memcpy(&packet[5 + n], topic, topiclen); memcpy(&packet[5 + n], topic, topiclen);
packet[5 + n + topiclen] = 0; /* QoS zero */ packet[5 + n + topiclen] = 0; /* QoS zero */
result = mqtt_send(conn, (char *)packet, packetlen); result = mqtt_send(data, (char *)packet, packetlen);
fail: fail:
free(topic); free(topic);
@ -285,19 +291,20 @@ fail:
/* /*
* Called when the first byte was already read. * Called when the first byte was already read.
*/ */
static CURLcode mqtt_verify_suback(struct connectdata *conn) static CURLcode mqtt_verify_suback(struct Curl_easy *data)
{ {
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char readbuf[MQTT_SUBACK_LEN]; unsigned char readbuf[MQTT_SUBACK_LEN];
ssize_t nread; ssize_t nread;
struct mqtt_conn *mqtt = &conn->proto.mqtt; struct mqtt_conn *mqtt = &conn->proto.mqtt;
result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread); result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
if(result) if(result)
goto fail; goto fail;
Curl_debug(conn->data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread); Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
/* fixme */ /* fixme */
if(nread < MQTT_SUBACK_LEN) { if(nread < MQTT_SUBACK_LEN) {
@ -315,10 +322,10 @@ fail:
return result; return result;
} }
static CURLcode mqtt_publish(struct connectdata *conn) static CURLcode mqtt_publish(struct Curl_easy *data)
{ {
CURLcode result; CURLcode result;
char *payload = conn->data->set.postfields; char *payload = data->set.postfields;
size_t payloadlen; size_t payloadlen;
char *topic = NULL; char *topic = NULL;
size_t topiclen; size_t topiclen;
@ -327,7 +334,7 @@ static CURLcode mqtt_publish(struct connectdata *conn)
size_t remaininglength; size_t remaininglength;
size_t encodelen; size_t encodelen;
char encodedbytes[4]; char encodedbytes[4];
curl_off_t postfieldsize = conn->data->set.postfieldsize; curl_off_t postfieldsize = data->set.postfieldsize;
if(!payload) if(!payload)
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
@ -336,7 +343,7 @@ static CURLcode mqtt_publish(struct connectdata *conn)
else else
payloadlen = (size_t)postfieldsize; payloadlen = (size_t)postfieldsize;
result = mqtt_get_topic(conn, &topic, &topiclen); result = mqtt_get_topic(data, &topic, &topiclen);
if(result) if(result)
goto fail; goto fail;
@ -360,7 +367,7 @@ static CURLcode mqtt_publish(struct connectdata *conn)
i += topiclen; i += topiclen;
memcpy(&pkt[i], payload, payloadlen); memcpy(&pkt[i], payload, payloadlen);
i += payloadlen; i += payloadlen;
result = mqtt_send(conn, (char *)pkt, i); result = mqtt_send(data, (char *)pkt, i);
fail: fail:
free(pkt); free(pkt);
@ -403,13 +410,14 @@ static const char *statenames[]={
#endif #endif
/* The only way to change state */ /* The only way to change state */
static void mqstate(struct connectdata *conn, static void mqstate(struct Curl_easy *data,
enum mqttstate state, enum mqttstate state,
enum mqttstate nextstate) /* used if state == FIRST */ enum mqttstate nextstate) /* used if state == FIRST */
{ {
struct connectdata *conn = data->conn;
struct mqtt_conn *mqtt = &conn->proto.mqtt; struct mqtt_conn *mqtt = &conn->proto.mqtt;
#ifdef CURLDEBUG #ifdef CURLDEBUG
infof(conn->data, "%s (from %s) (next is %s)\n", infof(data, "%s (from %s) (next is %s)\n",
statenames[state], statenames[state],
statenames[mqtt->state], statenames[mqtt->state],
(state == MQTT_FIRST)? statenames[nextstate] : ""); (state == MQTT_FIRST)? statenames[nextstate] : "");
@ -423,13 +431,12 @@ static void mqstate(struct connectdata *conn,
/* for the publish packet */ /* for the publish packet */
#define MQTT_HEADER_LEN 5 /* max 5 bytes */ #define MQTT_HEADER_LEN 5 /* max 5 bytes */
static CURLcode mqtt_read_publish(struct connectdata *conn, static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
ssize_t nread; ssize_t nread;
struct Curl_easy *data = conn->data;
unsigned char *pkt = (unsigned char *)data->state.buffer; unsigned char *pkt = (unsigned char *)data->state.buffer;
size_t remlen; size_t remlen;
struct mqtt_conn *mqtt = &conn->proto.mqtt; struct mqtt_conn *mqtt = &conn->proto.mqtt;
@ -439,11 +446,11 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
switch(mqtt->state) { switch(mqtt->state) {
MQTT_SUBACK_COMING: MQTT_SUBACK_COMING:
case MQTT_SUBACK_COMING: case MQTT_SUBACK_COMING:
result = mqtt_verify_suback(conn); result = mqtt_verify_suback(data);
if(result) if(result)
break; break;
mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT); mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
break; break;
case MQTT_SUBACK: case MQTT_SUBACK:
@ -451,9 +458,9 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
/* we are expecting PUBLISH or SUBACK */ /* we are expecting PUBLISH or SUBACK */
packet = mq->firstbyte & 0xf0; packet = mq->firstbyte & 0xf0;
if(packet == MQTT_MSG_PUBLISH) if(packet == MQTT_MSG_PUBLISH)
mqstate(conn, MQTT_PUB_REMAIN, MQTT_NOSTATE); mqstate(data, MQTT_PUB_REMAIN, MQTT_NOSTATE);
else if(packet == MQTT_MSG_SUBACK) { else if(packet == MQTT_MSG_SUBACK) {
mqstate(conn, MQTT_SUBACK_COMING, MQTT_NOSTATE); mqstate(data, MQTT_SUBACK_COMING, MQTT_NOSTATE);
goto MQTT_SUBACK_COMING; goto MQTT_SUBACK_COMING;
} }
else if(packet == MQTT_MSG_DISCONNECT) { else if(packet == MQTT_MSG_DISCONNECT) {
@ -480,7 +487,7 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
size_t rest = mq->npacket; size_t rest = mq->npacket;
if(rest > (size_t)data->set.buffer_size) if(rest > (size_t)data->set.buffer_size)
rest = (size_t)data->set.buffer_size; rest = (size_t)data->set.buffer_size;
result = Curl_read(conn, sockfd, (char *)pkt, rest, &nread); result = Curl_read(data, sockfd, (char *)pkt, rest, &nread);
if(result) { if(result) {
if(CURLE_AGAIN == result) { if(CURLE_AGAIN == result) {
infof(data, "EEEE AAAAGAIN\n"); infof(data, "EEEE AAAAGAIN\n");
@ -500,13 +507,13 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
/* if QoS is set, message contains packet id */ /* if QoS is set, message contains packet id */
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)pkt, nread); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)pkt, nread);
if(result) if(result)
goto end; goto end;
if(!mq->npacket) if(!mq->npacket)
/* no more PUBLISH payload, back to subscribe wait state */ /* no more PUBLISH payload, back to subscribe wait state */
mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT); mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
break; break;
} }
default: default:
@ -518,27 +525,25 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
return result; return result;
} }
static CURLcode mqtt_do(struct connectdata *conn, bool *done) static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
*done = FALSE; /* unconditionally */ *done = FALSE; /* unconditionally */
result = mqtt_connect(conn); result = mqtt_connect(data);
if(result) { if(result) {
failf(data, "Error %d sending MQTT CONN request", result); failf(data, "Error %d sending MQTT CONN request", result);
return result; return result;
} }
mqstate(conn, MQTT_FIRST, MQTT_CONNACK); mqstate(data, MQTT_FIRST, MQTT_CONNACK);
return CURLE_OK; return CURLE_OK;
} }
static CURLcode mqtt_doing(struct connectdata *conn, bool *done) static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct mqtt_conn *mqtt = &conn->proto.mqtt; struct mqtt_conn *mqtt = &conn->proto.mqtt;
struct Curl_easy *data = conn->data;
struct MQTT *mq = data->req.p.mqtt; struct MQTT *mq = data->req.p.mqtt;
ssize_t nread; ssize_t nread;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
@ -550,7 +555,7 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
if(mq->nsend) { if(mq->nsend) {
/* send the remainder of an outgoing packet */ /* send the remainder of an outgoing packet */
char *ptr = mq->sendleftovers; char *ptr = mq->sendleftovers;
result = mqtt_send(conn, mq->sendleftovers, mq->nsend); result = mqtt_send(data, mq->sendleftovers, mq->nsend);
free(ptr); free(ptr);
if(result) if(result)
return result; return result;
@ -560,17 +565,17 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
switch(mqtt->state) { switch(mqtt->state) {
case MQTT_FIRST: case MQTT_FIRST:
/* Read the initial byte only */ /* Read the initial byte only */
result = Curl_read(conn, sockfd, (char *)&mq->firstbyte, 1, &nread); result = Curl_read(data, sockfd, (char *)&mq->firstbyte, 1, &nread);
if(!nread) if(!nread)
break; break;
Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1); Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1);
/* remember the first byte */ /* remember the first byte */
mq->npacket = 0; mq->npacket = 0;
mqstate(conn, MQTT_REMAINING_LENGTH, MQTT_NOSTATE); mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
/* FALLTHROUGH */ /* FALLTHROUGH */
case MQTT_REMAINING_LENGTH: case MQTT_REMAINING_LENGTH:
do { do {
result = Curl_read(conn, sockfd, (char *)&byte, 1, &nread); result = Curl_read(data, sockfd, (char *)&byte, 1, &nread);
if(!nread) if(!nread)
break; break;
Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1); Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
@ -581,10 +586,10 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL); mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
mq->npacket = 0; mq->npacket = 0;
if(mq->remaining_length) { if(mq->remaining_length) {
mqstate(conn, mqtt->nextstate, MQTT_NOSTATE); mqstate(data, mqtt->nextstate, MQTT_NOSTATE);
break; break;
} }
mqstate(conn, MQTT_FIRST, MQTT_FIRST); mqstate(data, MQTT_FIRST, MQTT_FIRST);
if(mq->firstbyte == MQTT_MSG_DISCONNECT) { if(mq->firstbyte == MQTT_MSG_DISCONNECT) {
infof(data, "Got DISCONNECT\n"); infof(data, "Got DISCONNECT\n");
@ -592,22 +597,22 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
} }
break; break;
case MQTT_CONNACK: case MQTT_CONNACK:
result = mqtt_verify_connack(conn); result = mqtt_verify_connack(data);
if(result) if(result)
break; break;
if(conn->data->state.httpreq == HTTPREQ_POST) { if(data->state.httpreq == HTTPREQ_POST) {
result = mqtt_publish(conn); result = mqtt_publish(data);
if(!result) { if(!result) {
result = mqtt_disconnect(conn); result = mqtt_disconnect(data);
*done = TRUE; *done = TRUE;
} }
mqtt->nextstate = MQTT_FIRST; mqtt->nextstate = MQTT_FIRST;
} }
else { else {
result = mqtt_subscribe(conn); result = mqtt_subscribe(data);
if(!result) { if(!result) {
mqstate(conn, MQTT_FIRST, MQTT_SUBACK); mqstate(data, MQTT_FIRST, MQTT_SUBACK);
} }
} }
break; break;
@ -615,11 +620,11 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
case MQTT_SUBACK: case MQTT_SUBACK:
case MQTT_PUBWAIT: case MQTT_PUBWAIT:
case MQTT_PUB_REMAIN: case MQTT_PUB_REMAIN:
result = mqtt_read_publish(conn, done); result = mqtt_read_publish(data, done);
break; break;
default: default:
failf(conn->data, "State not handled yet"); failf(data, "State not handled yet");
*done = TRUE; *done = TRUE;
break; break;
} }

View file

@ -586,7 +586,7 @@ static CURLcode multi_done(struct Curl_easy *data,
/* this calls the protocol-specific function pointer previously set */ /* this calls the protocol-specific function pointer previously set */
if(conn->handler->done) if(conn->handler->done)
result = conn->handler->done(conn, status, premature); result = conn->handler->done(data, status, premature);
else else
result = status; result = status;
@ -697,17 +697,13 @@ static CURLcode multi_done(struct Curl_easy *data,
return result; return result;
} }
static int close_connect_only(struct connectdata *conn, void *param) static int close_connect_only(struct Curl_easy *data,
struct connectdata *conn, void *param)
{ {
struct Curl_easy *data = param; (void)param;
if(data->state.lastconnect_id != conn->connection_id) if(data->state.lastconnect_id != conn->connection_id)
return 0; return 0;
if(conn->data != data)
return 1;
conn->data = NULL;
if(!conn->bits.connect_only) if(!conn->bits.connect_only)
return 1; return 1;
@ -816,7 +812,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
if(data->state.lastconnect_id != -1) { if(data->state.lastconnect_id != -1) {
/* Mark any connect-only connection for closure */ /* Mark any connect-only connection for closure */
Curl_conncache_foreach(data, data->state.conn_cache, Curl_conncache_foreach(data, data->state.conn_cache,
data, &close_connect_only); NULL, close_connect_only);
} }
#ifdef USE_LIBPSL #ifdef USE_LIBPSL
@ -945,27 +941,30 @@ static int waitproxyconnect_getsock(struct connectdata *conn,
return GETSOCK_WRITESOCK(0); return GETSOCK_WRITESOCK(0);
} }
static int domore_getsock(struct connectdata *conn, static int domore_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks) curl_socket_t *socks)
{ {
if(conn && conn->handler->domore_getsock) if(conn && conn->handler->domore_getsock)
return conn->handler->domore_getsock(conn, socks); return conn->handler->domore_getsock(data, conn, socks);
return GETSOCK_BLANK; return GETSOCK_BLANK;
} }
static int doing_getsock(struct connectdata *conn, static int doing_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks) curl_socket_t *socks)
{ {
if(conn && conn->handler->doing_getsock) if(conn && conn->handler->doing_getsock)
return conn->handler->doing_getsock(conn, socks); return conn->handler->doing_getsock(data, conn, socks);
return GETSOCK_BLANK; return GETSOCK_BLANK;
} }
static int protocol_getsock(struct connectdata *conn, static int protocol_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks) curl_socket_t *socks)
{ {
if(conn->handler->proto_getsock) if(conn->handler->proto_getsock)
return conn->handler->proto_getsock(conn, socks); return conn->handler->proto_getsock(data, conn, socks);
/* Backup getsock logic. Since there is a live socket in use, we must wait /* Backup getsock logic. Since there is a live socket in use, we must wait
for it or it will be removed from watching when the multi_socket API is for it or it will be removed from watching when the multi_socket API is
used. */ used. */
@ -978,10 +977,11 @@ static int protocol_getsock(struct connectdata *conn,
static int multi_getsock(struct Curl_easy *data, static int multi_getsock(struct Curl_easy *data,
curl_socket_t *socks) curl_socket_t *socks)
{ {
struct connectdata *conn = data->conn;
/* The no connection case can happen when this is called from /* The no connection case can happen when this is called from
curl_multi_remove_handle() => singlesocket() => multi_getsock(). curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/ */
if(!data->conn) if(!conn)
return 0; return 0;
if(data->mstate > CURLM_STATE_CONNECT && if(data->mstate > CURLM_STATE_CONNECT &&
@ -995,30 +995,30 @@ static int multi_getsock(struct Curl_easy *data,
return 0; return 0;
case CURLM_STATE_WAITRESOLVE: case CURLM_STATE_WAITRESOLVE:
return Curl_resolv_getsock(data->conn, socks); return Curl_resolv_getsock(conn, socks);
case CURLM_STATE_PROTOCONNECT: case CURLM_STATE_PROTOCONNECT:
case CURLM_STATE_SENDPROTOCONNECT: case CURLM_STATE_SENDPROTOCONNECT:
return protocol_getsock(data->conn, socks); return protocol_getsock(data, conn, socks);
case CURLM_STATE_DO: case CURLM_STATE_DO:
case CURLM_STATE_DOING: case CURLM_STATE_DOING:
return doing_getsock(data->conn, socks); return doing_getsock(data, conn, socks);
case CURLM_STATE_WAITPROXYCONNECT: case CURLM_STATE_WAITPROXYCONNECT:
return waitproxyconnect_getsock(data->conn, socks); return waitproxyconnect_getsock(conn, socks);
case CURLM_STATE_WAITCONNECT: case CURLM_STATE_WAITCONNECT:
return waitconnect_getsock(data->conn, socks); return waitconnect_getsock(conn, socks);
case CURLM_STATE_DO_MORE: case CURLM_STATE_DO_MORE:
return domore_getsock(data->conn, socks); return domore_getsock(data, conn, socks);
case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
to waiting for the same as the *PERFORM to waiting for the same as the *PERFORM
states */ states */
case CURLM_STATE_PERFORM: case CURLM_STATE_PERFORM:
return Curl_single_getsock(data->conn, socks); return Curl_single_getsock(data, conn, socks);
} }
} }
@ -1401,7 +1401,8 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
if(conn->handler->do_it) if(conn->handler->do_it)
/* generic protocol-specific function pointer set in curl_connect() */ /* generic protocol-specific function pointer set in curl_connect() */
result = conn->handler->do_it(conn, done); result = conn->handler->do_it(data, done);
return result; return result;
} }
@ -1414,14 +1415,15 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
* DOING state there's more work to do! * DOING state there's more work to do!
*/ */
static CURLcode multi_do_more(struct connectdata *conn, int *complete) static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
*complete = 0; *complete = 0;
if(conn->handler->do_more) if(conn->handler->do_more)
result = conn->handler->do_more(conn, complete); result = conn->handler->do_more(data, complete);
return result; return result;
} }
@ -1432,14 +1434,14 @@ static CURLcode multi_do_more(struct connectdata *conn, int *complete)
* protocol layer. * protocol layer.
*/ */
static CURLcode protocol_connecting(struct connectdata *conn, static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
if(conn && conn->handler->connecting) { if(conn && conn->handler->connecting) {
*done = FALSE; *done = FALSE;
result = conn->handler->connecting(conn, done); result = conn->handler->connecting(data, done);
} }
else else
*done = TRUE; *done = TRUE;
@ -1452,13 +1454,14 @@ static CURLcode protocol_connecting(struct connectdata *conn,
* until the DOING phase is done on protocol layer. * until the DOING phase is done on protocol layer.
*/ */
static CURLcode protocol_doing(struct connectdata *conn, bool *done) static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
if(conn && conn->handler->doing) { if(conn && conn->handler->doing) {
*done = FALSE; *done = FALSE;
result = conn->handler->doing(conn, done); result = conn->handler->doing(data, done);
} }
else else
*done = TRUE; *done = TRUE;
@ -1471,11 +1474,11 @@ static CURLcode protocol_doing(struct connectdata *conn, bool *done)
* proceed with some action. * proceed with some action.
* *
*/ */
static CURLcode protocol_connect(struct connectdata *conn, static CURLcode protocol_connect(struct Curl_easy *data,
bool *protocol_done) bool *protocol_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
DEBUGASSERT(conn); DEBUGASSERT(conn);
DEBUGASSERT(protocol_done); DEBUGASSERT(protocol_done);
@ -1514,7 +1517,7 @@ static CURLcode protocol_connect(struct connectdata *conn,
/* is there a protocol-specific connect() procedure? */ /* is there a protocol-specific connect() procedure? */
/* Call the protocol-specific connect function */ /* Call the protocol-specific connect function */
result = conn->handler->connect_it(conn, protocol_done); result = conn->handler->connect_it(data, protocol_done);
} }
else else
*protocol_done = TRUE; *protocol_done = TRUE;
@ -1785,7 +1788,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITPROXYCONNECT: case CURLM_STATE_WAITPROXYCONNECT:
/* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
DEBUGASSERT(data->conn); DEBUGASSERT(data->conn);
result = Curl_http_connect(data->conn, &protocol_connected); result = Curl_http_connect(data, &protocol_connected);
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
if(data->conn->bits.proxy_connect_closed) { if(data->conn->bits.proxy_connect_closed) {
rc = CURLM_CALL_MULTI_PERFORM; rc = CURLM_CALL_MULTI_PERFORM;
@ -1816,7 +1819,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITCONNECT: case CURLM_STATE_WAITCONNECT:
/* awaiting a completion of an asynch TCP connect */ /* awaiting a completion of an asynch TCP connect */
DEBUGASSERT(data->conn); DEBUGASSERT(data->conn);
result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected); result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
if(connected && !result) { if(connected && !result) {
#ifndef CURL_DISABLE_HTTP #ifndef CURL_DISABLE_HTTP
if( if(
@ -1849,7 +1852,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break; break;
case CURLM_STATE_SENDPROTOCONNECT: case CURLM_STATE_SENDPROTOCONNECT:
result = protocol_connect(data->conn, &protocol_connected); result = protocol_connect(data, &protocol_connected);
if(!result && !protocol_connected) if(!result && !protocol_connected)
/* switch to waiting state */ /* switch to waiting state */
multistate(data, CURLM_STATE_PROTOCONNECT); multistate(data, CURLM_STATE_PROTOCONNECT);
@ -1868,7 +1871,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_PROTOCONNECT: case CURLM_STATE_PROTOCONNECT:
/* protocol-specific connect phase */ /* protocol-specific connect phase */
result = protocol_connecting(data->conn, &protocol_connected); result = protocol_connecting(data, &protocol_connected);
if(!result && protocol_connected) { if(!result && protocol_connected) {
/* after the connect has completed, go WAITDO or DO */ /* after the connect has completed, go WAITDO or DO */
multistate(data, CURLM_STATE_DO); multistate(data, CURLM_STATE_DO);
@ -1994,7 +1997,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_DOING: case CURLM_STATE_DOING:
/* we continue DOING until the DO phase is complete */ /* we continue DOING until the DO phase is complete */
DEBUGASSERT(data->conn); DEBUGASSERT(data->conn);
result = protocol_doing(data->conn, &dophase_done); result = protocol_doing(data, &dophase_done);
if(!result) { if(!result) {
if(dophase_done) { if(dophase_done) {
/* after DO, go DO_DONE or DO_MORE */ /* after DO, go DO_DONE or DO_MORE */
@ -2017,7 +2020,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
* When we are connected, DO MORE and then go DO_DONE * When we are connected, DO MORE and then go DO_DONE
*/ */
DEBUGASSERT(data->conn); DEBUGASSERT(data->conn);
result = multi_do_more(data->conn, &control); result = multi_do_more(data, &control);
if(!result) { if(!result) {
if(control) { if(control) {
@ -2280,14 +2283,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* allow a previously set error code take precedence */ /* allow a previously set error code take precedence */
if(!result) if(!result)
result = res; result = res;
/*
* If there are other handles on the connection, multi_done won't set
* conn to NULL. In such a case, curl_multi_remove_handle() can
* access free'd data, if the connection is free'd and the handle
* removed before we perform the processing in CURLM_STATE_COMPLETED
*/
Curl_detach_connnection(data);
} }
#ifndef CURL_DISABLE_FTP #ifndef CURL_DISABLE_FTP
@ -3329,16 +3324,18 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
* When information about a connection has appeared, call this! * When information about a connection has appeared, call this!
*/ */
void Curl_multiuse_state(struct connectdata *conn, void Curl_multiuse_state(struct Curl_easy *data,
int bundlestate) /* use BUNDLE_* defines */ int bundlestate) /* use BUNDLE_* defines */
{ {
struct connectdata *conn;
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
conn = data->conn;
DEBUGASSERT(conn); DEBUGASSERT(conn);
DEBUGASSERT(conn->bundle); DEBUGASSERT(conn->bundle);
DEBUGASSERT(conn->data);
DEBUGASSERT(conn->data->multi);
conn->bundle->multiuse = bundlestate; conn->bundle->multiuse = bundlestate;
process_pending_handles(conn->data->multi); process_pending_handles(data->multi);
} }
static void process_pending_handles(struct Curl_multi *multi) static void process_pending_handles(struct Curl_multi *multi)

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -69,7 +69,7 @@ size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */ /* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
size_t Curl_multi_max_total_connections(struct Curl_multi *multi); size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
void Curl_multiuse_state(struct connectdata *conn, void Curl_multiuse_state(struct Curl_easy *data,
int bundlestate); /* use BUNDLE_* defines */ int bundlestate); /* use BUNDLE_* defines */
/* /*

View file

@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org> * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
* Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -76,12 +76,14 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
LDAP **ld); LDAP **ld);
#endif #endif
static CURLcode ldap_setup_connection(struct connectdata *conn); static CURLcode ldap_setup_connection(struct Curl_easy *data,
static CURLcode ldap_do(struct connectdata *conn, bool *done); struct connectdata *conn);
static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); static CURLcode ldap_do(struct Curl_easy *data, bool *done);
static CURLcode ldap_connect(struct connectdata *conn, bool *done); static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool);
static CURLcode ldap_connecting(struct connectdata *conn, bool *done); static CURLcode ldap_connect(struct Curl_easy *data, bool *done);
static CURLcode ldap_disconnect(struct connectdata *conn, bool dead); static CURLcode ldap_connecting(struct Curl_easy *data, bool *done);
static CURLcode ldap_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead);
static Curl_recv ldap_recv; static Curl_recv ldap_recv;
@ -169,11 +171,11 @@ struct ldapreqinfo {
int nument; int nument;
}; };
static CURLcode ldap_setup_connection(struct connectdata *conn) static CURLcode ldap_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct ldapconninfo *li; struct ldapconninfo *li;
LDAPURLDesc *lud; LDAPURLDesc *lud;
struct Curl_easy *data = conn->data;
int rc, proto; int rc, proto;
CURLcode status; CURLcode status;
@ -205,10 +207,10 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
static Sockbuf_IO ldapsb_tls; static Sockbuf_IO ldapsb_tls;
#endif #endif
static CURLcode ldap_connect(struct connectdata *conn, bool *done) static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc; struct ldapconninfo *li = conn->proto.ldapc;
struct Curl_easy *data = conn->data;
int rc, proto = LDAP_VERSION3; int rc, proto = LDAP_VERSION3;
char hosturl[1024]; char hosturl[1024];
char *ptr; char *ptr;
@ -252,10 +254,10 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode ldap_connecting(struct connectdata *conn, bool *done) static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc; struct ldapconninfo *li = conn->proto.ldapc;
struct Curl_easy *data = conn->data;
LDAPMessage *msg = NULL; LDAPMessage *msg = NULL;
struct timeval tv = {0, 1}, *tvp; struct timeval tv = {0, 1}, *tvp;
int rc, err; int rc, err;
@ -357,10 +359,12 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) static CURLcode ldap_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{ {
struct ldapconninfo *li = conn->proto.ldapc; struct ldapconninfo *li = conn->proto.ldapc;
(void) dead_connection; (void) dead_connection;
(void) data;
if(li) { if(li) {
if(li->ld) { if(li->ld) {
@ -373,15 +377,15 @@ static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode ldap_do(struct connectdata *conn, bool *done) static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc; struct ldapconninfo *li = conn->proto.ldapc;
struct ldapreqinfo *lr; struct ldapreqinfo *lr;
CURLcode status = CURLE_OK; CURLcode status = CURLE_OK;
int rc = 0; int rc = 0;
LDAPURLDesc *ludp = NULL; LDAPURLDesc *ludp = NULL;
int msgid; int msgid;
struct Curl_easy *data = conn->data;
connkeep(conn, "OpenLDAP do"); connkeep(conn, "OpenLDAP do");
@ -418,10 +422,11 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode ldap_done(struct connectdata *conn, CURLcode res, static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
bool premature) bool premature)
{ {
struct ldapreqinfo *lr = conn->data->req.p.ldap; struct connectdata *conn = data->conn;
struct ldapreqinfo *lr = data->req.p.ldap;
(void)res; (void)res;
(void)premature; (void)premature;
@ -440,11 +445,11 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
return CURLE_OK; return CURLE_OK;
} }
static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *err) size_t len, CURLcode *err)
{ {
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc; struct ldapconninfo *li = conn->proto.ldapc;
struct Curl_easy *data = conn->data;
struct ldapreqinfo *lr = data->req.p.ldap; struct ldapreqinfo *lr = data->req.p.ldap;
int rc, ret; int rc, ret;
LDAPMessage *msg = NULL; LDAPMessage *msg = NULL;
@ -512,20 +517,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
*err = CURLE_RECV_ERROR; *err = CURLE_RECV_ERROR;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len); bv.bv_len);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
@ -546,18 +551,18 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
binary = 0; binary = 0;
if(bvals == NULL) { if(bvals == NULL) {
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len); bv.bv_len);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":\n", 2);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
@ -568,20 +573,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
for(i = 0; bvals[i].bv_val != NULL; i++) { for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0; int binval = 0;
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len); bv.bv_len);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":", 1);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
@ -619,7 +624,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
*err = error; *err = error;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, writeerr = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)": ", 2); (char *)": ", 2);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
@ -628,7 +633,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += 2; data->req.bytecount += 2;
if(val_b64_sz > 0) { if(val_b64_sz > 0) {
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, writeerr = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
val_b64_sz); val_b64_sz);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
@ -639,13 +644,13 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
} }
} }
else { else {
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)" ", 1);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, writeerr = Curl_client_write(data, CLIENTWRITE_BODY, bvals[i].bv_val,
bvals[i].bv_len); bvals[i].bv_len);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
@ -654,7 +659,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += bvals[i].bv_len + 1; data->req.bytecount += bvals[i].bv_len + 1;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
@ -663,14 +668,14 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount++; data->req.bytecount++;
} }
ber_memfree(bvals); ber_memfree(bvals);
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
} }
data->req.bytecount++; data->req.bytecount++;
} }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) { if(writeerr) {
*err = writeerr; *err = writeerr;
return -1; return -1;
@ -724,7 +729,7 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
ber_slen_t ret; ber_slen_t ret;
CURLcode err = CURLE_RECV_ERROR; CURLcode err = CURLE_RECV_ERROR;
ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err); ret = (li->recv)(conn->data, FIRSTSOCKET, buf, len, &err);
if(ret < 0 && err == CURLE_AGAIN) { if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK); SET_SOCKERRNO(EWOULDBLOCK);
} }
@ -739,7 +744,7 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
ber_slen_t ret; ber_slen_t ret;
CURLcode err = CURLE_SEND_ERROR; CURLcode err = CURLE_SEND_ERROR;
ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err); ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err);
if(ret < 0 && err == CURLE_AGAIN) { if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK); SET_SOCKERRNO(EWOULDBLOCK);
} }

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -44,10 +44,10 @@
/* Returns timeout in ms. 0 or negative number means the timeout has already /* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */ triggered */
timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting) timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
struct pingpong *pp, bool disconnecting)
{ {
struct connectdata *conn = pp->conn; struct connectdata *conn = pp->conn;
struct Curl_easy *data = conn->data;
timediff_t timeout_ms; /* in milliseconds */ timediff_t timeout_ms; /* in milliseconds */
timediff_t response_time = (data->set.server_response_timeout)? timediff_t response_time = (data->set.server_response_timeout)?
data->set.server_response_timeout: pp->response_time; data->set.server_response_timeout: pp->response_time;
@ -77,15 +77,15 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
/* /*
* Curl_pp_statemach() * Curl_pp_statemach()
*/ */
CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, CURLcode Curl_pp_statemach(struct Curl_easy *data,
struct pingpong *pp, bool block,
bool disconnecting) bool disconnecting)
{ {
struct connectdata *conn = pp->conn; struct connectdata *conn = pp->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc; int rc;
timediff_t interval_ms; timediff_t interval_ms;
timediff_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting); timediff_t timeout_ms = Curl_pp_state_timeout(data, pp, disconnecting);
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
if(timeout_ms <= 0) { if(timeout_ms <= 0) {
@ -131,17 +131,17 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
} }
else if(rc) else if(rc)
result = pp->statemach_act(conn); result = pp->statemachine(data, pp->conn);
return result; return result;
} }
/* initialize stuff to prepare for reading a fresh new response */ /* initialize stuff to prepare for reading a fresh new response */
void Curl_pp_init(struct pingpong *pp) void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp)
{ {
struct connectdata *conn = pp->conn; DEBUGASSERT(data);
pp->nread_resp = 0; pp->nread_resp = 0;
pp->linestart_resp = conn->data->state.buffer; pp->linestart_resp = data->state.buffer;
pp->pending_resp = TRUE; pp->pending_resp = TRUE;
pp->response = Curl_now(); /* start response time-out now! */ pp->response = Curl_now(); /* start response time-out now! */
} }
@ -162,7 +162,8 @@ void Curl_pp_setup(struct pingpong *pp)
* *
* made to never block * made to never block
*/ */
CURLcode Curl_pp_vsendf(struct pingpong *pp, CURLcode Curl_pp_vsendf(struct Curl_easy *data,
struct pingpong *pp,
const char *fmt, const char *fmt,
va_list args) va_list args)
{ {
@ -171,7 +172,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
char *s; char *s;
CURLcode result; CURLcode result;
struct connectdata *conn = pp->conn; struct connectdata *conn = pp->conn;
struct Curl_easy *data;
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
enum protection_level data_sec; enum protection_level data_sec;
@ -184,7 +184,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
if(!conn) if(!conn)
/* can't send without a connection! */ /* can't send without a connection! */
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
data = conn->data;
Curl_dyn_reset(&pp->sendbuf); Curl_dyn_reset(&pp->sendbuf);
result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args); result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args);
@ -198,7 +197,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
write_len = Curl_dyn_len(&pp->sendbuf); write_len = Curl_dyn_len(&pp->sendbuf);
s = Curl_dyn_ptr(&pp->sendbuf); s = Curl_dyn_ptr(&pp->sendbuf);
Curl_pp_init(pp); Curl_pp_init(data, pp);
result = Curl_convert_to_network(data, s, write_len); result = Curl_convert_to_network(data, s, write_len);
/* Curl_convert_to_network calls failf if unsuccessful */ /* Curl_convert_to_network calls failf if unsuccessful */
@ -208,7 +207,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD; conn->data_prot = PROT_CMD;
#endif #endif
result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, result = Curl_write(data, conn->sock[FIRSTSOCKET], s, write_len,
&bytes_written); &bytes_written);
if(result) if(result)
return result; return result;
@ -246,14 +245,14 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
* *
* made to never block * made to never block
*/ */
CURLcode Curl_pp_sendf(struct pingpong *pp, CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp,
const char *fmt, ...) const char *fmt, ...)
{ {
CURLcode result; CURLcode result;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
result = Curl_pp_vsendf(pp, fmt, ap); result = Curl_pp_vsendf(data, pp, fmt, ap);
va_end(ap); va_end(ap);
@ -265,7 +264,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
* *
* Reads a piece of a server response. * Reads a piece of a server response.
*/ */
CURLcode Curl_pp_readresp(curl_socket_t sockfd, CURLcode Curl_pp_readresp(struct Curl_easy *data,
curl_socket_t sockfd,
struct pingpong *pp, struct pingpong *pp,
int *code, /* return the server code if done */ int *code, /* return the server code if done */
size_t *size) /* size of the response */ size_t *size) /* size of the response */
@ -275,7 +275,6 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
ssize_t gotbytes; ssize_t gotbytes;
char *ptr; char *ptr;
struct connectdata *conn = pp->conn; struct connectdata *conn = pp->conn;
struct Curl_easy *data = conn->data;
char * const buf = data->state.buffer; char * const buf = data->state.buffer;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -315,7 +314,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#endif #endif
DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <= DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
(buf + data->set.buffer_size + 1)); (buf + data->set.buffer_size + 1));
result = Curl_read(conn, sockfd, ptr, result = Curl_read(data, sockfd, ptr,
data->set.buffer_size - pp->nread_resp, data->set.buffer_size - pp->nread_resp,
&gotbytes); &gotbytes);
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
@ -371,12 +370,12 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
* for "headers". The response lines can be seen as a kind of * for "headers". The response lines can be seen as a kind of
* headers. * headers.
*/ */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, result = Curl_client_write(data, CLIENTWRITE_HEADER,
pp->linestart_resp, perline); pp->linestart_resp, perline);
if(result) if(result)
return result; return result;
if(pp->endofresp(conn, pp->linestart_resp, perline, code)) { if(pp->endofresp(data, conn, pp->linestart_resp, perline, code)) {
/* This is the end of the last line, copy the last line to the /* This is the end of the last line, copy the last line to the
start of the buffer and null-terminate, for old times sake */ start of the buffer and null-terminate, for old times sake */
size_t n = ptr - pp->linestart_resp; size_t n = ptr - pp->linestart_resp;
@ -456,8 +455,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
return result; return result;
} }
int Curl_pp_getsock(struct pingpong *pp, int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks)
curl_socket_t *socks)
{ {
struct connectdata *conn = pp->conn; struct connectdata *conn = pp->conn;
socks[0] = conn->sock[FIRSTSOCKET]; socks[0] = conn->sock[FIRSTSOCKET];
@ -477,7 +475,7 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
struct connectdata *conn = pp->conn; struct connectdata *conn = pp->conn;
ssize_t written; ssize_t written;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize - CURLcode result = Curl_write(conn->data, sock, pp->sendthis + pp->sendsize -
pp->sendleft, pp->sendleft, &written); pp->sendleft, pp->sendleft, &written);
if(result) if(result)
return result; return result;

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -62,37 +62,44 @@ struct pingpong {
off, used to time-out response reading */ off, used to time-out response reading */
timediff_t response_time; /* When no timeout is given, this is the amount of timediff_t response_time; /* When no timeout is given, this is the amount of
milliseconds we await for a server response. */ milliseconds we await for a server response. */
struct connectdata *conn; /* points to the connectdata struct that this struct connectdata *conn; /* the connection */
belongs to */
struct dynbuf sendbuf; struct dynbuf sendbuf;
/* Function pointers the protocols MUST implement and provide for the /* Function pointers the protocols MUST implement and provide for the
pingpong layer to function */ pingpong layer to function */
CURLcode (*statemach_act)(struct connectdata *conn); CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn);
bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn,
bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len, char *ptr, size_t len, int *code);
int *code);
}; };
#define PINGPONG_SETUP(pp,s,e) \
do { \
pp->response_time = RESP_TIMEOUT; \
pp->statemachine = s; \
pp->endofresp = e; \
pp->conn = conn; \
} while(0)
/* /*
* Curl_pp_statemach() * Curl_pp_statemach()
* *
* called repeatedly until done. Set 'wait' to make it wait a while on the * called repeatedly until done. Set 'wait' to make it wait a while on the
* socket if there's no traffic. * socket if there's no traffic.
*/ */
CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp,
bool disconnecting); bool block, bool disconnecting);
/* initialize stuff to prepare for reading a fresh new response */ /* initialize stuff to prepare for reading a fresh new response */
void Curl_pp_init(struct pingpong *pp); void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp);
/* setup for the transfer */ /* setup for the transfer */
void Curl_pp_setup(struct pingpong *pp); void Curl_pp_setup(struct pingpong *pp);
/* Returns timeout in ms. 0 or negative number means the timeout has already /* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */ triggered */
timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting); timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
struct pingpong *pp, bool disconnecting);
/*********************************************************************** /***********************************************************************
@ -105,7 +112,8 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
* *
* made to never block * made to never block
*/ */
CURLcode Curl_pp_sendf(struct pingpong *pp, CURLcode Curl_pp_sendf(struct Curl_easy *data,
struct pingpong *pp,
const char *fmt, ...); const char *fmt, ...);
/*********************************************************************** /***********************************************************************
@ -118,7 +126,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
* *
* made to never block * made to never block
*/ */
CURLcode Curl_pp_vsendf(struct pingpong *pp, CURLcode Curl_pp_vsendf(struct Curl_easy *data,
struct pingpong *pp,
const char *fmt, const char *fmt,
va_list args); va_list args);
@ -127,7 +136,8 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
* *
* Reads a piece of a server response. * Reads a piece of a server response.
*/ */
CURLcode Curl_pp_readresp(curl_socket_t sockfd, CURLcode Curl_pp_readresp(struct Curl_easy *data,
curl_socket_t sockfd,
struct pingpong *pp, struct pingpong *pp,
int *code, /* return the server code if done */ int *code, /* return the server code if done */
size_t *size); /* size of the response */ size_t *size); /* size of the response */

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -88,22 +88,27 @@
#include "memdebug.h" #include "memdebug.h"
/* Local API functions */ /* Local API functions */
static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done); static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done);
static CURLcode pop3_do(struct connectdata *conn, bool *done); static CURLcode pop3_do(struct Curl_easy *data, bool *done);
static CURLcode pop3_done(struct connectdata *conn, CURLcode status, static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
bool premature); bool premature);
static CURLcode pop3_connect(struct connectdata *conn, bool *done); static CURLcode pop3_connect(struct Curl_easy *data, bool *done);
static CURLcode pop3_disconnect(struct connectdata *conn, bool dead); static CURLcode pop3_disconnect(struct Curl_easy *data,
static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done); struct connectdata *conn, bool dead);
static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks); static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done);
static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done); static int pop3_getsock(struct Curl_easy *data,
static CURLcode pop3_setup_connection(struct connectdata *conn); struct connectdata *conn, curl_socket_t *socks);
static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode pop3_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static CURLcode pop3_parse_url_options(struct connectdata *conn); static CURLcode pop3_parse_url_options(struct connectdata *conn);
static CURLcode pop3_parse_url_path(struct connectdata *conn); static CURLcode pop3_parse_url_path(struct Curl_easy *data);
static CURLcode pop3_parse_custom_request(struct connectdata *conn); static CURLcode pop3_parse_custom_request(struct Curl_easy *data);
static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, static CURLcode pop3_perform_auth(struct Curl_easy *data,
struct connectdata *conn, const char *mech,
const char *initresp); const char *initresp);
static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp); static CURLcode pop3_continue_auth(struct Curl_easy *data,
struct connectdata *conn, const char *resp);
static void pop3_get_message(char *buffer, char **outptr); static void pop3_get_message(char *buffer, char **outptr);
/* /*
@ -195,10 +200,11 @@ static void pop3_to_pop3s(struct connectdata *conn)
* capabilities from the CAPA response including the supported authentication * capabilities from the CAPA response including the supported authentication
* types and allowed SASL mechanisms. * types and allowed SASL mechanisms.
*/ */
static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
int *resp) char *line, size_t len, int *resp)
{ {
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
(void)data;
/* Do we have an error response? */ /* Do we have an error response? */
if(len >= 4 && !memcmp("-ERR", line, 4)) { if(len >= 4 && !memcmp("-ERR", line, 4)) {
@ -279,9 +285,9 @@ static void pop3_get_message(char *buffer, char **outptr)
* *
* This is the ONLY way to change POP3 state! * This is the ONLY way to change POP3 state!
*/ */
static void state(struct connectdata *conn, pop3state newstate) static void state(struct Curl_easy *data, pop3state newstate)
{ {
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &data->conn->proto.pop3c;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */ /* for debug purposes */
static const char * const names[] = { static const char * const names[] = {
@ -300,7 +306,7 @@ static void state(struct connectdata *conn, pop3state newstate)
}; };
if(pop3c->state != newstate) if(pop3c->state != newstate)
infof(conn->data, "POP3 %p state change from %s to %s\n", infof(data, "POP3 %p state change from %s to %s\n",
(void *)pop3c, names[pop3c->state], names[newstate]); (void *)pop3c, names[pop3c->state], names[newstate]);
#endif #endif
@ -314,7 +320,8 @@ static void state(struct connectdata *conn, pop3state newstate)
* Sends the CAPA command in order to obtain a list of server side supported * Sends the CAPA command in order to obtain a list of server side supported
* capabilities. * capabilities.
*/ */
static CURLcode pop3_perform_capa(struct connectdata *conn) static CURLcode pop3_perform_capa(struct Curl_easy *data,
struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
@ -324,10 +331,10 @@ static CURLcode pop3_perform_capa(struct connectdata *conn)
pop3c->tls_supported = FALSE; /* Clear the TLS capability */ pop3c->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPA command */ /* Send the CAPA command */
result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA"); result = Curl_pp_sendf(data, &pop3c->pp, "%s", "CAPA");
if(!result) if(!result)
state(conn, POP3_CAPA); state(data, POP3_CAPA);
return result; return result;
} }
@ -338,13 +345,14 @@ static CURLcode pop3_perform_capa(struct connectdata *conn)
* *
* Sends the STLS command to start the upgrade to TLS. * Sends the STLS command to start the upgrade to TLS.
*/ */
static CURLcode pop3_perform_starttls(struct connectdata *conn) static CURLcode pop3_perform_starttls(struct Curl_easy *data,
struct connectdata *conn)
{ {
/* Send the STLS command */ /* Send the STLS command */
CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS"); CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS");
if(!result) if(!result)
state(conn, POP3_STARTTLS); state(data, POP3_STARTTLS);
return result; return result;
} }
@ -355,7 +363,8 @@ static CURLcode pop3_perform_starttls(struct connectdata *conn)
* *
* Performs the upgrade to TLS. * Performs the upgrade to TLS.
*/ */
static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn) static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
struct connectdata *conn)
{ {
/* Start the SSL connection */ /* Start the SSL connection */
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
@ -364,11 +373,11 @@ static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
if(!result) { if(!result) {
if(pop3c->state != POP3_UPGRADETLS) if(pop3c->state != POP3_UPGRADETLS)
state(conn, POP3_UPGRADETLS); state(data, POP3_UPGRADETLS);
if(pop3c->ssldone) { if(pop3c->ssldone) {
pop3_to_pop3s(conn); pop3_to_pop3s(conn);
result = pop3_perform_capa(conn); result = pop3_perform_capa(data, conn);
} }
} }
@ -381,23 +390,24 @@ static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
* *
* Sends a clear text USER command to authenticate with. * Sends a clear text USER command to authenticate with.
*/ */
static CURLcode pop3_perform_user(struct connectdata *conn) static CURLcode pop3_perform_user(struct Curl_easy *data,
struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
/* Check we have a username and password to authenticate with and end the /* Check we have a username and password to authenticate with and end the
connect phase if we don't */ connect phase if we don't */
if(!conn->bits.user_passwd) { if(!conn->bits.user_passwd) {
state(conn, POP3_STOP); state(data, POP3_STOP);
return result; return result;
} }
/* Send the USER command */ /* Send the USER command */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s", result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s",
conn->user ? conn->user : ""); conn->user ? conn->user : "");
if(!result) if(!result)
state(conn, POP3_USER); state(data, POP3_USER);
return result; return result;
} }
@ -409,7 +419,8 @@ static CURLcode pop3_perform_user(struct connectdata *conn)
* *
* Sends an APOP command to authenticate with. * Sends an APOP command to authenticate with.
*/ */
static CURLcode pop3_perform_apop(struct connectdata *conn) static CURLcode pop3_perform_apop(struct Curl_easy *data,
struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
@ -421,7 +432,7 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
/* Check we have a username and password to authenticate with and end the /* Check we have a username and password to authenticate with and end the
connect phase if we don't */ connect phase if we don't */
if(!conn->bits.user_passwd) { if(!conn->bits.user_passwd) {
state(conn, POP3_STOP); state(data, POP3_STOP);
return result; return result;
} }
@ -444,10 +455,10 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
for(i = 0; i < MD5_DIGEST_LEN; i++) for(i = 0; i < MD5_DIGEST_LEN; i++)
msnprintf(&secret[2 * i], 3, "%02x", digest[i]); msnprintf(&secret[2 * i], 3, "%02x", digest[i]);
result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret); result = Curl_pp_sendf(data, &pop3c->pp, "APOP %s %s", conn->user, secret);
if(!result) if(!result)
state(conn, POP3_APOP); state(data, POP3_APOP);
return result; return result;
} }
@ -460,7 +471,8 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
* Sends an AUTH command allowing the client to login with the given SASL * Sends an AUTH command allowing the client to login with the given SASL
* authentication mechanism. * authentication mechanism.
*/ */
static CURLcode pop3_perform_auth(struct connectdata *conn, static CURLcode pop3_perform_auth(struct Curl_easy *data,
struct connectdata *conn,
const char *mech, const char *mech,
const char *initresp) const char *initresp)
{ {
@ -469,11 +481,11 @@ static CURLcode pop3_perform_auth(struct connectdata *conn,
if(initresp) { /* AUTH <mech> ...<crlf> */ if(initresp) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */ /* Send the AUTH command with the initial response */
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp); result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, initresp);
} }
else { else {
/* Send the AUTH command */ /* Send the AUTH command */
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s", mech);
} }
return result; return result;
@ -485,12 +497,13 @@ static CURLcode pop3_perform_auth(struct connectdata *conn,
* *
* Sends SASL continuation data or cancellation. * Sends SASL continuation data or cancellation.
*/ */
static CURLcode pop3_continue_auth(struct connectdata *conn, static CURLcode pop3_continue_auth(struct Curl_easy *data,
struct connectdata *conn,
const char *resp) const char *resp)
{ {
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
return Curl_pp_sendf(&pop3c->pp, "%s", resp); return Curl_pp_sendf(data, &pop3c->pp, "%s", resp);
} }
/*********************************************************************** /***********************************************************************
@ -501,7 +514,8 @@ static CURLcode pop3_continue_auth(struct connectdata *conn,
* authentication mechanism, falling back to APOP and clear text should a * authentication mechanism, falling back to APOP and clear text should a
* common mechanism not be available between the client and server. * common mechanism not be available between the client and server.
*/ */
static CURLcode pop3_perform_authentication(struct connectdata *conn) static CURLcode pop3_perform_authentication(struct Curl_easy *data,
struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
@ -510,7 +524,7 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
/* Check we have enough data to authenticate with and end the /* Check we have enough data to authenticate with and end the
connect phase if we don't */ connect phase if we don't */
if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) { if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) {
state(conn, POP3_STOP); state(data, POP3_STOP);
return result; return result;
} }
@ -520,22 +534,22 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
if(!result) if(!result)
if(progress == SASL_INPROGRESS) if(progress == SASL_INPROGRESS)
state(conn, POP3_AUTH); state(data, POP3_AUTH);
} }
if(!result && progress == SASL_IDLE) { if(!result && progress == SASL_IDLE) {
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */ /* Perform APOP authentication */
result = pop3_perform_apop(conn); result = pop3_perform_apop(data, conn);
else else
#endif #endif
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */ /* Perform clear text authentication */
result = pop3_perform_user(conn); result = pop3_perform_user(data, conn);
else { else {
/* Other mechanisms not supported */ /* Other mechanisms not supported */
infof(conn->data, "No known authentication mechanisms supported!\n"); infof(data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED; result = CURLE_LOGIN_DENIED;
} }
} }
@ -549,15 +563,15 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
* *
* Sends a POP3 based command. * Sends a POP3 based command.
*/ */
static CURLcode pop3_perform_command(struct connectdata *conn) static CURLcode pop3_perform_command(struct Curl_easy *data)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct POP3 *pop3 = data->req.p.pop3; struct POP3 *pop3 = data->req.p.pop3;
const char *command = NULL; const char *command = NULL;
/* Calculate the default command */ /* Calculate the default command */
if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) { if(pop3->id[0] == '\0' || data->set.ftp_list_only) {
command = "LIST"; command = "LIST";
if(pop3->id[0] != '\0') if(pop3->id[0] != '\0')
@ -569,16 +583,16 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
/* Send the command */ /* Send the command */
if(pop3->id[0] != '\0') if(pop3->id[0] != '\0')
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s", result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s %s",
(pop3->custom && pop3->custom[0] != '\0' ? (pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command), pop3->id); pop3->custom : command), pop3->id);
else else
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s",
(pop3->custom && pop3->custom[0] != '\0' ? (pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command)); pop3->custom : command));
if(!result) if(!result)
state(conn, POP3_COMMAND); state(data, POP3_COMMAND);
return result; return result;
} }
@ -589,24 +603,25 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
* *
* Performs the quit action prior to sclose() be called. * Performs the quit action prior to sclose() be called.
*/ */
static CURLcode pop3_perform_quit(struct connectdata *conn) static CURLcode pop3_perform_quit(struct Curl_easy *data,
struct connectdata *conn)
{ {
/* Send the QUIT command */ /* Send the QUIT command */
CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT"); CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT");
if(!result) if(!result)
state(conn, POP3_QUIT); state(data, POP3_QUIT);
return result; return result;
} }
/* For the initial server greeting */ /* For the initial server greeting */
static CURLcode pop3_state_servergreet_resp(struct connectdata *conn, static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
int pop3code, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer; const char *line = data->state.buffer;
size_t len = strlen(line); size_t len = strlen(line);
@ -654,18 +669,18 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
} }
} }
result = pop3_perform_capa(conn); result = pop3_perform_capa(data, conn);
} }
return result; return result;
} }
/* For CAPA responses */ /* For CAPA responses */
static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer; const char *line = data->state.buffer;
size_t len = strlen(line); size_t len = strlen(line);
@ -728,36 +743,35 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
/* We don't have a SSL/TLS connection yet, but SSL is requested */ /* We don't have a SSL/TLS connection yet, but SSL is requested */
if(pop3c->tls_supported) if(pop3c->tls_supported)
/* Switch to TLS connection now */ /* Switch to TLS connection now */
result = pop3_perform_starttls(conn); result = pop3_perform_starttls(data, conn);
else if(data->set.use_ssl == CURLUSESSL_TRY) else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */ /* Fallback and carry on with authentication */
result = pop3_perform_authentication(conn); result = pop3_perform_authentication(data, conn);
else { else {
failf(data, "STLS not supported."); failf(data, "STLS not supported.");
result = CURLE_USE_SSL_FAILED; result = CURLE_USE_SSL_FAILED;
} }
} }
else else
result = pop3_perform_authentication(conn); result = pop3_perform_authentication(data, conn);
} }
else { else {
/* Clear text is supported when CAPA isn't recognised */ /* Clear text is supported when CAPA isn't recognised */
pop3c->authtypes |= POP3_TYPE_CLEARTEXT; pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
result = pop3_perform_authentication(conn); result = pop3_perform_authentication(data, conn);
} }
return result; return result;
} }
/* For STARTTLS responses */ /* For STARTTLS responses */
static CURLcode pop3_state_starttls_resp(struct connectdata *conn, static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
struct connectdata *conn,
int pop3code, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(pop3code != '+') { if(pop3code != '+') {
@ -766,21 +780,21 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED; result = CURLE_USE_SSL_FAILED;
} }
else else
result = pop3_perform_authentication(conn); result = pop3_perform_authentication(data, conn);
} }
else else
result = pop3_perform_upgrade_tls(conn); result = pop3_perform_upgrade_tls(data, conn);
return result; return result;
} }
/* For SASL authentication responses */ /* For SASL authentication responses */
static CURLcode pop3_state_auth_resp(struct connectdata *conn, static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
int pop3code, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
saslprogress progress; saslprogress progress;
@ -790,18 +804,18 @@ static CURLcode pop3_state_auth_resp(struct connectdata *conn,
if(!result) if(!result)
switch(progress) { switch(progress) {
case SASL_DONE: case SASL_DONE:
state(conn, POP3_STOP); /* Authenticated */ state(data, POP3_STOP); /* Authenticated */
break; break;
case SASL_IDLE: /* No mechanism left after cancellation */ case SASL_IDLE: /* No mechanism left after cancellation */
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */ /* Perform APOP authentication */
result = pop3_perform_apop(conn); result = pop3_perform_apop(data, conn);
else else
#endif #endif
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */ /* Perform clear text authentication */
result = pop3_perform_user(conn); result = pop3_perform_user(data, conn);
else { else {
failf(data, "Authentication cancelled"); failf(data, "Authentication cancelled");
result = CURLE_LOGIN_DENIED; result = CURLE_LOGIN_DENIED;
@ -816,12 +830,10 @@ static CURLcode pop3_state_auth_resp(struct connectdata *conn,
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
/* For APOP responses */ /* For APOP responses */
static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code, static CURLcode pop3_state_apop_resp(struct Curl_easy *data, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(pop3code != '+') { if(pop3code != '+') {
@ -830,19 +842,18 @@ static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
} }
else else
/* End of connect phase */ /* End of connect phase */
state(conn, POP3_STOP); state(data, POP3_STOP);
return result; return result;
} }
#endif #endif
/* For USER responses */ /* For USER responses */
static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code, static CURLcode pop3_state_user_resp(struct Curl_easy *data, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(pop3code != '+') { if(pop3code != '+') {
@ -851,21 +862,19 @@ static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code,
} }
else else
/* Send the PASS command */ /* Send the PASS command */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s", result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "PASS %s",
conn->passwd ? conn->passwd : ""); conn->passwd ? conn->passwd : "");
if(!result) if(!result)
state(conn, POP3_PASS); state(data, POP3_PASS);
return result; return result;
} }
/* For PASS responses */ /* For PASS responses */
static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code, static CURLcode pop3_state_pass_resp(struct Curl_easy *data, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(pop3code != '+') { if(pop3code != '+') {
@ -874,18 +883,18 @@ static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
} }
else else
/* End of connect phase */ /* End of connect phase */
state(conn, POP3_STOP); state(data, POP3_STOP);
return result; return result;
} }
/* For command responses */ /* For command responses */
static CURLcode pop3_state_command_resp(struct connectdata *conn, static CURLcode pop3_state_command_resp(struct Curl_easy *data,
int pop3code, int pop3code,
pop3state instate) pop3state instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct POP3 *pop3 = data->req.p.pop3; struct POP3 *pop3 = data->req.p.pop3;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp; struct pingpong *pp = &pop3c->pp;
@ -893,7 +902,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(pop3code != '+') { if(pop3code != '+') {
state(conn, POP3_STOP); state(data, POP3_STOP);
return CURLE_RECV_ERROR; return CURLE_RECV_ERROR;
} }
@ -917,7 +926,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
"headers" after the body */ "headers" after the body */
if(!data->set.opt_no_body) { if(!data->set.opt_no_body) {
result = Curl_pop3_write(conn, pp->cache, pp->cache_size); result = Curl_pop3_write(data, pp->cache, pp->cache_size);
if(result) if(result)
return result; return result;
} }
@ -931,12 +940,13 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
} }
/* End of DO phase */ /* End of DO phase */
state(conn, POP3_STOP); state(data, POP3_STOP);
return result; return result;
} }
static CURLcode pop3_statemach_act(struct connectdata *conn) static CURLcode pop3_statemachine(struct Curl_easy *data,
struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
@ -944,10 +954,11 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp; struct pingpong *pp = &pop3c->pp;
size_t nread = 0; size_t nread = 0;
(void)data;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
if(pop3c->state == POP3_UPGRADETLS) if(pop3c->state == POP3_UPGRADETLS)
return pop3_perform_upgrade_tls(conn); return pop3_perform_upgrade_tls(data, conn);
/* Flush any data that needs to be sent */ /* Flush any data that needs to be sent */
if(pp->sendleft) if(pp->sendleft)
@ -955,9 +966,9 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
do { do {
/* Read the response from the server */ /* Read the response from the server */
result = Curl_pp_readresp(sock, pp, &pop3code, &nread); result = Curl_pp_readresp(data, sock, pp, &pop3code, &nread);
if(result) if(result)
return result; return result;
if(!pop3code) if(!pop3code)
break; break;
@ -965,44 +976,44 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
/* We have now received a full POP3 server response */ /* We have now received a full POP3 server response */
switch(pop3c->state) { switch(pop3c->state) {
case POP3_SERVERGREET: case POP3_SERVERGREET:
result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state); result = pop3_state_servergreet_resp(data, pop3code, pop3c->state);
break; break;
case POP3_CAPA: case POP3_CAPA:
result = pop3_state_capa_resp(conn, pop3code, pop3c->state); result = pop3_state_capa_resp(data, pop3code, pop3c->state);
break; break;
case POP3_STARTTLS: case POP3_STARTTLS:
result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); result = pop3_state_starttls_resp(data, conn, pop3code, pop3c->state);
break; break;
case POP3_AUTH: case POP3_AUTH:
result = pop3_state_auth_resp(conn, pop3code, pop3c->state); result = pop3_state_auth_resp(data, pop3code, pop3c->state);
break; break;
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
case POP3_APOP: case POP3_APOP:
result = pop3_state_apop_resp(conn, pop3code, pop3c->state); result = pop3_state_apop_resp(data, pop3code, pop3c->state);
break; break;
#endif #endif
case POP3_USER: case POP3_USER:
result = pop3_state_user_resp(conn, pop3code, pop3c->state); result = pop3_state_user_resp(data, pop3code, pop3c->state);
break; break;
case POP3_PASS: case POP3_PASS:
result = pop3_state_pass_resp(conn, pop3code, pop3c->state); result = pop3_state_pass_resp(data, pop3code, pop3c->state);
break; break;
case POP3_COMMAND: case POP3_COMMAND:
result = pop3_state_command_resp(conn, pop3code, pop3c->state); result = pop3_state_command_resp(data, pop3code, pop3c->state);
break; break;
case POP3_QUIT: case POP3_QUIT:
/* fallthrough, just stop! */ /* fallthrough, just stop! */
default: default:
/* internal error */ /* internal error */
state(conn, POP3_STOP); state(data, POP3_STOP);
break; break;
} }
} while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp)); } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
@ -1011,9 +1022,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
} }
/* Called repeatedly until done from multi.c */ /* Called repeatedly until done from multi.c */
static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) { if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
@ -1022,30 +1034,30 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
return result; return result;
} }
result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE); result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE);
*done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
return result; return result;
} }
static CURLcode pop3_block_statemach(struct connectdata *conn, static CURLcode pop3_block_statemach(struct Curl_easy *data,
struct connectdata *conn,
bool disconnecting) bool disconnecting)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
while(pop3c->state != POP3_STOP && !result) while(pop3c->state != POP3_STOP && !result)
result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting); result = Curl_pp_statemach(data, &pop3c->pp, TRUE, disconnecting);
return result; return result;
} }
/* Allocate and initialize the POP3 struct for the current Curl_easy if /* Allocate and initialize the POP3 struct for the current Curl_easy if
required */ required */
static CURLcode pop3_init(struct connectdata *conn) static CURLcode pop3_init(struct Curl_easy *data)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct POP3 *pop3; struct POP3 *pop3;
pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1); pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1);
@ -1056,8 +1068,10 @@ static CURLcode pop3_init(struct connectdata *conn)
} }
/* For the POP3 "protocol connect" and "doing" phases only */ /* For the POP3 "protocol connect" and "doing" phases only */
static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks) static int pop3_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{ {
(void)data;
return Curl_pp_getsock(&conn->proto.pop3c.pp, socks); return Curl_pp_getsock(&conn->proto.pop3c.pp, socks);
} }
@ -1071,9 +1085,10 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks)
* The variable 'done' points to will be TRUE if the protocol-layer connect * The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE if not. * phase is done when this function returns, or FALSE if not.
*/ */
static CURLcode pop3_connect(struct connectdata *conn, bool *done) static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp; struct pingpong *pp = &pop3c->pp;
@ -1082,11 +1097,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
/* We always support persistent connections in POP3 */ /* We always support persistent connections in POP3 */
connkeep(conn, "POP3 default"); connkeep(conn, "POP3 default");
/* Set the default response time-out */ PINGPONG_SETUP(pp, pop3_statemachine, pop3_endofresp);
pp->response_time = RESP_TIMEOUT;
pp->statemach_act = pop3_statemach_act;
pp->endofresp = pop3_endofresp;
pp->conn = conn;
/* Set the default preferred authentication type and mechanism */ /* Set the default preferred authentication type and mechanism */
pop3c->preftype = POP3_TYPE_ANY; pop3c->preftype = POP3_TYPE_ANY;
@ -1094,7 +1105,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
/* Initialise the pingpong layer */ /* Initialise the pingpong layer */
Curl_pp_setup(pp); Curl_pp_setup(pp);
Curl_pp_init(pp); Curl_pp_init(data, pp);
/* Parse the URL options */ /* Parse the URL options */
result = pop3_parse_url_options(conn); result = pop3_parse_url_options(conn);
@ -1102,9 +1113,9 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
return result; return result;
/* Start off waiting for the server greeting response */ /* Start off waiting for the server greeting response */
state(conn, POP3_SERVERGREET); state(data, POP3_SERVERGREET);
result = pop3_multi_statemach(conn, done); result = pop3_multi_statemach(data, done);
return result; return result;
} }
@ -1118,11 +1129,10 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
* *
* Input argument is already checked for validity. * Input argument is already checked for validity.
*/ */
static CURLcode pop3_done(struct connectdata *conn, CURLcode status, static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct POP3 *pop3 = data->req.p.pop3; struct POP3 *pop3 = data->req.p.pop3;
(void)premature; (void)premature;
@ -1131,7 +1141,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
return CURLE_OK; return CURLE_OK;
if(status) { if(status) {
connclose(conn, "POP3 done with bad status"); connclose(data->conn, "POP3 done with bad status");
result = status; /* use the already set error code */ result = status; /* use the already set error code */
} }
@ -1152,16 +1162,17 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
* This is the actual DO function for POP3. Get a message/listing according to * This is the actual DO function for POP3. Get a message/listing according to
* the options previously setup. * the options previously setup.
*/ */
static CURLcode pop3_perform(struct connectdata *conn, bool *connected, static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
bool *dophase_done) bool *dophase_done)
{ {
/* This is POP3 and no proxy */ /* This is POP3 and no proxy */
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct POP3 *pop3 = conn->data->req.p.pop3; struct connectdata *conn = data->conn;
struct POP3 *pop3 = data->req.p.pop3;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(data, "DO phase starts\n"));
if(conn->data->set.opt_no_body) { if(data->set.opt_no_body) {
/* Requested no body means no transfer */ /* Requested no body means no transfer */
pop3->transfer = FTPTRANSFER_INFO; pop3->transfer = FTPTRANSFER_INFO;
} }
@ -1169,17 +1180,16 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
/* Start the first command in the DO phase */ /* Start the first command in the DO phase */
result = pop3_perform_command(conn); result = pop3_perform_command(data);
if(result) if(result)
return result; return result;
/* Run the state-machine */ /* Run the state-machine */
result = pop3_multi_statemach(conn, dophase_done); result = pop3_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET]; *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
return result; return result;
} }
@ -1193,23 +1203,22 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
* *
* The input argument is already checked for validity. * The input argument is already checked for validity.
*/ */
static CURLcode pop3_do(struct connectdata *conn, bool *done) static CURLcode pop3_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
/* Parse the URL path */ /* Parse the URL path */
result = pop3_parse_url_path(conn); result = pop3_parse_url_path(data);
if(result) if(result)
return result; return result;
/* Parse the custom request */ /* Parse the custom request */
result = pop3_parse_custom_request(conn); result = pop3_parse_custom_request(data);
if(result) if(result)
return result; return result;
result = pop3_regular_transfer(conn, done); result = pop3_regular_transfer(data, done);
return result; return result;
} }
@ -1221,19 +1230,20 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
* Disconnect from an POP3 server. Cleanup protocol-specific per-connection * Disconnect from an POP3 server. Cleanup protocol-specific per-connection
* resources. BLOCKING. * resources. BLOCKING.
*/ */
static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) static CURLcode pop3_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{ {
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
(void)data;
/* We cannot send quit unconditionally. If this connection is stale or /* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to. */ disconnect wait in vain and cause more problems than we need to. */
/* The POP3 session may or may not have been allocated/setup at this if(!dead_connection && conn->bits.protoconnstart) {
point! */ if(!pop3_perform_quit(data, conn))
if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart) (void)pop3_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */
if(!pop3_perform_quit(conn)) }
(void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */
/* Disconnect from the server */ /* Disconnect from the server */
Curl_pp_disconnect(&pop3c->pp); Curl_pp_disconnect(&pop3c->pp);
@ -1248,25 +1258,25 @@ static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
} }
/* Call this when the DO phase has completed */ /* Call this when the DO phase has completed */
static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected) static CURLcode pop3_dophase_done(struct Curl_easy *data, bool connected)
{ {
(void)conn; (void)data;
(void)connected; (void)connected;
return CURLE_OK; return CURLE_OK;
} }
/* Called from multi.c while DOing */ /* Called from multi.c while DOing */
static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done) static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done)
{ {
CURLcode result = pop3_multi_statemach(conn, dophase_done); CURLcode result = pop3_multi_statemach(data, dophase_done);
if(result) if(result)
DEBUGF(infof(conn->data, "DO phase failed\n")); DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) { else if(*dophase_done) {
result = pop3_dophase_done(conn, FALSE /* not connected */); result = pop3_dophase_done(data, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
@ -1281,12 +1291,11 @@ static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done)
* Performs all commands done before a regular transfer between a local and a * Performs all commands done before a regular transfer between a local and a
* remote host. * remote host.
*/ */
static CURLcode pop3_regular_transfer(struct connectdata *conn, static CURLcode pop3_regular_transfer(struct Curl_easy *data,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
bool connected = FALSE; bool connected = FALSE;
struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */ /* Make sure size is unknown at this point */
data->req.size = -1; data->req.size = -1;
@ -1298,19 +1307,20 @@ static CURLcode pop3_regular_transfer(struct connectdata *conn,
Curl_pgrsSetDownloadSize(data, -1); Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */ /* Carry out the perform */
result = pop3_perform(conn, &connected, dophase_done); result = pop3_perform(data, &connected, dophase_done);
/* Perform post DO phase operations if necessary */ /* Perform post DO phase operations if necessary */
if(!result && *dophase_done) if(!result && *dophase_done)
result = pop3_dophase_done(conn, connected); result = pop3_dophase_done(data, connected);
return result; return result;
} }
static CURLcode pop3_setup_connection(struct connectdata *conn) static CURLcode pop3_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
/* Initialise the POP3 layer */ /* Initialise the POP3 layer */
CURLcode result = pop3_init(conn); CURLcode result = pop3_init(data);
if(result) if(result)
return result; return result;
@ -1385,10 +1395,9 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
* *
* Parse the URL path into separate path components. * Parse the URL path into separate path components.
*/ */
static CURLcode pop3_parse_url_path(struct connectdata *conn) static CURLcode pop3_parse_url_path(struct Curl_easy *data)
{ {
/* The POP3 struct is already initialised in pop3_connect() */ /* The POP3 struct is already initialised in pop3_connect() */
struct Curl_easy *data = conn->data;
struct POP3 *pop3 = data->req.p.pop3; struct POP3 *pop3 = data->req.p.pop3;
const char *path = &data->state.up.path[1]; /* skip leading path */ const char *path = &data->state.up.path[1]; /* skip leading path */
@ -1402,10 +1411,9 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
* *
* Parse the custom request. * Parse the custom request.
*/ */
static CURLcode pop3_parse_custom_request(struct connectdata *conn) static CURLcode pop3_parse_custom_request(struct Curl_easy *data)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct POP3 *pop3 = data->req.p.pop3; struct POP3 *pop3 = data->req.p.pop3;
const char *custom = data->set.str[STRING_CUSTOMREQUEST]; const char *custom = data->set.str[STRING_CUSTOMREQUEST];
@ -1423,13 +1431,12 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
* This function scans the body after the end-of-body and writes everything * This function scans the body after the end-of-body and writes everything
* until the end is found. * until the end is found.
*/ */
CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread)
{ {
/* This code could be made into a special function in the handler struct */ /* This code could be made into a special function in the handler struct */
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
bool strip_dot = FALSE; bool strip_dot = FALSE;
size_t last = 0; size_t last = 0;
@ -1450,7 +1457,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
if(i) { if(i) {
/* Write out the body part that didn't match */ /* Write out the body part that didn't match */
result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last],
i - last); i - last);
if(result) if(result)
@ -1508,7 +1515,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
if(prev) { if(prev) {
/* If the partial match was the CRLF and dot then only write the CRLF /* If the partial match was the CRLF and dot then only write the CRLF
as the server would have inserted the dot */ as the server would have inserted the dot */
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
strip_dot ? prev - 1 : prev); strip_dot ? prev - 1 : prev);
if(result) if(result)
@ -1524,7 +1531,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
/* We have a full match so the transfer is done, however we must transfer /* We have a full match so the transfer is done, however we must transfer
the CRLF at the start of the EOB as this is considered to be part of the the CRLF at the start of the EOB as this is considered to be part of the
message as per RFC-1939, sect. 3 */ message as per RFC-1939, sect. 3 */
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2); result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, 2);
k->keepon &= ~KEEP_RECV; k->keepon &= ~KEEP_RECV;
pop3c->eob = 0; pop3c->eob = 0;
@ -1537,7 +1544,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
return CURLE_OK; return CURLE_OK;
if(nread - last) { if(nread - last) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last],
nread - last); nread - last);
} }

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2009 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -90,6 +90,6 @@ extern const struct Curl_handler Curl_handler_pop3s;
/* This function scans the body after the end-of-body and writes everything /* This function scans the body after the end-of-body and writes everything
* until the end is found */ * until the end is found */
CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread); CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread);
#endif /* HEADER_CURL_POP3_H */ #endif /* HEADER_CURL_POP3_H */

View file

@ -48,11 +48,13 @@
((int)((unsigned char)((p)[3])))) ((int)((unsigned char)((p)[3]))))
/* protocol-specific functions set up to be called by the main engine */ /* protocol-specific functions set up to be called by the main engine */
static CURLcode rtsp_do(struct connectdata *conn, bool *done); static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature); static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature);
static CURLcode rtsp_connect(struct connectdata *conn, bool *done); static CURLcode rtsp_connect(struct Curl_easy *data, bool *done);
static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead); static CURLcode rtsp_disconnect(struct Curl_easy *data,
static int rtsp_getsock_do(struct connectdata *conn, curl_socket_t *socks); struct connectdata *conn, bool dead);
static int rtsp_getsock_do(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
/* /*
* Parse and write out any available RTP data. * Parse and write out any available RTP data.
@ -66,17 +68,20 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
ssize_t *nread, ssize_t *nread,
bool *readmore); bool *readmore);
static CURLcode rtsp_setup_connection(struct connectdata *conn); static CURLcode rtsp_setup_connection(struct Curl_easy *data,
static unsigned int rtsp_conncheck(struct connectdata *check, struct connectdata *conn);
static unsigned int rtsp_conncheck(struct Curl_easy *data,
struct connectdata *check,
unsigned int checks_to_perform); unsigned int checks_to_perform);
/* this returns the socket to wait for in the DO and DOING state for the multi /* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */ the single socket to become writable only */
static int rtsp_getsock_do(struct connectdata *conn, static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks) curl_socket_t *socks)
{ {
/* write mode */ /* write mode */
(void)data;
socks[0] = conn->sock[FIRSTSOCKET]; socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0); return GETSOCK_WRITESOCK(0);
} }
@ -111,11 +116,13 @@ const struct Curl_handler Curl_handler_rtsp = {
}; };
static CURLcode rtsp_setup_connection(struct connectdata *conn) static CURLcode rtsp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct RTSP *rtsp; struct RTSP *rtsp;
(void)conn;
conn->data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP)); data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
if(!rtsp) if(!rtsp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -156,13 +163,15 @@ static bool rtsp_connisdead(struct connectdata *check)
/* /*
* Function to check on various aspects of a connection. * Function to check on various aspects of a connection.
*/ */
static unsigned int rtsp_conncheck(struct connectdata *check, static unsigned int rtsp_conncheck(struct Curl_easy *data,
struct connectdata *conn,
unsigned int checks_to_perform) unsigned int checks_to_perform)
{ {
unsigned int ret_val = CONNRESULT_NONE; unsigned int ret_val = CONNRESULT_NONE;
(void)data;
if(checks_to_perform & CONNCHECK_ISDEAD) { if(checks_to_perform & CONNCHECK_ISDEAD) {
if(rtsp_connisdead(check)) if(rtsp_connisdead(conn))
ret_val |= CONNRESULT_DEAD; ret_val |= CONNRESULT_DEAD;
} }
@ -170,12 +179,11 @@ static unsigned int rtsp_conncheck(struct connectdata *check,
} }
static CURLcode rtsp_connect(struct connectdata *conn, bool *done) static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
{ {
CURLcode httpStatus; CURLcode httpStatus;
struct Curl_easy *data = conn->data;
httpStatus = Curl_http_connect(conn, done); httpStatus = Curl_http_connect(data, done);
/* Initialize the CSeq if not already done */ /* Initialize the CSeq if not already done */
if(data->state.rtsp_next_client_CSeq == 0) if(data->state.rtsp_next_client_CSeq == 0)
@ -183,23 +191,24 @@ static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
if(data->state.rtsp_next_server_CSeq == 0) if(data->state.rtsp_next_server_CSeq == 0)
data->state.rtsp_next_server_CSeq = 1; data->state.rtsp_next_server_CSeq = 1;
conn->proto.rtspc.rtp_channel = -1; data->conn->proto.rtspc.rtp_channel = -1;
return httpStatus; return httpStatus;
} }
static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead) static CURLcode rtsp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead)
{ {
(void) dead; (void) dead;
(void) data;
Curl_safefree(conn->proto.rtspc.rtp_buf); Curl_safefree(conn->proto.rtspc.rtp_buf);
return CURLE_OK; return CURLE_OK;
} }
static CURLcode rtsp_done(struct connectdata *conn, static CURLcode rtsp_done(struct Curl_easy *data,
CURLcode status, bool premature) CURLcode status, bool premature)
{ {
struct Curl_easy *data = conn->data;
struct RTSP *rtsp = data->req.p.rtsp; struct RTSP *rtsp = data->req.p.rtsp;
CURLcode httpStatus; CURLcode httpStatus;
@ -207,7 +216,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
if(data->set.rtspreq == RTSPREQ_RECEIVE) if(data->set.rtspreq == RTSPREQ_RECEIVE)
premature = TRUE; premature = TRUE;
httpStatus = Curl_http_done(conn, status, premature); httpStatus = Curl_http_done(data, status, premature);
if(rtsp) { if(rtsp) {
/* Check the sequence numbers */ /* Check the sequence numbers */
@ -220,7 +229,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
return CURLE_RTSP_CSEQ_ERROR; return CURLE_RTSP_CSEQ_ERROR;
} }
if(data->set.rtspreq == RTSPREQ_RECEIVE && if(data->set.rtspreq == RTSPREQ_RECEIVE &&
(conn->proto.rtspc.rtp_channel == -1)) { (data->conn->proto.rtspc.rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
} }
} }
@ -228,9 +237,9 @@ static CURLcode rtsp_done(struct connectdata *conn,
return httpStatus; return httpStatus;
} }
static CURLcode rtsp_do(struct connectdata *conn, bool *done) static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq; Curl_RtspReq rtspreq = data->set.rtspreq;
struct RTSP *rtsp = data->req.p.rtsp; struct RTSP *rtsp = data->req.p.rtsp;
@ -330,7 +339,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
} }
/* Transport Header for SETUP requests */ /* Transport Header for SETUP requests */
p_transport = Curl_checkheaders(conn, "Transport"); p_transport = Curl_checkheaders(data, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) { if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */ /* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) { if(data->set.str[STRING_RTSP_TRANSPORT]) {
@ -354,11 +363,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept Headers for DESCRIBE requests */ /* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) { if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */ /* Accept Header */
p_accept = Curl_checkheaders(conn, "Accept")? p_accept = Curl_checkheaders(data, "Accept")?
NULL:"Accept: application/sdp\r\n"; NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */ /* Accept-Encoding header */
if(!Curl_checkheaders(conn, "Accept-Encoding") && if(!Curl_checkheaders(data, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) { data->set.str[STRING_ENCODING]) {
Curl_safefree(data->state.aptr.accept_encoding); Curl_safefree(data->state.aptr.accept_encoding);
data->state.aptr.accept_encoding = data->state.aptr.accept_encoding =
@ -375,17 +384,17 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string with the user-agent string specified, we erase the previously made string
here. */ here. */
if(Curl_checkheaders(conn, "User-Agent") && data->state.aptr.uagent) { if(Curl_checkheaders(data, "User-Agent") && data->state.aptr.uagent) {
Curl_safefree(data->state.aptr.uagent); Curl_safefree(data->state.aptr.uagent);
data->state.aptr.uagent = NULL; data->state.aptr.uagent = NULL;
} }
else if(!Curl_checkheaders(conn, "User-Agent") && else if(!Curl_checkheaders(data, "User-Agent") &&
data->set.str[STRING_USERAGENT]) { data->set.str[STRING_USERAGENT]) {
p_uagent = data->state.aptr.uagent; p_uagent = data->state.aptr.uagent;
} }
/* setup the authentication headers */ /* setup the authentication headers */
result = Curl_http_output_auth(conn, p_request, HTTPREQ_GET, result = Curl_http_output_auth(data, conn, p_request, HTTPREQ_GET,
p_stream_uri, FALSE); p_stream_uri, FALSE);
if(result) if(result)
return result; return result;
@ -395,7 +404,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */ /* Referrer */
Curl_safefree(data->state.aptr.ref); Curl_safefree(data->state.aptr.ref);
if(data->change.referer && !Curl_checkheaders(conn, "Referer")) if(data->change.referer && !Curl_checkheaders(data, "Referer"))
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else else
data->state.aptr.ref = NULL; data->state.aptr.ref = NULL;
@ -412,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */ /* Check to see if there is a range set in the custom headers */
if(!Curl_checkheaders(conn, "Range") && data->state.range) { if(!Curl_checkheaders(data, "Range") && data->state.range) {
Curl_safefree(data->state.aptr.rangeline); Curl_safefree(data->state.aptr.rangeline);
data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range); data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = data->state.aptr.rangeline; p_range = data->state.aptr.rangeline;
@ -422,11 +431,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* /*
* Sanity check the custom headers * Sanity check the custom headers
*/ */
if(Curl_checkheaders(conn, "CSeq")) { if(Curl_checkheaders(data, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header."); failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR; return CURLE_RTSP_CSEQ_ERROR;
} }
if(Curl_checkheaders(conn, "Session")) { if(Curl_checkheaders(data, "Session")) {
failf(data, "Session ID cannot be set as a custom header."); failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }
@ -485,12 +494,12 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
return result; return result;
if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) { if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
result = Curl_add_timecondition(conn, &req_buffer); result = Curl_add_timecondition(data, &req_buffer);
if(result) if(result)
return result; return result;
} }
result = Curl_add_custom_headers(conn, FALSE, &req_buffer); result = Curl_add_custom_headers(data, FALSE, &req_buffer);
if(result) if(result)
return result; return result;
@ -513,7 +522,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) { if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to /* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */ * actually set a custom Content-Length in the headers */
if(!Curl_checkheaders(conn, "Content-Length")) { if(!Curl_checkheaders(data, "Content-Length")) {
result = result =
Curl_dyn_addf(&req_buffer, Curl_dyn_addf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
@ -524,7 +533,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER || if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) { rtspreq == RTSPREQ_GET_PARAMETER) {
if(!Curl_checkheaders(conn, "Content-Type")) { if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer, result = Curl_dyn_addf(&req_buffer,
"Content-Type: text/parameters\r\n"); "Content-Type: text/parameters\r\n");
if(result) if(result)
@ -533,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
} }
if(rtspreq == RTSPREQ_ANNOUNCE) { if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(conn, "Content-Type")) { if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer, result = Curl_dyn_addf(&req_buffer,
"Content-Type: application/sdp\r\n"); "Content-Type: application/sdp\r\n");
if(result) if(result)
@ -565,7 +574,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
} }
/* issue the request */ /* issue the request */
result = Curl_buffer_send(&req_buffer, conn, result = Curl_buffer_send(&req_buffer, data,
&data->info.request_size, 0, FIRSTSOCKET); &data->info.request_size, 0, FIRSTSOCKET);
if(result) { if(result) {
failf(data, "Failed sending RTSP request"); failf(data, "Failed sending RTSP request");

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -293,7 +293,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
* If the write would block (CURLE_AGAIN), we return CURLE_OK and * If the write would block (CURLE_AGAIN), we return CURLE_OK and
* (*written == 0). Otherwise we return regular CURLcode value. * (*written == 0). Otherwise we return regular CURLcode value.
*/ */
CURLcode Curl_write(struct connectdata *conn, CURLcode Curl_write(struct Curl_easy *data,
curl_socket_t sockfd, curl_socket_t sockfd,
const void *mem, const void *mem,
size_t len, size_t len,
@ -301,9 +301,14 @@ CURLcode Curl_write(struct connectdata *conn,
{ {
ssize_t bytes_written; ssize_t bytes_written;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
int num = (sockfd == conn->sock[SECONDARYSOCKET]); struct connectdata *conn;
int num;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
conn = data->conn;
num = (sockfd == conn->sock[SECONDARYSOCKET]);
bytes_written = conn->send[num](conn, num, mem, len, &result); bytes_written = conn->send[num](data, num, mem, len, &result);
*written = bytes_written; *written = bytes_written;
if(bytes_written >= 0) if(bytes_written >= 0)
@ -326,11 +331,17 @@ CURLcode Curl_write(struct connectdata *conn,
} }
} }
ssize_t Curl_send_plain(struct connectdata *conn, int num, ssize_t Curl_send_plain(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code) const void *mem, size_t len, CURLcode *code)
{ {
curl_socket_t sockfd = conn->sock[num]; struct connectdata *conn;
curl_socket_t sockfd;
ssize_t bytes_written; ssize_t bytes_written;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
conn = data->conn;
sockfd = conn->sock[num];
/* WinSock will destroy unread received data if send() is /* WinSock will destroy unread received data if send() is
failed. failed.
To avoid lossage of received data, recv() must be To avoid lossage of received data, recv() must be
@ -373,9 +384,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
} }
else { else {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
failf(conn->data, "Send failure: %s", failf(data, "Send failure: %s",
Curl_strerror(err, buffer, sizeof(buffer))); Curl_strerror(err, buffer, sizeof(buffer)));
conn->data->state.os_errno = err; data->state.os_errno = err;
*code = CURLE_SEND_ERROR; *code = CURLE_SEND_ERROR;
} }
} }
@ -387,28 +398,31 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
* server using plain sockets only. Otherwise meant to have the exact same * server using plain sockets only. Otherwise meant to have the exact same
* proto as Curl_write() * proto as Curl_write()
*/ */
CURLcode Curl_write_plain(struct connectdata *conn, CURLcode Curl_write_plain(struct Curl_easy *data,
curl_socket_t sockfd, curl_socket_t sockfd,
const void *mem, const void *mem,
size_t len, size_t len,
ssize_t *written) ssize_t *written)
{ {
ssize_t bytes_written;
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
int num = (sockfd == conn->sock[SECONDARYSOCKET]); int num = (sockfd == conn->sock[SECONDARYSOCKET]);
bytes_written = Curl_send_plain(conn, num, mem, len, &result); *written = Curl_send_plain(data, num, mem, len, &result);
*written = bytes_written;
return result; return result;
} }
ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code) size_t len, CURLcode *code)
{ {
curl_socket_t sockfd = conn->sock[num]; struct connectdata *conn;
curl_socket_t sockfd;
ssize_t nread; ssize_t nread;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
conn = data->conn;
sockfd = conn->sock[num];
/* Check and return data that already received and storied in internal /* Check and return data that already received and storied in internal
intermediate buffer */ intermediate buffer */
nread = get_pre_recved(conn, num, buf, len); nread = get_pre_recved(conn, num, buf, len);
@ -439,9 +453,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
} }
else { else {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
failf(conn->data, "Recv failure: %s", failf(data, "Recv failure: %s",
Curl_strerror(err, buffer, sizeof(buffer))); Curl_strerror(err, buffer, sizeof(buffer)));
conn->data->state.os_errno = err; data->state.os_errno = err;
*code = CURLE_RECV_ERROR; *code = CURLE_RECV_ERROR;
} }
} }
@ -500,12 +514,12 @@ static CURLcode pausewrite(struct Curl_easy *data,
* client write callback(s) and takes care of pause requests from the * client write callback(s) and takes care of pause requests from the
* callbacks. * callbacks.
*/ */
static CURLcode chop_write(struct connectdata *conn, static CURLcode chop_write(struct Curl_easy *data,
int type, int type,
char *optr, char *optr,
size_t olen) size_t olen)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
curl_write_callback writeheader = NULL; curl_write_callback writeheader = NULL;
curl_write_callback writebody = NULL; curl_write_callback writebody = NULL;
char *ptr = optr; char *ptr = optr;
@ -595,13 +609,12 @@ static CURLcode chop_write(struct connectdata *conn,
local character encoding. This is a problem and should be changed in local character encoding. This is a problem and should be changed in
the future to leave the original data alone. the future to leave the original data alone.
*/ */
CURLcode Curl_client_write(struct connectdata *conn, CURLcode Curl_client_write(struct Curl_easy *data,
int type, int type,
char *ptr, char *ptr,
size_t len) size_t len)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
if(0 == len) if(0 == len)
len = strlen(ptr); len = strlen(ptr);
@ -623,7 +636,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
#endif /* CURL_DO_LINEEND_CONV */ #endif /* CURL_DO_LINEEND_CONV */
} }
return chop_write(conn, type, ptr, len); return chop_write(data, type, ptr, len);
} }
CURLcode Curl_read_plain(curl_socket_t sockfd, CURLcode Curl_read_plain(curl_socket_t sockfd,
@ -658,7 +671,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
* *
* Returns a regular CURLcode value. * Returns a regular CURLcode value.
*/ */
CURLcode Curl_read(struct connectdata *conn, /* connection data */ CURLcode Curl_read(struct Curl_easy *data, /* transfer */
curl_socket_t sockfd, /* read from this socket */ curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */ char *buf, /* store read data here */
size_t sizerequested, /* max amount to read */ size_t sizerequested, /* max amount to read */
@ -668,7 +681,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
ssize_t nread = 0; ssize_t nread = 0;
size_t bytesfromsocket = 0; size_t bytesfromsocket = 0;
char *buffertofill = NULL; char *buffertofill = NULL;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
/* Set 'num' to 0 or 1, depending on which socket that has been sent here. /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets If it is the second socket, we set num to 1. Otherwise to 0. This lets
@ -680,7 +693,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size); bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
buffertofill = buf; buffertofill = buf;
nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result); nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
if(nread < 0) if(nread < 0)
return result; return result;

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -49,7 +49,7 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...);
#define CLIENTWRITE_HEADER (1<<1) #define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) #define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT; size_t len) WARN_UNUSED_RESULT;
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex); bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);
@ -60,23 +60,24 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
size_t bytesfromsocket, size_t bytesfromsocket,
ssize_t *n); ssize_t *n);
ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code); size_t len, CURLcode *code);
ssize_t Curl_send_plain(struct connectdata *conn, int num, ssize_t Curl_send_plain(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code); const void *mem, size_t len, CURLcode *code);
/* internal read-function, does plain socket, SSL and krb4 */ /* internal read-function, does plain socket, SSL and krb4 */
CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
char *buf, size_t buffersize, char *buf, size_t buffersize,
ssize_t *n); ssize_t *n);
/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ /* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
CURLcode Curl_write(struct connectdata *conn, CURLcode Curl_write(struct Curl_easy *data,
curl_socket_t sockfd, curl_socket_t sockfd,
const void *mem, size_t len, const void *mem, size_t len,
ssize_t *written); ssize_t *written);
/* internal write-function, does plain sockets ONLY */ /* internal write-function, does plain sockets ONLY */
CURLcode Curl_write_plain(struct connectdata *conn, CURLcode Curl_write_plain(struct Curl_easy *data,
curl_socket_t sockfd, curl_socket_t sockfd,
const void *mem, size_t len, const void *mem, size_t len,
ssize_t *written); ssize_t *written);

244
lib/smb.c
View file

@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2016 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
* Copyright (C) 2016-2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -54,16 +54,20 @@
#include "memdebug.h" #include "memdebug.h"
/* Local API functions */ /* Local API functions */
static CURLcode smb_setup_connection(struct connectdata *conn); static CURLcode smb_setup_connection(struct Curl_easy *data,
static CURLcode smb_connect(struct connectdata *conn, bool *done); struct connectdata *conn);
static CURLcode smb_connection_state(struct connectdata *conn, bool *done); static CURLcode smb_connect(struct Curl_easy *data, bool *done);
static CURLcode smb_do(struct connectdata *conn, bool *done); static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
static CURLcode smb_request_state(struct connectdata *conn, bool *done); static CURLcode smb_do(struct Curl_easy *data, bool *done);
static CURLcode smb_done(struct connectdata *conn, CURLcode status, static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
bool premature); bool premature);
static CURLcode smb_disconnect(struct connectdata *conn, bool dead); static CURLcode smb_disconnect(struct Curl_easy *data,
static int smb_getsock(struct connectdata *conn, curl_socket_t *socks); struct connectdata *conn, bool dead);
static CURLcode smb_parse_url_path(struct connectdata *conn); static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks);
static CURLcode smb_parse_url_path(struct Curl_easy *data,
struct connectdata *conn);
/* /*
* SMB handler interface * SMB handler interface
@ -183,9 +187,9 @@ struct smb_request {
CURLcode result; CURLcode result;
}; };
static void conn_state(struct connectdata *conn, enum smb_conn_state newstate) static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
{ {
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &data->conn->proto.smbc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */ /* For debug purposes */
static const char * const names[] = { static const char * const names[] = {
@ -198,17 +202,17 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
}; };
if(smbc->state != newstate) if(smbc->state != newstate)
infof(conn->data, "SMB conn %p state change from %s to %s\n", infof(data, "SMB conn %p state change from %s to %s\n",
(void *)smbc, names[smbc->state], names[newstate]); (void *)smbc, names[smbc->state], names[newstate]);
#endif #endif
smbc->state = newstate; smbc->state = newstate;
} }
static void request_state(struct connectdata *conn, static void request_state(struct Curl_easy *data,
enum smb_req_state newstate) enum smb_req_state newstate)
{ {
struct smb_request *req = conn->data->req.p.smb; struct smb_request *req = data->req.p.smb;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */ /* For debug purposes */
static const char * const names[] = { static const char * const names[] = {
@ -224,7 +228,7 @@ static void request_state(struct connectdata *conn,
}; };
if(req->state != newstate) if(req->state != newstate)
infof(conn->data, "SMB request %p state change from %s to %s\n", infof(data, "SMB request %p state change from %s to %s\n",
(void *)req, names[req->state], names[newstate]); (void *)req, names[req->state], names[newstate]);
#endif #endif
@ -233,21 +237,23 @@ static void request_state(struct connectdata *conn,
/* this should setup things in the connection, not in the easy /* this should setup things in the connection, not in the easy
handle */ handle */
static CURLcode smb_setup_connection(struct connectdata *conn) static CURLcode smb_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct smb_request *req; struct smb_request *req;
/* Initialize the request state */ /* Initialize the request state */
conn->data->req.p.smb = req = calloc(1, sizeof(struct smb_request)); data->req.p.smb = req = calloc(1, sizeof(struct smb_request));
if(!req) if(!req)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* Parse the URL path */ /* Parse the URL path */
return smb_parse_url_path(conn); return smb_parse_url_path(data, conn);
} }
static CURLcode smb_connect(struct connectdata *conn, bool *done) static CURLcode smb_connect(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
char *slash; char *slash;
@ -288,8 +294,9 @@ static CURLcode smb_connect(struct connectdata *conn, bool *done)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode smb_recv_message(struct connectdata *conn, void **msg) static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
char *buf = smbc->recv_buf; char *buf = smbc->recv_buf;
ssize_t bytes_read; ssize_t bytes_read;
@ -298,7 +305,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
size_t len = MAX_MESSAGE_SIZE - smbc->got; size_t len = MAX_MESSAGE_SIZE - smbc->got;
CURLcode result; CURLcode result;
result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read); result = Curl_read(data, FIRSTSOCKET, buf + smbc->got, len, &bytes_read);
if(result) if(result)
return result; return result;
@ -342,11 +349,12 @@ static void smb_pop_message(struct connectdata *conn)
smbc->got = 0; smbc->got = 0;
} }
static void smb_format_message(struct connectdata *conn, struct smb_header *h, static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
unsigned char cmd, size_t len) unsigned char cmd, size_t len)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
struct smb_request *req = conn->data->req.p.smb; struct smb_request *req = data->req.p.smb;
unsigned int pid; unsigned int pid;
memset(h, 0, sizeof(*h)); memset(h, 0, sizeof(*h));
@ -363,14 +371,15 @@ static void smb_format_message(struct connectdata *conn, struct smb_header *h,
h->pid = smb_swap16((unsigned short) pid); h->pid = smb_swap16((unsigned short) pid);
} }
static CURLcode smb_send(struct connectdata *conn, ssize_t len, static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
size_t upload_size) size_t upload_size)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written; ssize_t bytes_written;
CURLcode result; CURLcode result;
result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf, result = Curl_write(data, FIRSTSOCKET, data->state.ulbuf,
len, &bytes_written); len, &bytes_written);
if(result) if(result)
return result; return result;
@ -385,8 +394,9 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode smb_flush(struct connectdata *conn) static CURLcode smb_flush(struct Curl_easy *data)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written; ssize_t bytes_written;
ssize_t len = smbc->send_size - smbc->sent; ssize_t len = smbc->send_size - smbc->sent;
@ -395,8 +405,8 @@ static CURLcode smb_flush(struct connectdata *conn)
if(!smbc->send_size) if(!smbc->send_size)
return CURLE_OK; return CURLE_OK;
result = Curl_write(conn, FIRSTSOCKET, result = Curl_write(data, FIRSTSOCKET,
conn->data->state.ulbuf + smbc->sent, data->state.ulbuf + smbc->sent,
len, &bytes_written); len, &bytes_written);
if(result) if(result)
return result; return result;
@ -409,29 +419,30 @@ static CURLcode smb_flush(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd, static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd,
const void *msg, size_t msg_len) const void *msg, size_t msg_len)
{ {
CURLcode result = Curl_get_upload_buffer(conn->data); CURLcode result = Curl_get_upload_buffer(data);
if(result) if(result)
return result; return result;
smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf, smb_format_message(data, (struct smb_header *)data->state.ulbuf,
cmd, msg_len); cmd, msg_len);
memcpy(conn->data->state.ulbuf + sizeof(struct smb_header), memcpy(data->state.ulbuf + sizeof(struct smb_header),
msg, msg_len); msg, msg_len);
return smb_send(conn, sizeof(struct smb_header) + msg_len, 0); return smb_send(data, sizeof(struct smb_header) + msg_len, 0);
} }
static CURLcode smb_send_negotiate(struct connectdata *conn) static CURLcode smb_send_negotiate(struct Curl_easy *data)
{ {
const char *msg = "\x00\x0c\x00\x02NT LM 0.12"; const char *msg = "\x00\x0c\x00\x02NT LM 0.12";
return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15); return smb_send_message(data, SMB_COM_NEGOTIATE, msg, 15);
} }
static CURLcode smb_send_setup(struct connectdata *conn) static CURLcode smb_send_setup(struct Curl_easy *data)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
struct smb_setup msg; struct smb_setup msg;
char *p = msg.bytes; char *p = msg.bytes;
@ -446,10 +457,10 @@ static CURLcode smb_send_setup(struct connectdata *conn)
if(byte_count > sizeof(msg.bytes)) if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED; return CURLE_FILESIZE_EXCEEDED;
Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash); Curl_ntlm_core_mk_lm_hash(data, conn->passwd, lm_hash);
Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm); Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm);
#ifdef USE_NTRESPONSES #ifdef USE_NTRESPONSES
Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash); Curl_ntlm_core_mk_nt_hash(data, conn->passwd, nt_hash);
Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt); Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt);
#else #else
memset(nt, 0, sizeof(nt)); memset(nt, 0, sizeof(nt));
@ -476,13 +487,14 @@ static CURLcode smb_send_setup(struct connectdata *conn)
byte_count = p - msg.bytes; byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count); msg.byte_count = smb_swap16((unsigned short)byte_count);
return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg, return smb_send_message(data, SMB_COM_SETUP_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count); sizeof(msg) - sizeof(msg.bytes) + byte_count);
} }
static CURLcode smb_send_tree_connect(struct connectdata *conn) static CURLcode smb_send_tree_connect(struct Curl_easy *data)
{ {
struct smb_tree_connect msg; struct smb_tree_connect msg;
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
char *p = msg.bytes; char *p = msg.bytes;
@ -503,13 +515,13 @@ static CURLcode smb_send_tree_connect(struct connectdata *conn)
byte_count = p - msg.bytes; byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count); msg.byte_count = smb_swap16((unsigned short)byte_count);
return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg, return smb_send_message(data, SMB_COM_TREE_CONNECT_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count); sizeof(msg) - sizeof(msg.bytes) + byte_count);
} }
static CURLcode smb_send_open(struct connectdata *conn) static CURLcode smb_send_open(struct Curl_easy *data)
{ {
struct smb_request *req = conn->data->req.p.smb; struct smb_request *req = data->req.p.smb;
struct smb_nt_create msg; struct smb_nt_create msg;
size_t byte_count; size_t byte_count;
@ -522,7 +534,7 @@ static CURLcode smb_send_open(struct connectdata *conn)
byte_count = strlen(req->path); byte_count = strlen(req->path);
msg.name_length = smb_swap16((unsigned short)byte_count); msg.name_length = smb_swap16((unsigned short)byte_count);
msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
if(conn->data->set.upload) { if(data->set.upload) {
msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
} }
@ -533,35 +545,35 @@ static CURLcode smb_send_open(struct connectdata *conn)
msg.byte_count = smb_swap16((unsigned short) ++byte_count); msg.byte_count = smb_swap16((unsigned short) ++byte_count);
strcpy(msg.bytes, req->path); strcpy(msg.bytes, req->path);
return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg, return smb_send_message(data, SMB_COM_NT_CREATE_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count); sizeof(msg) - sizeof(msg.bytes) + byte_count);
} }
static CURLcode smb_send_close(struct connectdata *conn) static CURLcode smb_send_close(struct Curl_easy *data)
{ {
struct smb_request *req = conn->data->req.p.smb; struct smb_request *req = data->req.p.smb;
struct smb_close msg; struct smb_close msg;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
msg.word_count = SMB_WC_CLOSE; msg.word_count = SMB_WC_CLOSE;
msg.fid = smb_swap16(req->fid); msg.fid = smb_swap16(req->fid);
return smb_send_message(conn, SMB_COM_CLOSE, &msg, sizeof(msg)); return smb_send_message(data, SMB_COM_CLOSE, &msg, sizeof(msg));
} }
static CURLcode smb_send_tree_disconnect(struct connectdata *conn) static CURLcode smb_send_tree_disconnect(struct Curl_easy *data)
{ {
struct smb_tree_disconnect msg; struct smb_tree_disconnect msg;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg)); return smb_send_message(data, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
} }
static CURLcode smb_send_read(struct connectdata *conn) static CURLcode smb_send_read(struct Curl_easy *data)
{ {
struct smb_request *req = conn->data->req.p.smb; struct smb_request *req = data->req.p.smb;
curl_off_t offset = conn->data->req.offset; curl_off_t offset = data->req.offset;
struct smb_read msg; struct smb_read msg;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
@ -573,19 +585,19 @@ static CURLcode smb_send_read(struct connectdata *conn)
msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE); msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE); msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg)); return smb_send_message(data, SMB_COM_READ_ANDX, &msg, sizeof(msg));
} }
static CURLcode smb_send_write(struct connectdata *conn) static CURLcode smb_send_write(struct Curl_easy *data)
{ {
struct smb_write *msg; struct smb_write *msg;
struct smb_request *req = conn->data->req.p.smb; struct smb_request *req = data->req.p.smb;
curl_off_t offset = conn->data->req.offset; curl_off_t offset = data->req.offset;
curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount; curl_off_t upload_size = data->req.size - data->req.bytecount;
CURLcode result = Curl_get_upload_buffer(conn->data); CURLcode result = Curl_get_upload_buffer(data);
if(result) if(result)
return result; return result;
msg = (struct smb_write *)conn->data->state.ulbuf; msg = (struct smb_write *)data->state.ulbuf;
if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */ if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
upload_size = MAX_PAYLOAD_SIZE - 1; upload_size = MAX_PAYLOAD_SIZE - 1;
@ -600,24 +612,25 @@ static CURLcode smb_send_write(struct connectdata *conn)
msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int)); msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int));
msg->byte_count = smb_swap16((unsigned short) (upload_size + 1)); msg->byte_count = smb_swap16((unsigned short) (upload_size + 1));
smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX, smb_format_message(data, &msg->h, SMB_COM_WRITE_ANDX,
sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size); sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size);
return smb_send(conn, sizeof(*msg), (size_t) upload_size); return smb_send(data, sizeof(*msg), (size_t) upload_size);
} }
static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
CURLcode result; CURLcode result;
*msg = NULL; /* if it returns early */ *msg = NULL; /* if it returns early */
/* Check if there is data in the transfer buffer */ /* Check if there is data in the transfer buffer */
if(!smbc->send_size && smbc->upload_size) { if(!smbc->send_size && smbc->upload_size) {
size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ? size_t nread = smbc->upload_size > data->set.upload_buffer_size ?
conn->data->set.upload_buffer_size : data->set.upload_buffer_size :
smbc->upload_size; smbc->upload_size;
conn->data->req.upload_fromhere = conn->data->state.ulbuf; data->req.upload_fromhere = data->state.ulbuf;
result = Curl_fillreadbuffer(conn, nread, &nread); result = Curl_fillreadbuffer(conn, nread, &nread);
if(result && result != CURLE_AGAIN) if(result && result != CURLE_AGAIN)
return result; return result;
@ -631,7 +644,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
/* Check if there is data to send */ /* Check if there is data to send */
if(smbc->send_size) { if(smbc->send_size) {
result = smb_flush(conn); result = smb_flush(data);
if(result) if(result)
return result; return result;
} }
@ -640,11 +653,12 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
if(smbc->send_size || smbc->upload_size) if(smbc->send_size || smbc->upload_size)
return CURLE_AGAIN; return CURLE_AGAIN;
return smb_recv_message(conn, msg); return smb_recv_message(data, msg);
} }
static CURLcode smb_connection_state(struct connectdata *conn, bool *done) static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
struct smb_negotiate_response *nrsp; struct smb_negotiate_response *nrsp;
struct smb_header *h; struct smb_header *h;
@ -663,17 +677,17 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
} }
#endif #endif
result = smb_send_negotiate(conn); result = smb_send_negotiate(data);
if(result) { if(result) {
connclose(conn, "SMB: failed to send negotiate message"); connclose(conn, "SMB: failed to send negotiate message");
return result; return result;
} }
conn_state(conn, SMB_NEGOTIATE); conn_state(data, SMB_NEGOTIATE);
} }
/* Send the previous message and check for a response */ /* Send the previous message and check for a response */
result = smb_send_and_recv(conn, &msg); result = smb_send_and_recv(data, &msg);
if(result && result != CURLE_AGAIN) { if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate"); connclose(conn, "SMB: failed to communicate");
return result; return result;
@ -694,12 +708,12 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
nrsp = msg; nrsp = msg;
memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge)); memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge));
smbc->session_key = smb_swap32(nrsp->session_key); smbc->session_key = smb_swap32(nrsp->session_key);
result = smb_send_setup(conn); result = smb_send_setup(data);
if(result) { if(result) {
connclose(conn, "SMB: failed to send setup message"); connclose(conn, "SMB: failed to send setup message");
return result; return result;
} }
conn_state(conn, SMB_SETUP); conn_state(data, SMB_SETUP);
break; break;
case SMB_SETUP: case SMB_SETUP:
@ -708,7 +722,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
} }
smbc->uid = smb_swap16(h->uid); smbc->uid = smb_swap16(h->uid);
conn_state(conn, SMB_CONNECTED); conn_state(data, SMB_CONNECTED);
*done = true; *done = true;
break; break;
@ -740,9 +754,10 @@ static void get_posix_time(time_t *out, curl_off_t timestamp)
*out = (time_t) timestamp; *out = (time_t) timestamp;
} }
static CURLcode smb_request_state(struct connectdata *conn, bool *done) static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
{ {
struct smb_request *req = conn->data->req.p.smb; struct connectdata *conn = data->conn;
struct smb_request *req = data->req.p.smb;
struct smb_header *h; struct smb_header *h;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
enum smb_req_state next_state = SMB_DONE; enum smb_req_state next_state = SMB_DONE;
@ -754,17 +769,17 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
/* Start the request */ /* Start the request */
if(req->state == SMB_REQUESTING) { if(req->state == SMB_REQUESTING) {
result = smb_send_tree_connect(conn); result = smb_send_tree_connect(data);
if(result) { if(result) {
connclose(conn, "SMB: failed to send tree connect message"); connclose(conn, "SMB: failed to send tree connect message");
return result; return result;
} }
request_state(conn, SMB_TREE_CONNECT); request_state(data, SMB_TREE_CONNECT);
} }
/* Send the previous message and check for a response */ /* Send the previous message and check for a response */
result = smb_send_and_recv(conn, &msg); result = smb_send_and_recv(data, &msg);
if(result && result != CURLE_AGAIN) { if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate"); connclose(conn, "SMB: failed to communicate");
return result; return result;
@ -797,23 +812,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
} }
smb_m = (const struct smb_nt_create_response*) msg; smb_m = (const struct smb_nt_create_response*) msg;
req->fid = smb_swap16(smb_m->fid); req->fid = smb_swap16(smb_m->fid);
conn->data->req.offset = 0; data->req.offset = 0;
if(conn->data->set.upload) { if(data->set.upload) {
conn->data->req.size = conn->data->state.infilesize; data->req.size = data->state.infilesize;
Curl_pgrsSetUploadSize(conn->data, conn->data->req.size); Curl_pgrsSetUploadSize(data, data->req.size);
next_state = SMB_UPLOAD; next_state = SMB_UPLOAD;
} }
else { else {
smb_m = (const struct smb_nt_create_response*) msg; smb_m = (const struct smb_nt_create_response*) msg;
conn->data->req.size = smb_swap64(smb_m->end_of_file); data->req.size = smb_swap64(smb_m->end_of_file);
if(conn->data->req.size < 0) { if(data->req.size < 0) {
req->result = CURLE_WEIRD_SERVER_REPLY; req->result = CURLE_WEIRD_SERVER_REPLY;
next_state = SMB_CLOSE; next_state = SMB_CLOSE;
} }
else { else {
Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size); Curl_pgrsSetDownloadSize(data, data->req.size);
if(conn->data->set.get_filetime) if(data->set.get_filetime)
get_posix_time(&conn->data->info.filetime, smb_m->last_change_time); get_posix_time(&data->info.filetime, smb_m->last_change_time);
next_state = SMB_DOWNLOAD; next_state = SMB_DOWNLOAD;
} }
} }
@ -831,11 +846,11 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
sizeof(struct smb_header) + 13); sizeof(struct smb_header) + 13);
if(len > 0) { if(len > 0) {
if(off + sizeof(unsigned int) + len > smbc->got) { if(off + sizeof(unsigned int) + len > smbc->got) {
failf(conn->data, "Invalid input packet"); failf(data, "Invalid input packet");
result = CURLE_RECV_ERROR; result = CURLE_RECV_ERROR;
} }
else else
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)msg + off + sizeof(unsigned int), (char *)msg + off + sizeof(unsigned int),
len); len);
if(result) { if(result) {
@ -844,9 +859,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break; break;
} }
} }
conn->data->req.bytecount += len; data->req.bytecount += len;
conn->data->req.offset += len; data->req.offset += len;
Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount); Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break; break;
@ -858,10 +873,10 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
} }
len = Curl_read16_le(((const unsigned char *) msg) + len = Curl_read16_le(((const unsigned char *) msg) +
sizeof(struct smb_header) + 5); sizeof(struct smb_header) + 5);
conn->data->req.bytecount += len; data->req.bytecount += len;
conn->data->req.offset += len; data->req.offset += len;
Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount); Curl_pgrsSetUploadCounter(data, data->req.bytecount);
if(conn->data->req.bytecount >= conn->data->req.size) if(data->req.bytecount >= data->req.size)
next_state = SMB_CLOSE; next_state = SMB_CLOSE;
else else
next_state = SMB_UPLOAD; next_state = SMB_UPLOAD;
@ -885,23 +900,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
switch(next_state) { switch(next_state) {
case SMB_OPEN: case SMB_OPEN:
result = smb_send_open(conn); result = smb_send_open(data);
break; break;
case SMB_DOWNLOAD: case SMB_DOWNLOAD:
result = smb_send_read(conn); result = smb_send_read(data);
break; break;
case SMB_UPLOAD: case SMB_UPLOAD:
result = smb_send_write(conn); result = smb_send_write(data);
break; break;
case SMB_CLOSE: case SMB_CLOSE:
result = smb_send_close(conn); result = smb_send_close(data);
break; break;
case SMB_TREE_DISCONNECT: case SMB_TREE_DISCONNECT:
result = smb_send_tree_disconnect(conn); result = smb_send_tree_disconnect(data);
break; break;
case SMB_DONE: case SMB_DONE:
@ -918,37 +933,42 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
return result; return result;
} }
request_state(conn, next_state); request_state(data, next_state);
return CURLE_OK; return CURLE_OK;
} }
static CURLcode smb_done(struct connectdata *conn, CURLcode status, static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
(void) premature; (void) premature;
Curl_safefree(conn->data->req.p.smb); Curl_safefree(data->req.p.smb);
return status; return status;
} }
static CURLcode smb_disconnect(struct connectdata *conn, bool dead) static CURLcode smb_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead)
{ {
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
(void) dead; (void) dead;
(void) data;
Curl_safefree(smbc->share); Curl_safefree(smbc->share);
Curl_safefree(smbc->domain); Curl_safefree(smbc->domain);
Curl_safefree(smbc->recv_buf); Curl_safefree(smbc->recv_buf);
return CURLE_OK; return CURLE_OK;
} }
static int smb_getsock(struct connectdata *conn, curl_socket_t *socks) static int smb_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{ {
(void)data;
socks[0] = conn->sock[FIRSTSOCKET]; socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0); return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
} }
static CURLcode smb_do(struct connectdata *conn, bool *done) static CURLcode smb_do(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
*done = FALSE; *done = FALSE;
@ -958,9 +978,9 @@ static CURLcode smb_do(struct connectdata *conn, bool *done)
return CURLE_URL_MALFORMAT; return CURLE_URL_MALFORMAT;
} }
static CURLcode smb_parse_url_path(struct connectdata *conn) static CURLcode smb_parse_url_path(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct Curl_easy *data = conn->data;
struct smb_request *req = data->req.p.smb; struct smb_request *req = data->req.p.smb;
struct smb_conn *smbc = &conn->proto.smbc; struct smb_conn *smbc = &conn->proto.smbc;
char *path; char *path;

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2009 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -91,6 +91,6 @@ extern const struct Curl_handler Curl_handler_smtps;
#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e" #define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
#define SMTP_EOB_REPL_LEN 4 #define SMTP_EOB_REPL_LEN 4
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread); CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread);
#endif /* HEADER_CURL_SMTP_H */ #endif /* HEADER_CURL_SMTP_H */

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -357,7 +357,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
/* FALLTHROUGH */ /* FALLTHROUGH */
case CONNECT_REQ_SENDING: case CONNECT_REQ_SENDING:
/* Send request */ /* Send request */
result = Curl_write_plain(conn, sockfd, (char *)sx->outp, result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written); sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) { if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS4 connect request."); failf(data, "Failed to send SOCKS4 connect request.");
@ -561,7 +561,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
/* write the number of authentication methods */ /* write the number of authentication methods */
socksreq[1] = (unsigned char) (idx - 2); socksreq[1] = (unsigned char) (idx - 2);
result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written); result = Curl_write_plain(data, sockfd, (char *)socksreq, idx, &written);
if(result && (CURLE_AGAIN != result)) { if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to send initial SOCKS5 request."); failf(data, "Unable to send initial SOCKS5 request.");
return CURLPX_SEND_CONNECT; return CURLPX_SEND_CONNECT;
@ -575,7 +575,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
sxstate(conn, CONNECT_SOCKS_READ); sxstate(conn, CONNECT_SOCKS_READ);
goto CONNECT_SOCKS_READ_INIT; goto CONNECT_SOCKS_READ_INIT;
case CONNECT_SOCKS_SEND: case CONNECT_SOCKS_SEND:
result = Curl_write_plain(conn, sockfd, (char *)sx->outp, result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written); sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) { if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to send initial SOCKS5 request."); failf(data, "Unable to send initial SOCKS5 request.");
@ -707,7 +707,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case CONNECT_AUTH_SEND: case CONNECT_AUTH_SEND:
result = Curl_write_plain(conn, sockfd, (char *)sx->outp, result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written); sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) { if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS5 sub-negotiation request."); failf(data, "Failed to send SOCKS5 sub-negotiation request.");
@ -881,7 +881,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
sxstate(conn, CONNECT_REQ_SENDING); sxstate(conn, CONNECT_REQ_SENDING);
/* FALLTHROUGH */ /* FALLTHROUGH */
case CONNECT_REQ_SENDING: case CONNECT_REQ_SENDING:
result = Curl_write_plain(conn, sockfd, (char *)sx->outp, result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written); sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) { if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS5 connect request."); failf(data, "Failed to send SOCKS5 connect request.");

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com> * Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
@ -201,7 +201,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
us_length = htons((short)gss_send_token.length); us_length = htons((short)gss_send_token.length);
memcpy(socksreq + 2, &us_length, sizeof(short)); memcpy(socksreq + 2, &us_length, sizeof(short));
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) { if(code || (4 != written)) {
failf(data, "Failed to send GSS-API authentication request."); failf(data, "Failed to send GSS-API authentication request.");
gss_release_name(&gss_status, &server); gss_release_name(&gss_status, &server);
@ -211,7 +211,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
code = Curl_write_plain(conn, sock, (char *)gss_send_token.value, code = Curl_write_plain(data, sock, (char *)gss_send_token.value,
gss_send_token.length, &written); gss_send_token.length, &written);
if(code || ((ssize_t)gss_send_token.length != written)) { if(code || ((ssize_t)gss_send_token.length != written)) {
@ -408,7 +408,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
memcpy(socksreq + 2, &us_length, sizeof(short)); memcpy(socksreq + 2, &us_length, sizeof(short));
} }
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) { if(code || (4 != written)) {
failf(data, "Failed to send GSS-API encryption request."); failf(data, "Failed to send GSS-API encryption request.");
gss_release_buffer(&gss_status, &gss_w_token); gss_release_buffer(&gss_status, &gss_w_token);
@ -418,7 +418,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(data->set.socks5_gssapi_nec) { if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1); memcpy(socksreq, &gss_enc, 1);
code = Curl_write_plain(conn, sock, socksreq, 1, &written); code = Curl_write_plain(data, sock, socksreq, 1, &written);
if(code || ( 1 != written)) { if(code || ( 1 != written)) {
failf(data, "Failed to send GSS-API encryption type."); failf(data, "Failed to send GSS-API encryption type.");
gss_delete_sec_context(&gss_status, &gss_context, NULL); gss_delete_sec_context(&gss_status, &gss_context, NULL);
@ -426,7 +426,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
} }
} }
else { else {
code = Curl_write_plain(conn, sock, (char *)gss_w_token.value, code = Curl_write_plain(data, sock, (char *)gss_w_token.value,
gss_w_token.length, &written); gss_w_token.length, &written);
if(code || ((ssize_t)gss_w_token.length != written)) { if(code || ((ssize_t)gss_w_token.length != written)) {
failf(data, "Failed to send GSS-API encryption type."); failf(data, "Failed to send GSS-API encryption type.");

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com> * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
@ -204,7 +204,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
us_length = htons((short)sspi_send_token.cbBuffer); us_length = htons((short)sspi_send_token.cbBuffer);
memcpy(socksreq + 2, &us_length, sizeof(short)); memcpy(socksreq + 2, &us_length, sizeof(short));
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) { if(code || (4 != written)) {
failf(data, "Failed to send SSPI authentication request."); failf(data, "Failed to send SSPI authentication request.");
free(service_name); free(service_name);
@ -217,7 +217,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
sspi_send_token.cbBuffer, &written); sspi_send_token.cbBuffer, &written);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) { if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI authentication token."); failf(data, "Failed to send SSPI authentication token.");
@ -466,7 +466,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
memcpy(socksreq + 2, &us_length, sizeof(short)); memcpy(socksreq + 2, &us_length, sizeof(short));
} }
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) { if(code || (4 != written)) {
failf(data, "Failed to send SSPI encryption request."); failf(data, "Failed to send SSPI encryption request.");
if(sspi_send_token.pvBuffer) if(sspi_send_token.pvBuffer)
@ -477,7 +477,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(data->set.socks5_gssapi_nec) { if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1); memcpy(socksreq, &gss_enc, 1);
code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); code = Curl_write_plain(data, sock, (char *)socksreq, 1, &written);
if(code || (1 != written)) { if(code || (1 != written)) {
failf(data, "Failed to send SSPI encryption type."); failf(data, "Failed to send SSPI encryption type.");
s_pSecFn->DeleteSecurityContext(&sspi_context); s_pSecFn->DeleteSecurityContext(&sspi_context);
@ -485,7 +485,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
} }
} }
else { else {
code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
sspi_send_token.cbBuffer, &written); sspi_send_token.cbBuffer, &written);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) { if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI encryption type."); failf(data, "Failed to send SSPI encryption type.");

View file

@ -111,10 +111,10 @@ static void printsub(struct Curl_easy *data,
static void suboption(struct connectdata *); static void suboption(struct connectdata *);
static void sendsuboption(struct connectdata *conn, int option); static void sendsuboption(struct connectdata *conn, int option);
static CURLcode telnet_do(struct connectdata *conn, bool *done); static CURLcode telnet_do(struct Curl_easy *data, bool *done);
static CURLcode telnet_done(struct connectdata *conn, static CURLcode telnet_done(struct Curl_easy *data,
CURLcode, bool premature); CURLcode, bool premature);
static CURLcode send_telnet_data(struct connectdata *conn, static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread); char *buffer, ssize_t nread);
/* For negotiation compliant to RFC 1143 */ /* For negotiation compliant to RFC 1143 */
@ -995,7 +995,7 @@ static void sendsuboption(struct connectdata *conn, int option)
} }
/* ... then the window size with the send_telnet_data() function /* ... then the window size with the send_telnet_data() function
to deal with 0xFF cases ... */ to deal with 0xFF cases ... */
send_telnet_data(conn, (char *)tn->subbuffer + 3, 4); send_telnet_data(data, (char *)tn->subbuffer + 3, 4);
/* ... and the footer */ /* ... and the footer */
bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2); bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2);
if(bytes_written < 0) { if(bytes_written < 0) {
@ -1021,7 +1021,7 @@ CURLcode telrcv(struct connectdata *conn,
#define startskipping() \ #define startskipping() \
if(startwrite >= 0) { \ if(startwrite >= 0) { \
result = Curl_client_write(conn, \ result = Curl_client_write(data, \
CLIENTWRITE_BODY, \ CLIENTWRITE_BODY, \
(char *)&inbuf[startwrite], \ (char *)&inbuf[startwrite], \
in-startwrite); \ in-startwrite); \
@ -1171,13 +1171,14 @@ CURLcode telrcv(struct connectdata *conn,
} }
/* Escape and send a telnet data block */ /* Escape and send a telnet data block */
static CURLcode send_telnet_data(struct connectdata *conn, static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread) char *buffer, ssize_t nread)
{ {
ssize_t escapes, i, outlen; ssize_t escapes, i, outlen;
unsigned char *outbuf = NULL; unsigned char *outbuf = NULL;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
ssize_t bytes_written, total_written; ssize_t bytes_written, total_written;
struct connectdata *conn = data->conn;
/* Determine size of new buffer after escaping */ /* Determine size of new buffer after escaping */
escapes = 0; escapes = 0;
@ -1216,7 +1217,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
break; break;
default: /* write! */ default: /* write! */
bytes_written = 0; bytes_written = 0;
result = Curl_write(conn, conn->sock[FIRSTSOCKET], result = Curl_write(data, conn->sock[FIRSTSOCKET],
outbuf + total_written, outbuf + total_written,
outlen - total_written, outlen - total_written,
&bytes_written); &bytes_written);
@ -1232,9 +1233,10 @@ static CURLcode send_telnet_data(struct connectdata *conn,
return result; return result;
} }
static CURLcode telnet_done(struct connectdata *conn, static CURLcode telnet_done(struct Curl_easy *data,
CURLcode status, bool premature) CURLcode status, bool premature)
{ {
struct connectdata *conn = data->conn;
struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet; struct TELNET *tn = (struct TELNET *)conn->data->req.p.telnet;
(void)status; /* unused */ (void)status; /* unused */
(void)premature; /* not used */ (void)premature; /* not used */
@ -1250,10 +1252,10 @@ static CURLcode telnet_done(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode telnet_do(struct connectdata *conn, bool *done) static CURLcode telnet_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result; CURLcode result;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WSAEVENT event_handle; WSAEVENT event_handle;
@ -1378,7 +1380,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
} }
} }
result = send_telnet_data(conn, buf, readfile_read); result = send_telnet_data(data, buf, readfile_read);
if(result) { if(result) {
keepon = FALSE; keepon = FALSE;
break; break;
@ -1396,7 +1398,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break; break;
} }
result = send_telnet_data(conn, buf, readfile_read); result = send_telnet_data(data, buf, readfile_read);
if(result) { if(result) {
keepon = FALSE; keepon = FALSE;
break; break;
@ -1418,7 +1420,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
} }
if(events.lNetworkEvents & FD_READ) { if(events.lNetworkEvents & FD_READ) {
/* read data from network */ /* read data from network */
result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */ /* read would've blocked. Loop again */
if(result == CURLE_AGAIN) if(result == CURLE_AGAIN)
break; break;
@ -1498,7 +1500,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
default: /* read! */ default: /* read! */
if(pfd[0].revents & POLLIN) { if(pfd[0].revents & POLLIN) {
/* read data from network */ /* read data from network */
result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */ /* read would've blocked. Loop again */
if(result == CURLE_AGAIN) if(result == CURLE_AGAIN)
break; break;
@ -1550,7 +1552,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
} }
if(nread > 0) { if(nread > 0) {
result = send_telnet_data(conn, buf, nread); result = send_telnet_data(data, buf, nread);
if(result) { if(result) {
keepon = FALSE; keepon = FALSE;
break; break;

View file

@ -124,7 +124,7 @@ struct tftp_state_data {
tftp_mode_t mode; tftp_mode_t mode;
tftp_error_t error; tftp_error_t error;
tftp_event_t event; tftp_event_t event;
struct connectdata *conn; struct Curl_easy *data;
curl_socket_t sockfd; curl_socket_t sockfd;
int retries; int retries;
int retry_time; int retry_time;
@ -148,16 +148,19 @@ struct tftp_state_data {
/* Forward declarations */ /* Forward declarations */
static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event); static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event); static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_connect(struct connectdata *conn, bool *done); static CURLcode tftp_connect(struct Curl_easy *data, bool *done);
static CURLcode tftp_disconnect(struct connectdata *conn, static CURLcode tftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection); bool dead_connection);
static CURLcode tftp_do(struct connectdata *conn, bool *done); static CURLcode tftp_do(struct Curl_easy *data, bool *done);
static CURLcode tftp_done(struct connectdata *conn, static CURLcode tftp_done(struct Curl_easy *data,
CURLcode, bool premature); CURLcode, bool premature);
static CURLcode tftp_setup_connection(struct connectdata *conn); static CURLcode tftp_setup_connection(struct Curl_easy *data,
static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done); struct connectdata *conn);
static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done); static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done);
static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks); static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done);
static int tftp_getsock(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks);
static CURLcode tftp_translate_code(tftp_error_t error); static CURLcode tftp_translate_code(tftp_error_t error);
@ -206,11 +209,11 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
time(&state->start_time); time(&state->start_time);
/* Compute drop-dead time */ /* Compute drop-dead time */
timeout_ms = Curl_timeleft(state->conn->data, NULL, start); timeout_ms = Curl_timeleft(state->data, NULL, start);
if(timeout_ms < 0) { if(timeout_ms < 0) {
/* time-out, bail out, go home */ /* time-out, bail out, go home */
failf(state->conn->data, "Connection time-out"); failf(state->data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT; return CURLE_OPERATION_TIMEDOUT;
} }
@ -261,7 +264,7 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
if(state->retry_time<1) if(state->retry_time<1)
state->retry_time = 1; state->retry_time = 1;
infof(state->conn->data, infof(state->data,
"set timeouts for state %d; Total %ld, retry %d maxtry %d\n", "set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
(int)state->state, (long)(state->max_time-state->start_time), (int)state->state, (long)(state->max_time-state->start_time),
state->retry_time, state->retry_max); state->retry_time, state->retry_max);
@ -335,7 +338,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
const char *ptr, int len) const char *ptr, int len)
{ {
const char *tmp = ptr; const char *tmp = ptr;
struct Curl_easy *data = state->conn->data; struct Curl_easy *data = state->data;
/* if OACK doesn't contain blksize option, the default (512) must be used */ /* if OACK doesn't contain blksize option, the default (512) must be used */
state->blksize = TFTP_BLKSIZE_DEFAULT; state->blksize = TFTP_BLKSIZE_DEFAULT;
@ -419,7 +422,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
{ {
CURLcode result; CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS #ifndef CURL_DISABLE_VERBOSE_STRINGS
struct Curl_easy *data = state->conn->data; struct Curl_easy *data = state->data;
infof(data, "%s\n", "Connected for transmit"); infof(data, "%s\n", "Connected for transmit");
#endif #endif
@ -435,7 +438,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
{ {
CURLcode result; CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS #ifndef CURL_DISABLE_VERBOSE_STRINGS
struct Curl_easy *data = state->conn->data; struct Curl_easy *data = state->data;
infof(data, "%s\n", "Connected for receive"); infof(data, "%s\n", "Connected for receive");
#endif #endif
@ -453,7 +456,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
ssize_t senddata; ssize_t senddata;
const char *mode = "octet"; const char *mode = "octet";
char *filename; char *filename;
struct Curl_easy *data = state->conn->data; struct Curl_easy *data = state->data;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
/* Set ascii mode if -B flag was used */ /* Set ascii mode if -B flag was used */
@ -475,7 +478,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
if(data->set.upload) { if(data->set.upload) {
/* If we are uploading, send an WRQ */ /* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ); setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
state->conn->data->req.upload_fromhere = state->data->req.upload_fromhere =
(char *)state->spacket.data + 4; (char *)state->spacket.data + 4;
if(data->state.infilesize != -1) if(data->state.infilesize != -1)
Curl_pgrsSetUploadSize(data, data->state.infilesize); Curl_pgrsSetUploadSize(data, data->state.infilesize);
@ -487,7 +490,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
/* As RFC3617 describes the separator slash is not actually part of the /* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path file name so we skip the always-present first letter of the path
string. */ string. */
result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0, result = Curl_urldecode(data, &state->data->state.up.path[1], 0,
&filename, NULL, REJECT_ZERO); &filename, NULL, REJECT_ZERO);
if(result) if(result)
return result; return result;
@ -551,8 +554,8 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
not have a size_t argument, like older unixes that want an 'int' */ not have a size_t argument, like older unixes that want an 'int' */
senddata = sendto(state->sockfd, (void *)state->spacket.data, senddata = sendto(state->sockfd, (void *)state->spacket.data,
(SEND_TYPE_ARG3)sbytes, 0, (SEND_TYPE_ARG3)sbytes, 0,
state->conn->ip_addr->ai_addr, data->conn->ip_addr->ai_addr,
state->conn->ip_addr->ai_addrlen); data->conn->ip_addr->ai_addrlen);
if(senddata != (ssize_t)sbytes) { if(senddata != (ssize_t)sbytes) {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
@ -582,7 +585,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
break; break;
default: default:
failf(state->conn->data, "tftp_send_first: internal error"); failf(state->data, "tftp_send_first: internal error");
break; break;
} }
@ -605,7 +608,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
{ {
ssize_t sbytes; ssize_t sbytes;
int rblock; int rblock;
struct Curl_easy *data = state->conn->data; struct Curl_easy *data = state->data;
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
switch(event) { switch(event) {
@ -725,7 +728,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
**********************************************************/ **********************************************************/
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
{ {
struct Curl_easy *data = state->conn->data; struct Curl_easy *data = state->data;
ssize_t sbytes; ssize_t sbytes;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
@ -794,14 +797,14 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
* data block. * data block.
* */ * */
state->sbytes = 0; state->sbytes = 0;
state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4; state->data->req.upload_fromhere = (char *)state->spacket.data + 4;
do { do {
result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes, result = Curl_fillreadbuffer(data->conn, state->blksize - state->sbytes,
&cb); &cb);
if(result) if(result)
return result; return result;
state->sbytes += (int)cb; state->sbytes += (int)cb;
state->conn->data->req.upload_fromhere += cb; state->data->req.upload_fromhere += cb;
} while(state->sbytes < state->blksize && cb != 0); } while(state->sbytes < state->blksize && cb != 0);
sbytes = sendto(state->sockfd, (void *) state->spacket.data, sbytes = sendto(state->sockfd, (void *) state->spacket.data,
@ -927,7 +930,7 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
tftp_event_t event) tftp_event_t event)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = state->conn->data; struct Curl_easy *data = state->data;
switch(state->state) { switch(state->state) {
case TFTP_STATE_START: case TFTP_STATE_START:
@ -962,9 +965,11 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
* The disconnect callback * The disconnect callback
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) static CURLcode tftp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{ {
struct tftp_state_data *state = conn->proto.tftpc; struct tftp_state_data *state = conn->proto.tftpc;
(void) data;
(void) dead_connection; (void) dead_connection;
/* done, free dynamically allocated pkt buffers */ /* done, free dynamically allocated pkt buffers */
@ -984,11 +989,12 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
* The connect callback * The connect callback
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_connect(struct connectdata *conn, bool *done) static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
{ {
struct tftp_state_data *state; struct tftp_state_data *state;
int blksize; int blksize;
int need_blksize; int need_blksize;
struct connectdata *conn = data->conn;
blksize = TFTP_BLKSIZE_DEFAULT; blksize = TFTP_BLKSIZE_DEFAULT;
@ -997,8 +1003,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* alloc pkt buffers based on specified blksize */ /* alloc pkt buffers based on specified blksize */
if(conn->data->set.tftp_blksize) { if(data->set.tftp_blksize) {
blksize = (int)conn->data->set.tftp_blksize; blksize = (int)data->set.tftp_blksize;
if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN) if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
return CURLE_TFTP_ILLEGAL; return CURLE_TFTP_ILLEGAL;
} }
@ -1026,8 +1032,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
* little gain for UDP */ * little gain for UDP */
connclose(conn, "TFTP"); connclose(conn, "TFTP");
state->conn = conn; state->data = data;
state->sockfd = state->conn->sock[FIRSTSOCKET]; state->sockfd = conn->sock[FIRSTSOCKET];
state->state = TFTP_STATE_START; state->state = TFTP_STATE_START;
state->error = TFTP_ERR_NONE; state->error = TFTP_ERR_NONE;
state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */ state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */
@ -1056,14 +1062,14 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
conn->ip_addr->ai_addrlen); conn->ip_addr->ai_addrlen);
if(rc) { if(rc) {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
failf(conn->data, "bind() failed; %s", failf(data, "bind() failed; %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
conn->bits.bound = TRUE; conn->bits.bound = TRUE;
} }
Curl_pgrsStartNow(conn->data); Curl_pgrsStartNow(data);
*done = TRUE; *done = TRUE;
@ -1077,10 +1083,11 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
* The done callback * The done callback
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_done(struct connectdata *conn, CURLcode status, static CURLcode tftp_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc; struct tftp_state_data *state = conn->proto.tftpc;
(void)status; /* unused */ (void)status; /* unused */
@ -1103,8 +1110,10 @@ static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
* The getsock callback * The getsock callback
* *
**********************************************************/ **********************************************************/
static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks) static int tftp_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{ {
(void)data;
socks[0] = conn->sock[FIRSTSOCKET]; socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0); return GETSOCK_READSOCK(0);
} }
@ -1116,12 +1125,12 @@ static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks)
* Called once select fires and data is ready on the socket * Called once select fires and data is ready on the socket
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_receive_packet(struct connectdata *conn) static CURLcode tftp_receive_packet(struct Curl_easy *data)
{ {
struct Curl_sockaddr_storage fromaddr; struct Curl_sockaddr_storage fromaddr;
curl_socklen_t fromlen; curl_socklen_t fromlen;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc; struct tftp_state_data *state = conn->proto.tftpc;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
@ -1154,7 +1163,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
/* Don't pass to the client empty or retransmitted packets */ /* Don't pass to the client empty or retransmitted packets */
if(state->rbytes > 4 && if(state->rbytes > 4 &&
(NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)state->rpacket.data + 4, (char *)state->rpacket.data + 4,
state->rbytes-4); state->rbytes-4);
if(result) { if(result) {
@ -1207,9 +1216,10 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
* Check if timeouts have been reached * Check if timeouts have been reached
* *
**********************************************************/ **********************************************************/
static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) static long tftp_state_timeout(struct Curl_easy *data, tftp_event_t *event)
{ {
time_t current; time_t current;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc; struct tftp_state_data *state = conn->proto.tftpc;
if(event) if(event)
@ -1217,7 +1227,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
time(&current); time(&current);
if(current > state->max_time) { if(current > state->max_time) {
DEBUGF(infof(conn->data, "timeout: %ld > %ld\n", DEBUGF(infof(data, "timeout: %ld > %ld\n",
(long)current, (long)state->max_time)); (long)current, (long)state->max_time));
state->error = TFTP_ERR_TIMEOUT; state->error = TFTP_ERR_TIMEOUT;
state->state = TFTP_STATE_FIN; state->state = TFTP_STATE_FIN;
@ -1242,13 +1252,13 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
* Handle single RX socket event and return * Handle single RX socket event and return
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
{ {
tftp_event_t event; tftp_event_t event;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc; struct tftp_state_data *state = conn->proto.tftpc;
long timeout_ms = tftp_state_timeout(conn, &event); long timeout_ms = tftp_state_timeout(data, &event);
*done = FALSE; *done = FALSE;
@ -1277,7 +1287,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
state->event = TFTP_EVENT_ERROR; state->event = TFTP_EVENT_ERROR;
} }
else if(rc != 0) { else if(rc != 0) {
result = tftp_receive_packet(conn); result = tftp_receive_packet(data);
if(result) if(result)
return result; return result;
result = tftp_state_machine(state, state->event); result = tftp_state_machine(state, state->event);
@ -1301,22 +1311,22 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
* Called from multi.c while DOing * Called from multi.c while DOing
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done)
{ {
CURLcode result; CURLcode result;
result = tftp_multi_statemach(conn, dophase_done); result = tftp_multi_statemach(data, dophase_done);
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
else if(!result) { else if(!result) {
/* The multi code doesn't have this logic for the DOING state so we /* The multi code doesn't have this logic for the DOING state so we
provide it for TFTP since it may do the entire transfer in this provide it for TFTP since it may do the entire transfer in this
state. */ state. */
if(Curl_pgrsUpdate(conn)) if(Curl_pgrsUpdate(data->conn))
result = CURLE_ABORTED_BY_CALLBACK; result = CURLE_ABORTED_BY_CALLBACK;
else else
result = Curl_speedcheck(conn->data, Curl_now()); result = Curl_speedcheck(data, Curl_now());
} }
return result; return result;
} }
@ -1328,9 +1338,10 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
* Entry point for transfer from tftp_do, sarts state mach * Entry point for transfer from tftp_do, sarts state mach
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc; struct tftp_state_data *state = conn->proto.tftpc;
*dophase_done = FALSE; *dophase_done = FALSE;
@ -1340,10 +1351,10 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
if((state->state == TFTP_STATE_FIN) || result) if((state->state == TFTP_STATE_FIN) || result)
return result; return result;
tftp_multi_statemach(conn, dophase_done); tftp_multi_statemach(data, dophase_done);
if(*dophase_done) if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
return result; return result;
} }
@ -1359,15 +1370,16 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
* *
**********************************************************/ **********************************************************/
static CURLcode tftp_do(struct connectdata *conn, bool *done) static CURLcode tftp_do(struct Curl_easy *data, bool *done)
{ {
struct tftp_state_data *state; struct tftp_state_data *state;
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
*done = FALSE; *done = FALSE;
if(!conn->proto.tftpc) { if(!conn->proto.tftpc) {
result = tftp_connect(conn, done); result = tftp_connect(data, done);
if(result) if(result)
return result; return result;
} }
@ -1376,7 +1388,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
if(!state) if(!state)
return CURLE_TFTP_ILLEGAL; return CURLE_TFTP_ILLEGAL;
result = tftp_perform(conn, done); result = tftp_perform(data, done);
/* If tftp_perform() returned an error, use that for return code. If it /* If tftp_perform() returned an error, use that for return code. If it
was OK, see if tftp_translate_code() has an error. */ was OK, see if tftp_translate_code() has an error. */
@ -1387,9 +1399,9 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
return result; return result;
} }
static CURLcode tftp_setup_connection(struct connectdata *conn) static CURLcode tftp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct Curl_easy *data = conn->data;
char *type; char *type;
conn->transport = TRNSPRT_UDP; conn->transport = TRNSPRT_UDP;

View file

@ -93,12 +93,11 @@
* *
* Returns a pointer to the first matching header or NULL if none matched. * Returns a pointer to the first matching header or NULL if none matched.
*/ */
char *Curl_checkheaders(const struct connectdata *conn, char *Curl_checkheaders(const struct Curl_easy *data,
const char *thisheader) const char *thisheader)
{ {
struct curl_slist *head; struct curl_slist *head;
size_t thislen = strlen(thisheader); size_t thislen = strlen(thisheader);
struct Curl_easy *data = conn->data;
for(head = data->set.headers; head; head = head->next) { for(head = data->set.headers; head; head = head->next) {
if(strncasecompare(head->data, thisheader, thislen) && if(strncasecompare(head->data, thisheader, thislen) &&
@ -599,7 +598,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(bytestoread) { if(bytestoread) {
/* receive data from the network! */ /* receive data from the network! */
result = Curl_read(conn, conn->sockfd, buf, bytestoread, &nread); result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
/* read would've blocked */ /* read would've blocked */
if(CURLE_AGAIN == result) if(CURLE_AGAIN == result)
@ -814,11 +813,11 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* Don't let excess data pollute body writes */ /* Don't let excess data pollute body writes */
if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload) if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&data->state.headerb), Curl_dyn_ptr(&data->state.headerb),
headlen); headlen);
else else
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&data->state.headerb), Curl_dyn_ptr(&data->state.headerb),
(size_t)k->maxdownload); (size_t)k->maxdownload);
@ -835,10 +834,10 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(!k->ignorebody) { if(!k->ignorebody) {
#ifndef CURL_DISABLE_POP3 #ifndef CURL_DISABLE_POP3
if(conn->handler->protocol & PROTO_FAMILY_POP3) if(conn->handler->protocol & PROTO_FAMILY_POP3)
result = Curl_pop3_write(conn, k->str, nread); result = Curl_pop3_write(data, k->str, nread);
else else
#endif /* CURL_DISABLE_POP3 */ #endif /* CURL_DISABLE_POP3 */
result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str, result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
nread); nread);
} }
} }
@ -904,13 +903,14 @@ static CURLcode readwrite_data(struct Curl_easy *data,
return CURLE_OK; return CURLE_OK;
} }
CURLcode Curl_done_sending(struct connectdata *conn, CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k) struct SingleRequest *k)
{ {
struct connectdata *conn = data->conn;
k->keepon &= ~KEEP_SEND; /* we're done writing */ k->keepon &= ~KEEP_SEND; /* we're done writing */
/* These functions should be moved into the handler struct! */ /* These functions should be moved into the handler struct! */
Curl_http2_done_sending(conn); Curl_http2_done_sending(data, conn);
Curl_quic_done_sending(conn); Curl_quic_done_sending(conn);
if(conn->bits.rewindaftersend) { if(conn->bits.rewindaftersend) {
@ -1017,7 +1017,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
break; break;
} }
if(nread <= 0) { if(nread <= 0) {
result = Curl_done_sending(conn, k); result = Curl_done_sending(data, k);
if(result) if(result)
return result; return result;
break; break;
@ -1079,7 +1079,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
#ifndef CURL_DISABLE_SMTP #ifndef CURL_DISABLE_SMTP
if(conn->handler->protocol & PROTO_FAMILY_SMTP) { if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
result = Curl_smtp_escape_eob(conn, nread); result = Curl_smtp_escape_eob(data, nread);
if(result) if(result)
return result; return result;
} }
@ -1091,7 +1091,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
} }
/* write to socket (send away data) */ /* write to socket (send away data) */
result = Curl_write(conn, result = Curl_write(data,
conn->writesockfd, /* socket to send to */ conn->writesockfd, /* socket to send to */
k->upload_fromhere, /* buffer pointer */ k->upload_fromhere, /* buffer pointer */
k->upload_present, /* buffer size */ k->upload_present, /* buffer size */
@ -1148,7 +1148,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
k->upload_present = 0; /* no more bytes left */ k->upload_present = 0; /* no more bytes left */
if(k->upload_done) { if(k->upload_done) {
result = Curl_done_sending(conn, k); result = Curl_done_sending(data, k);
if(result) if(result)
return result; return result;
} }
@ -1336,15 +1336,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
* keeps track of. This function will only be called for connections that are * keeps track of. This function will only be called for connections that are
* in the proper state to have this information available. * in the proper state to have this information available.
*/ */
int Curl_single_getsock(const struct connectdata *conn, int Curl_single_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *sock) curl_socket_t *sock)
{ {
const struct Curl_easy *data = conn->data;
int bitmap = GETSOCK_BLANK; int bitmap = GETSOCK_BLANK;
unsigned sockindex = 0; unsigned sockindex = 0;
if(conn->handler->perform_getsock) if(conn->handler->perform_getsock)
return conn->handler->perform_getsock(conn, sock); return conn->handler->perform_getsock(data, conn, sock);
/* don't include HOLD and PAUSE connections */ /* don't include HOLD and PAUSE connections */
if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) { if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {

View file

@ -23,7 +23,7 @@
***************************************************************************/ ***************************************************************************/
#define Curl_headersep(x) ((((x)==':') || ((x)==';'))) #define Curl_headersep(x) ((((x)==':') || ((x)==';')))
char *Curl_checkheaders(const struct connectdata *conn, char *Curl_checkheaders(const struct Curl_easy *data,
const char *thisheader); const char *thisheader);
void Curl_init_CONNECT(struct Curl_easy *data); void Curl_init_CONNECT(struct Curl_easy *data);
@ -45,8 +45,8 @@ CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
CURLcode Curl_readwrite(struct connectdata *conn, CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data, bool *done, struct Curl_easy *data, bool *done,
bool *comeback); bool *comeback);
int Curl_single_getsock(const struct connectdata *conn, int Curl_single_getsock(struct Curl_easy *data,
curl_socket_t *socks); struct connectdata *conn, curl_socket_t *socks);
CURLcode Curl_readrewind(struct connectdata *conn); CURLcode Curl_readrewind(struct connectdata *conn);
CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
size_t *nreadp); size_t *nreadp);
@ -54,7 +54,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc); bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
CURLcode Curl_get_upload_buffer(struct Curl_easy *data); CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
CURLcode Curl_done_sending(struct connectdata *conn, CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k); struct SingleRequest *k);
/* This sets up a forthcoming transfer */ /* This sets up a forthcoming transfer */

View file

@ -364,6 +364,9 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_expire_clear(data); /* shut off timers */ Curl_expire_clear(data); /* shut off timers */
/* Detach connection if any is left. This should not be normal, but can be
the case for example with CONNECT_ONLY + recv/send (test 556) */
Curl_detach_connnection(data);
m = data->multi; m = data->multi;
if(m) if(m)
/* This handle is still part of a multi handle, take care of this first /* This handle is still part of a multi handle, take care of this first
@ -709,11 +712,11 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
static void conn_shutdown(struct connectdata *conn) static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
{ {
DEBUGASSERT(conn); DEBUGASSERT(conn);
infof(conn->data, "Closing connection %ld\n", conn->connection_id); DEBUGASSERT(data);
DEBUGASSERT(conn->data); infof(data, "Closing connection %ld\n", conn->connection_id);
/* possible left-overs from the async name resolvers */ /* possible left-overs from the async name resolvers */
Curl_resolver_cancel(conn); Curl_resolver_cancel(conn);
@ -725,13 +728,13 @@ static void conn_shutdown(struct connectdata *conn)
/* close possibly still open sockets */ /* close possibly still open sockets */
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]);
if(CURL_SOCKET_BAD != conn->tempsock[0]) if(CURL_SOCKET_BAD != conn->tempsock[0])
Curl_closesocket(conn, conn->tempsock[0]); Curl_closesocket(data, conn, conn->tempsock[0]);
if(CURL_SOCKET_BAD != conn->tempsock[1]) if(CURL_SOCKET_BAD != conn->tempsock[1])
Curl_closesocket(conn, conn->tempsock[1]); Curl_closesocket(data, conn, conn->tempsock[1]);
} }
static void conn_free(struct connectdata *conn) static void conn_free(struct connectdata *conn)
@ -834,11 +837,18 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
/* treat the connection as dead in CONNECT_ONLY situations */ /* treat the connection as dead in CONNECT_ONLY situations */
dead_connection = TRUE; dead_connection = TRUE;
if(conn->handler->disconnect) if(conn->handler->disconnect) {
/* This is set if protocol-specific cleanups should be made */ /* During disconnect, the connection and the transfer is already
conn->handler->disconnect(conn, dead_connection); disassociated, but the SSH backends (and more?) still need the
transfer's connection pointer to identify the used connection */
data->conn = conn;
conn_shutdown(conn); /* This is set if protocol-specific cleanups should be made */
conn->handler->disconnect(data, conn, dead_connection);
data->conn = NULL; /* forget it again */
}
conn_shutdown(data, conn);
conn_free(conn); conn_free(conn);
return CURLE_OK; return CURLE_OK;
} }
@ -961,23 +971,29 @@ static bool conn_maxage(struct Curl_easy *data,
static bool extract_if_dead(struct connectdata *conn, static bool extract_if_dead(struct connectdata *conn,
struct Curl_easy *data) struct Curl_easy *data)
{ {
if(!CONN_INUSE(conn) && !conn->data) { if(!CONN_INUSE(conn)) {
/* The check for a dead socket makes sense only if the connection isn't in /* The check for a dead socket makes sense only if the connection isn't in
use */ use */
bool dead; bool dead;
struct curltime now = Curl_now(); struct curltime now = Curl_now();
if(conn_maxage(data, conn, now)) { if(conn_maxage(data, conn, now)) {
/* avoid check if already too old */
dead = TRUE; dead = TRUE;
} }
else if(conn->handler->connection_check) { else if(conn->handler->connection_check) {
/* The protocol has a special method for checking the state of the /* The protocol has a special method for checking the state of the
connection. Use it to check if the connection is dead. */ connection. Use it to check if the connection is dead. */
unsigned int state; unsigned int state;
struct Curl_easy *olddata = conn->data;
conn->data = data; /* use this transfer for now */ /* briefly attach the connection to this transfer for the purpose of
state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD); checking it */
conn->data = olddata; Curl_attach_connnection(data, conn);
conn->data = data; /* find the way back if necessary */
state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);
dead = (state & CONNRESULT_DEAD); dead = (state & CONNRESULT_DEAD);
/* detach the connection again */
Curl_detach_connnection(data);
conn->data = NULL; /* clear it again */
} }
else { else {
/* Use the general method for determining the death of a connection */ /* Use the general method for determining the death of a connection */
@ -1002,10 +1018,11 @@ struct prunedead {
* Wrapper to use extract_if_dead() function in Curl_conncache_foreach() * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
* *
*/ */
static int call_extract_if_dead(struct connectdata *conn, void *param) static int call_extract_if_dead(struct Curl_easy *data,
struct connectdata *conn, void *param)
{ {
struct prunedead *p = (struct prunedead *)param; struct prunedead *p = (struct prunedead *)param;
if(extract_if_dead(conn, p->data)) { if(extract_if_dead(conn, data)) {
/* stop the iteration here, pass back the connection that was extracted */ /* stop the iteration here, pass back the connection that was extracted */
p->extracted = conn; p->extracted = conn;
return 1; return 1;
@ -1015,14 +1032,16 @@ static int call_extract_if_dead(struct connectdata *conn, void *param)
/* /*
* This function scans the connection cache for half-open/dead connections, * This function scans the connection cache for half-open/dead connections,
* closes and removes them. * closes and removes them. The cleanup is done at most once per second.
* The cleanup is done at most once per second. *
* When called, this transfer has no connection attached.
*/ */
static void prune_dead_connections(struct Curl_easy *data) static void prune_dead_connections(struct Curl_easy *data)
{ {
struct curltime now = Curl_now(); struct curltime now = Curl_now();
timediff_t elapsed; timediff_t elapsed;
DEBUGASSERT(!data->conn); /* no connection */
CONNCACHE_LOCK(data); CONNCACHE_LOCK(data);
elapsed = elapsed =
Curl_timediff(now, data->state.conn_cache->last_cleanup); Curl_timediff(now, data->state.conn_cache->last_cleanup);
@ -1463,9 +1482,10 @@ ConnectionExists(struct Curl_easy *data,
* verboseconnect() displays verbose information after a connect * verboseconnect() displays verbose information after a connect
*/ */
#ifndef CURL_DISABLE_VERBOSE_STRINGS #ifndef CURL_DISABLE_VERBOSE_STRINGS
void Curl_verboseconnect(struct connectdata *conn) void Curl_verboseconnect(struct Curl_easy *data,
struct connectdata *conn)
{ {
if(conn->data->set.verbose) if(data->set.verbose)
infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
conn->bits.socksproxy ? conn->socks_proxy.host.dispname : conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
@ -2084,7 +2104,8 @@ static CURLcode setup_range(struct Curl_easy *data)
* *
* This MUST get called after proxy magic has been figured out. * This MUST get called after proxy magic has been figured out.
*/ */
static CURLcode setup_connection_internals(struct connectdata *conn) static CURLcode setup_connection_internals(struct Curl_easy *data,
struct connectdata *conn)
{ {
const struct Curl_handler *p; const struct Curl_handler *p;
CURLcode result; CURLcode result;
@ -2093,7 +2114,7 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
p = conn->handler; p = conn->handler;
if(p->setup_connection) { if(p->setup_connection) {
result = (*p->setup_connection)(conn); result = (*p->setup_connection)(data, conn);
if(result) if(result)
return result; return result;
@ -3337,7 +3358,8 @@ static CURLcode resolve_server(struct Curl_easy *data,
* previously existing one. All relevant data is copied over and old_conn is * previously existing one. All relevant data is copied over and old_conn is
* ready for freeing once this function returns. * ready for freeing once this function returns.
*/ */
static void reuse_conn(struct connectdata *old_conn, static void reuse_conn(struct Curl_easy *data,
struct connectdata *old_conn,
struct connectdata *conn) struct connectdata *conn)
{ {
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
@ -3352,7 +3374,7 @@ static void reuse_conn(struct connectdata *old_conn,
allocated in vain and is targeted for destruction */ allocated in vain and is targeted for destruction */
Curl_free_primary_ssl_config(&old_conn->ssl_config); Curl_free_primary_ssl_config(&old_conn->ssl_config);
conn->data = old_conn->data; conn->data = data;
/* get the user+password information from the old_conn struct since it may /* get the user+password information from the old_conn struct since it may
* be new for this request even when we re-use an existing connection */ * be new for this request even when we re-use an existing connection */
@ -3406,7 +3428,7 @@ static void reuse_conn(struct connectdata *old_conn,
old_conn->hostname_resolve = NULL; old_conn->hostname_resolve = NULL;
/* persist connection info in session handle */ /* persist connection info in session handle */
Curl_persistconninfo(conn); Curl_persistconninfo(data, conn);
conn_reset_all_postponed_data(old_conn); /* free buffers */ conn_reset_all_postponed_data(old_conn); /* free buffers */
@ -3600,7 +3622,7 @@ static CURLcode create_conn(struct Curl_easy *data,
* Setup internals depending on protocol. Needs to be done after * Setup internals depending on protocol. Needs to be done after
* we figured out what/if proxy to use. * we figured out what/if proxy to use.
*************************************************************/ *************************************************************/
result = setup_connection_internals(conn); result = setup_connection_internals(data, conn);
if(result) if(result)
goto out; goto out;
@ -3620,8 +3642,8 @@ static CURLcode create_conn(struct Curl_easy *data,
/* this is supposed to be the connect function so we better at least check /* this is supposed to be the connect function so we better at least check
that the file is present here! */ that the file is present here! */
DEBUGASSERT(conn->handler->connect_it); DEBUGASSERT(conn->handler->connect_it);
Curl_persistconninfo(conn); Curl_persistconninfo(data, conn);
result = conn->handler->connect_it(conn, &done); result = conn->handler->connect_it(data, &done);
/* Setup a "faked" transfer that'll do nothing */ /* Setup a "faked" transfer that'll do nothing */
if(!result) { if(!result) {
@ -3639,7 +3661,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result) { if(result) {
DEBUGASSERT(conn->handler->done); DEBUGASSERT(conn->handler->done);
/* we ignore the return code for the protocol-specific DONE */ /* we ignore the return code for the protocol-specific DONE */
(void)conn->handler->done(conn, result, FALSE); (void)conn->handler->done(data, result, FALSE);
goto out; goto out;
} }
Curl_setup_transfer(data, -1, -1, FALSE, -1); Curl_setup_transfer(data, -1, -1, FALSE, -1);
@ -3752,12 +3774,11 @@ static CURLcode create_conn(struct Curl_easy *data,
if(reuse) { if(reuse) {
/* /*
* We already have a connection for this, we got the former connection * We already have a connection for this, we got the former connection in
* in the conn_temp variable and thus we need to cleanup the one we * the conn_temp variable and thus we need to cleanup the one we just
* just allocated before we can move along and use the previously * allocated before we can move along and use the previously existing one.
* existing one.
*/ */
reuse_conn(conn, conn_temp); reuse_conn(data, conn, conn_temp);
#ifdef USE_SSL #ifdef USE_SSL
free(conn->ssl_extra); free(conn->ssl_extra);
#endif #endif
@ -3958,7 +3979,7 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
conn->bits.tcpconnect[FIRSTSOCKET] = FALSE; conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
result = Curl_connecthost(conn, conn->dns_entry); result = Curl_connecthost(data, conn, conn->dns_entry);
if(result) if(result)
return result; return result;
} }
@ -3969,8 +3990,8 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
*protocol_done = TRUE; *protocol_done = TRUE;
Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]); Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
Curl_verboseconnect(conn); Curl_verboseconnect(data, conn);
} }
conn->now = Curl_now(); /* time this *after* the connect is done, we set conn->now = Curl_now(); /* time this *after* the connect is done, we set

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -72,9 +72,9 @@ void Curl_free_idnconverted_hostname(struct hostname *host);
specified */ specified */
#ifdef CURL_DISABLE_VERBOSE_STRINGS #ifdef CURL_DISABLE_VERBOSE_STRINGS
#define Curl_verboseconnect(x) Curl_nop_stmt #define Curl_verboseconnect(x,y) Curl_nop_stmt
#else #else
void Curl_verboseconnect(struct connectdata *conn); void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn);
#endif #endif
#ifdef CURL_DISABLE_PROXY #ifdef CURL_DISABLE_PROXY

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -105,14 +105,14 @@
#include "dynbuf.h" #include "dynbuf.h"
/* return the count of bytes sent, or -1 on error */ /* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */ int sockindex, /* socketindex */
const void *buf, /* data to write */ const void *buf, /* data to write */
size_t len, /* max amount to write */ size_t len, /* max amount to write */
CURLcode *err); /* error to return */ CURLcode *err); /* error to return */
/* return the count of bytes read, or -1 on error */ /* return the count of bytes read, or -1 on error */
typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */ int sockindex, /* socketindex */
char *buf, /* store data here */ char *buf, /* store data here */
size_t len, /* max amount to read */ size_t len, /* max amount to read */
@ -535,12 +535,6 @@ struct Curl_async {
#define FIRSTSOCKET 0 #define FIRSTSOCKET 0
#define SECONDARYSOCKET 1 #define SECONDARYSOCKET 1
/* These function pointer types are here only to allow easier typecasting
within the source when we need to cast between data pointers (such as NULL)
and function pointers. */
typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
enum expect100 { enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */ EXP100_SEND_DATA, /* enough waiting, just send the body now */
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
@ -697,18 +691,20 @@ struct SingleRequest {
struct Curl_handler { struct Curl_handler {
const char *scheme; /* URL scheme name. */ const char *scheme; /* URL scheme name. */
/* Complement to setup_connection_internals(). */ /* Complement to setup_connection_internals(). This is done before the
CURLcode (*setup_connection)(struct connectdata *); transfer "owns" the connection. */
CURLcode (*setup_connection)(struct Curl_easy *data,
struct connectdata *conn);
/* These two functions MUST be set to be protocol dependent */ /* These two functions MUST be set to be protocol dependent */
CURLcode (*do_it)(struct connectdata *, bool *done); CURLcode (*do_it)(struct Curl_easy *data, bool *done);
Curl_done_func done; CURLcode (*done)(struct Curl_easy *, CURLcode, bool);
/* If the curl_do() function is better made in two halves, this /* If the curl_do() function is better made in two halves, this
* curl_do_more() function will be called afterwards, if set. For example * curl_do_more() function will be called afterwards, if set. For example
* for doing the FTP stuff after the PASV/PORT command. * for doing the FTP stuff after the PASV/PORT command.
*/ */
Curl_do_more_func do_more; CURLcode (*do_more)(struct Curl_easy *, int *);
/* This function *MAY* be set to a protocol-dependent function that is run /* This function *MAY* be set to a protocol-dependent function that is run
* after the connect() and everything is done, as a step in the connection. * after the connect() and everything is done, as a step in the connection.
@ -716,39 +712,41 @@ struct Curl_handler {
* function completes before return. If it doesn't complete, the caller * function completes before return. If it doesn't complete, the caller
* should call the curl_connecting() function until it is. * should call the curl_connecting() function until it is.
*/ */
CURLcode (*connect_it)(struct connectdata *, bool *done); CURLcode (*connect_it)(struct Curl_easy *data, bool *done);
/* See above. */ /* See above. */
CURLcode (*connecting)(struct connectdata *, bool *done); CURLcode (*connecting)(struct Curl_easy *data, bool *done);
CURLcode (*doing)(struct connectdata *, bool *done); CURLcode (*doing)(struct Curl_easy *data, bool *done);
/* Called from the multi interface during the PROTOCONNECT phase, and it /* Called from the multi interface during the PROTOCONNECT phase, and it
should then return a proper fd set */ should then return a proper fd set */
int (*proto_getsock)(struct connectdata *conn, int (*proto_getsock)(struct Curl_easy *data,
curl_socket_t *socks); struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DOING phase, and it should /* Called from the multi interface during the DOING phase, and it should
then return a proper fd set */ then return a proper fd set */
int (*doing_getsock)(struct connectdata *conn, int (*doing_getsock)(struct Curl_easy *data,
curl_socket_t *socks); struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_MORE phase, and it should /* Called from the multi interface during the DO_MORE phase, and it should
then return a proper fd set */ then return a proper fd set */
int (*domore_getsock)(struct connectdata *conn, int (*domore_getsock)(struct Curl_easy *data,
curl_socket_t *socks); struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_DONE, PERFORM and /* Called from the multi interface during the DO_DONE, PERFORM and
WAITPERFORM phases, and it should then return a proper fd set. Not setting WAITPERFORM phases, and it should then return a proper fd set. Not setting
this will make libcurl use the generic default one. */ this will make libcurl use the generic default one. */
int (*perform_getsock)(const struct connectdata *conn, int (*perform_getsock)(struct Curl_easy *data,
curl_socket_t *socks); struct connectdata *conn, curl_socket_t *socks);
/* This function *MAY* be set to a protocol-dependent function that is run /* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection. If the handler * by the curl_disconnect(), as a step in the disconnection. If the handler
* is called because the connection has been considered dead, dead_connection * is called because the connection has been considered dead,
* is set to TRUE. * dead_connection is set to TRUE. The connection is already disassociated
* from the transfer here.
*/ */
CURLcode (*disconnect)(struct connectdata *, bool dead_connection); CURLcode (*disconnect)(struct Curl_easy *, struct connectdata *,
bool dead_connection);
/* If used, this function gets called from transfer.c:readwrite_data() to /* If used, this function gets called from transfer.c:readwrite_data() to
allow the protocol to do extra reads/writes */ allow the protocol to do extra reads/writes */
@ -758,7 +756,8 @@ struct Curl_handler {
/* This function can perform various checks on the connection. See /* This function can perform various checks on the connection. See
CONNCHECK_* for more information about the checks that can be performed, CONNCHECK_* for more information about the checks that can be performed,
and CONNRESULT_* for the results that can be returned. */ and CONNRESULT_* for the results that can be returned. */
unsigned int (*connection_check)(struct connectdata *conn, unsigned int (*connection_check)(struct Curl_easy *data,
struct connectdata *conn,
unsigned int checks_to_perform); unsigned int checks_to_perform);
long defport; /* Default port. */ long defport; /* Default port. */

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -90,7 +90,7 @@ struct h3out {
static CURLcode ng_process_ingress(struct connectdata *conn, static CURLcode ng_process_ingress(struct connectdata *conn,
curl_socket_t sockfd, curl_socket_t sockfd,
struct quicsocket *qs); struct quicsocket *qs);
static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, static CURLcode ng_flush_egress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs); struct quicsocket *qs);
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
size_t datalen, void *user_data, size_t datalen, void *user_data,
@ -843,9 +843,10 @@ int Curl_quic_ver(char *p, size_t len)
ng2->version_str, ht3->version_str); ng2->version_str, ht3->version_str);
} }
static int ng_getsock(struct connectdata *conn, curl_socket_t *socks) static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks)
{ {
struct SingleRequest *k = &conn->data->req; struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK; int bitmap = GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET]; socks[0] = conn->sock[FIRSTSOCKET];
@ -861,12 +862,6 @@ static int ng_getsock(struct connectdata *conn, curl_socket_t *socks)
return bitmap; return bitmap;
} }
static int ng_perform_getsock(const struct connectdata *conn,
curl_socket_t *socks)
{
return ng_getsock((struct connectdata *)conn, socks);
}
static void qs_disconnect(struct quicsocket *qs) static void qs_disconnect(struct quicsocket *qs)
{ {
int i; int i;
@ -904,18 +899,22 @@ void Curl_quic_disconnect(struct connectdata *conn,
qs_disconnect(&conn->hequic[tempindex]); qs_disconnect(&conn->hequic[tempindex]);
} }
static CURLcode ng_disconnect(struct connectdata *conn, static CURLcode ng_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection) bool dead_connection)
{ {
(void)dead_connection; (void)dead_connection;
(void)data;
Curl_quic_disconnect(conn, 0); Curl_quic_disconnect(conn, 0);
Curl_quic_disconnect(conn, 1); Curl_quic_disconnect(conn, 1);
return CURLE_OK; return CURLE_OK;
} }
static unsigned int ng_conncheck(struct connectdata *conn, static unsigned int ng_conncheck(struct Curl_easy *data,
struct connectdata *conn,
unsigned int checks_to_perform) unsigned int checks_to_perform)
{ {
(void)data;
(void)conn; (void)conn;
(void)checks_to_perform; (void)checks_to_perform;
return CONNRESULT_NONE; return CONNRESULT_NONE;
@ -933,7 +932,7 @@ static const struct Curl_handler Curl_handler_http3 = {
ng_getsock, /* proto_getsock */ ng_getsock, /* proto_getsock */
ng_getsock, /* doing_getsock */ ng_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
ng_perform_getsock, /* perform_getsock */ ng_getsock, /* perform_getsock */
ng_disconnect, /* disconnect */ ng_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
ng_conncheck, /* connection_check */ ng_conncheck, /* connection_check */
@ -1235,14 +1234,15 @@ static size_t drain_overflow_buffer(struct HTTP *stream)
} }
/* incoming data frames on the h3 stream */ /* incoming data frames on the h3 stream */
static ssize_t ngh3_stream_recv(struct connectdata *conn, static ssize_t ngh3_stream_recv(struct Curl_easy *data,
int sockindex, int sockindex,
char *buf, char *buf,
size_t buffersize, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[sockindex]; curl_socket_t sockfd = conn->sock[sockindex];
struct HTTP *stream = conn->data->req.p.http; struct HTTP *stream = data->req.p.http;
struct quicsocket *qs = conn->quic; struct quicsocket *qs = conn->quic;
if(!stream->memlen) { if(!stream->memlen) {
@ -1261,7 +1261,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
*curlcode = CURLE_RECV_ERROR; *curlcode = CURLE_RECV_ERROR;
return -1; return -1;
} }
if(ng_flush_egress(conn, sockfd, qs)) { if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1; return -1;
} }
@ -1277,7 +1277,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
/* extend the stream window with the data we're consuming and send out /* extend the stream window with the data we're consuming and send out
any additional packets to tell the server that we can receive more */ any additional packets to tell the server that we can receive more */
extend_stream_window(qs->qconn, stream); extend_stream_window(qs->qconn, stream);
if(ng_flush_egress(conn, sockfd, qs)) { if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1; return -1;
} }
@ -1289,7 +1289,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
return 0; return 0;
} }
infof(conn->data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n"); infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
return -1; return -1;
} }
@ -1382,10 +1382,11 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
field list. */ field list. */
#define AUTHORITY_DST_IDX 3 #define AUTHORITY_DST_IDX 3
static CURLcode http_request(struct connectdata *conn, const void *mem, static CURLcode http_request(struct Curl_easy *data, const void *mem,
size_t len) size_t len)
{ {
struct HTTP *stream = conn->data->req.p.http; struct connectdata *conn = data->conn;
struct HTTP *stream = data->req.p.http;
size_t nheader; size_t nheader;
size_t i; size_t i;
size_t authority_idx; size_t authority_idx;
@ -1393,7 +1394,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
char *end, *line_end; char *end, *line_end;
struct quicsocket *qs = conn->quic; struct quicsocket *qs = conn->quic;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
nghttp3_nv *nva = NULL; nghttp3_nv *nva = NULL;
int64_t stream3_id; int64_t stream3_id;
int rc; int rc;
@ -1401,7 +1401,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL); rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL);
if(rc) { if(rc) {
failf(conn->data, "can get bidi streams"); failf(data, "can get bidi streams");
result = CURLE_SEND_ERROR; result = CURLE_SEND_ERROR;
goto fail; goto fail;
} }
@ -1587,8 +1587,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
stream->h3out = h3out; stream->h3out = h3out;
rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id, rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
nva, nheader, &data_reader, nva, nheader, &data_reader, data);
conn->data);
if(rc) { if(rc) {
result = CURLE_SEND_ERROR; result = CURLE_SEND_ERROR;
goto fail; goto fail;
@ -1598,9 +1597,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
default: default:
stream->upload_left = 0; /* nothing left to send */ stream->upload_left = 0; /* nothing left to send */
rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id, rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
nva, nheader, nva, nheader, NULL, data);
NULL, /* no body! */
conn->data);
if(rc) { if(rc) {
result = CURLE_SEND_ERROR; result = CURLE_SEND_ERROR;
goto fail; goto fail;
@ -1619,19 +1616,20 @@ fail:
free(nva); free(nva);
return result; return result;
} }
static ssize_t ngh3_stream_send(struct connectdata *conn, static ssize_t ngh3_stream_send(struct Curl_easy *data,
int sockindex, int sockindex,
const void *mem, const void *mem,
size_t len, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
ssize_t sent; ssize_t sent;
struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic; struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex]; curl_socket_t sockfd = conn->sock[sockindex];
struct HTTP *stream = conn->data->req.p.http; struct HTTP *stream = data->req.p.http;
if(!stream->h3req) { if(!stream->h3req) {
CURLcode result = http_request(conn, mem, len); CURLcode result = http_request(data, mem, len);
if(result) { if(result) {
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1; return -1;
@ -1639,7 +1637,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn,
sent = len; sent = len;
} }
else { else {
H3BUGF(infof(conn->data, "ngh3_stream_send() wants to send %zd bytes\n", H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n",
len)); len));
if(!stream->upload_len) { if(!stream->upload_len) {
stream->upload_mem = mem; stream->upload_mem = mem;
@ -1653,7 +1651,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn,
} }
} }
if(ng_flush_egress(conn, sockfd, qs)) { if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1; return -1;
} }
@ -1689,7 +1687,7 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
if(result) if(result)
goto error; goto error;
result = ng_flush_egress(conn, sockfd, qs); result = ng_flush_egress(conn->data, sockfd, qs);
if(result) if(result)
goto error; goto error;
@ -1749,7 +1747,8 @@ static CURLcode ng_process_ingress(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, static CURLcode ng_flush_egress(struct Curl_easy *data,
int sockfd,
struct quicsocket *qs) struct quicsocket *qs)
{ {
int rv; int rv;
@ -1783,7 +1782,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
rv = ngtcp2_conn_handle_expiry(qs->qconn, ts); rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
if(rv != 0) { if(rv != 0) {
failf(conn->data, "ngtcp2_conn_handle_expiry returned error: %s", failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
ngtcp2_strerror(rv)); ngtcp2_strerror(rv));
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
} }
@ -1796,7 +1795,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec, veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
sizeof(vec) / sizeof(vec[0])); sizeof(vec) / sizeof(vec[0]));
if(veccnt < 0) { if(veccnt < 0) {
failf(conn->data, "nghttp3_conn_writev_stream returned error: %s", failf(data, "nghttp3_conn_writev_stream returned error: %s",
nghttp3_strerror((int)veccnt)); nghttp3_strerror((int)veccnt));
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
} }
@ -1817,7 +1816,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
assert(ndatalen == -1); assert(ndatalen == -1);
rv = nghttp3_conn_block_stream(qs->h3conn, stream_id); rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
if(rv != 0) { if(rv != 0) {
failf(conn->data, failf(data,
"nghttp3_conn_block_stream returned error: %s\n", "nghttp3_conn_block_stream returned error: %s\n",
nghttp3_strerror(rv)); nghttp3_strerror(rv));
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
@ -1829,7 +1828,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id,
ndatalen); ndatalen);
if(rv != 0) { if(rv != 0) {
failf(conn->data, failf(data,
"nghttp3_conn_add_write_offset returned error: %s\n", "nghttp3_conn_add_write_offset returned error: %s\n",
nghttp3_strerror(rv)); nghttp3_strerror(rv));
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
@ -1838,7 +1837,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
} }
else { else {
assert(ndatalen == -1); assert(ndatalen == -1);
failf(conn->data, "ngtcp2_conn_writev_stream returned error: %s", failf(data, "ngtcp2_conn_writev_stream returned error: %s",
ngtcp2_strerror((int)outlen)); ngtcp2_strerror((int)outlen));
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
} }
@ -1852,7 +1851,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, NULL, outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, NULL,
out, pktlen, ts); out, pktlen, ts);
if(outlen < 0) { if(outlen < 0) {
failf(conn->data, "ngtcp2_conn_write_pkt returned error: %s", failf(data, "ngtcp2_conn_write_pkt returned error: %s",
ngtcp2_strerror((int)outlen)); ngtcp2_strerror((int)outlen));
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
} }
@ -1871,7 +1870,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
break; break;
} }
else { else {
failf(conn->data, "send() returned %zd (errno %d)", sent, failf(data, "send() returned %zd (errno %d)", sent,
SOCKERRNO); SOCKERRNO);
return CURLE_SEND_ERROR; return CURLE_SEND_ERROR;
} }
@ -1886,7 +1885,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
else { else {
timeout = expiry - ts; timeout = expiry - ts;
} }
Curl_expire(conn->data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC); Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
} }
return CURLE_OK; return CURLE_OK;

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -65,9 +65,10 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
static Curl_recv h3_stream_recv; static Curl_recv h3_stream_recv;
static Curl_send h3_stream_send; static Curl_send h3_stream_send;
static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks) static int quiche_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{ {
struct SingleRequest *k = &conn->data->req; struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK; int bitmap = GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET]; socks[0] = conn->sock[FIRSTSOCKET];
@ -83,12 +84,6 @@ static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks)
return bitmap; return bitmap;
} }
static int quiche_perform_getsock(const struct connectdata *conn,
curl_socket_t *socks)
{
return quiche_getsock((struct connectdata *)conn, socks);
}
static CURLcode qs_disconnect(struct connectdata *conn, static CURLcode qs_disconnect(struct connectdata *conn,
struct quicsocket *qs) struct quicsocket *qs)
{ {
@ -111,10 +106,12 @@ static CURLcode qs_disconnect(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode quiche_disconnect(struct connectdata *conn, static CURLcode quiche_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection) bool dead_connection)
{ {
struct quicsocket *qs = conn->quic; struct quicsocket *qs = conn->quic;
(void)data;
(void)dead_connection; (void)dead_connection;
return qs_disconnect(conn, qs); return qs_disconnect(conn, qs);
} }
@ -126,19 +123,21 @@ void Curl_quic_disconnect(struct connectdata *conn,
qs_disconnect(conn, &conn->hequic[tempindex]); qs_disconnect(conn, &conn->hequic[tempindex]);
} }
static unsigned int quiche_conncheck(struct connectdata *conn, static unsigned int quiche_conncheck(struct Curl_easy *data,
struct connectdata *conn,
unsigned int checks_to_perform) unsigned int checks_to_perform)
{ {
(void)data;
(void)conn; (void)conn;
(void)checks_to_perform; (void)checks_to_perform;
return CONNRESULT_NONE; return CONNRESULT_NONE;
} }
static CURLcode quiche_do(struct connectdata *conn, bool *done) static CURLcode quiche_do(struct Curl_easy *data, bool *done)
{ {
struct HTTP *stream = conn->data->req.p.http; struct HTTP *stream = data->req.p.http;
stream->h3req = FALSE; /* not sent */ stream->h3req = FALSE; /* not sent */
return Curl_http(conn, done); return Curl_http(data, done);
} }
static const struct Curl_handler Curl_handler_http3 = { static const struct Curl_handler Curl_handler_http3 = {
@ -153,7 +152,7 @@ static const struct Curl_handler Curl_handler_http3 = {
quiche_getsock, /* proto_getsock */ quiche_getsock, /* proto_getsock */
quiche_getsock, /* doing_getsock */ quiche_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
quiche_perform_getsock, /* perform_getsock */ quiche_getsock, /* perform_getsock */
quiche_disconnect, /* disconnect */ quiche_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
quiche_conncheck, /* connection_check */ quiche_conncheck, /* connection_check */
@ -256,7 +255,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
Curl_persistconninfo(conn); Curl_persistconninfo(data, conn);
/* for connection reuse purposes: */ /* for connection reuse purposes: */
conn->ssl[FIRSTSOCKET].state = ssl_connection_complete; conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
@ -453,7 +452,7 @@ static int cb_each_header(uint8_t *name, size_t name_len,
return 0; return 0;
} }
static ssize_t h3_stream_recv(struct connectdata *conn, static ssize_t h3_stream_recv(struct Curl_easy *data,
int sockindex, int sockindex,
char *buf, char *buf,
size_t buffersize, size_t buffersize,
@ -461,12 +460,12 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
{ {
ssize_t recvd = -1; ssize_t recvd = -1;
ssize_t rcode; ssize_t rcode;
struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic; struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex]; curl_socket_t sockfd = conn->sock[sockindex];
quiche_h3_event *ev; quiche_h3_event *ev;
int rc; int rc;
struct h3h1header headers; struct h3h1header headers;
struct Curl_easy *data = conn->data;
struct HTTP *stream = data->req.p.http; struct HTTP *stream = data->req.p.http;
headers.dest = buf; headers.dest = buf;
headers.destlen = buffersize; headers.destlen = buffersize;
@ -546,16 +545,17 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
return recvd; return recvd;
} }
static ssize_t h3_stream_send(struct connectdata *conn, static ssize_t h3_stream_send(struct Curl_easy *data,
int sockindex, int sockindex,
const void *mem, const void *mem,
size_t len, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
ssize_t sent; ssize_t sent;
struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic; struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex]; curl_socket_t sockfd = conn->sock[sockindex];
struct HTTP *stream = conn->data->req.p.http; struct HTTP *stream = data->req.p.http;
if(!stream->h3req) { if(!stream->h3req) {
CURLcode result = http_request(conn, mem, len); CURLcode result = http_request(conn, mem, len);

View file

@ -107,34 +107,37 @@
#endif #endif
/* Local functions: */ /* Local functions: */
static CURLcode myssh_connect(struct connectdata *conn, bool *done); static CURLcode myssh_connect(struct Curl_easy *data, bool *done);
static CURLcode myssh_multi_statemach(struct connectdata *conn, static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done); bool *done);
static CURLcode myssh_do_it(struct connectdata *conn, bool *done); static CURLcode myssh_do_it(struct Curl_easy *data, bool *done);
static CURLcode scp_done(struct connectdata *conn, static CURLcode scp_done(struct Curl_easy *data,
CURLcode, bool premature); CURLcode, bool premature);
static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done); static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode scp_disconnect(struct connectdata *conn, static CURLcode scp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection); bool dead_connection);
static CURLcode sftp_done(struct connectdata *conn, static CURLcode sftp_done(struct Curl_easy *data,
CURLcode, bool premature); CURLcode, bool premature);
static CURLcode sftp_doing(struct connectdata *conn, static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done); bool *dophase_done);
static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); static CURLcode sftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead);
static static
CURLcode sftp_perform(struct connectdata *conn, CURLcode sftp_perform(struct Curl_easy *data,
bool *connected, bool *connected,
bool *dophase_done); bool *dophase_done);
static void sftp_quote(struct connectdata *conn); static void sftp_quote(struct connectdata *conn);
static void sftp_quote_stat(struct connectdata *conn); static void sftp_quote_stat(struct connectdata *conn);
static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock); static int myssh_getsock(struct Curl_easy *data,
static int myssh_perform_getsock(const struct connectdata *conn, struct connectdata *conn, curl_socket_t *sock);
curl_socket_t *sock);
static CURLcode myssh_setup_connection(struct connectdata *conn); static CURLcode myssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
/* /*
* SCP protocol handler. * SCP protocol handler.
@ -152,7 +155,7 @@ const struct Curl_handler Curl_handler_scp = {
myssh_getsock, /* proto_getsock */ myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */ myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
myssh_perform_getsock, /* perform_getsock */ myssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */ scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */ ZERO_NULL, /* connection_check */
@ -178,7 +181,7 @@ const struct Curl_handler Curl_handler_sftp = {
myssh_getsock, /* proto_getsock */ myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */ myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
myssh_perform_getsock, /* perform_getsock */ myssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */ sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */ ZERO_NULL, /* connection_check */
@ -660,10 +663,10 @@ restart:
* to will be set to TRUE if the libssh function returns SSH_AGAIN * to will be set to TRUE if the libssh function returns SSH_AGAIN
* meaning it wants to be called again when the socket is ready * meaning it wants to be called again when the socket is ready
*/ */
static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct SSHPROTO *protop = data->req.p.ssh; struct SSHPROTO *protop = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
@ -950,7 +953,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->homedir == NULL) { if(sshc->homedir == NULL) {
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
} }
conn->data->state.most_recent_ftp_entrypath = sshc->homedir; data->state.most_recent_ftp_entrypath = sshc->homedir;
/* This is the last step in the SFTP connect phase. Do note that while /* This is the last step in the SFTP connect phase. Do note that while
we get the homedir here, we get the "workingpath" in the DO action we get the homedir here, we get the "workingpath" in the DO action
@ -1150,7 +1153,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
break; break;
} }
result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp); free(tmp);
if(result) { if(result) {
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
@ -1419,7 +1422,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_OUT_OF_MEMORY; sshc->actualcode = CURLE_OUT_OF_MEMORY;
break; break;
} }
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
tmpLine, sshc->readdir_len + 1); tmpLine, sshc->readdir_len + 1);
free(tmpLine); free(tmpLine);
@ -1540,7 +1543,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_currLen, sshc->readdir_currLen,
sshc->readdir_totalLen - sshc->readdir_totalLen -
sshc->readdir_currLen, "\n"); sshc->readdir_currLen, "\n");
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
sshc->readdir_line, sshc->readdir_line,
sshc->readdir_currLen); sshc->readdir_currLen);
@ -1618,14 +1621,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME; return CURLE_BAD_DOWNLOAD_RESUME;
} }
if(conn->data->state.use_range) { if(data->state.use_range) {
curl_off_t from, to; curl_off_t from, to;
char *ptr; char *ptr;
char *ptr2; char *ptr2;
CURLofft to_t; CURLofft to_t;
CURLofft from_t; CURLofft from_t;
from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW) { if(from_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR; return CURLE_RANGE_ERROR;
} }
@ -1772,7 +1775,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
} }
SSH_STRING_FREE_CHAR(sshc->homedir); SSH_STRING_FREE_CHAR(sshc->homedir);
conn->data->state.most_recent_ftp_entrypath = NULL; data->state.most_recent_ftp_entrypath = NULL;
state(conn, SSH_SESSION_DISCONNECT); state(conn, SSH_SESSION_DISCONNECT);
break; break;
@ -1808,7 +1811,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(!sshc->scp_session) { if(!sshc->scp_session) {
err_msg = ssh_get_error(sshc->ssh_session); err_msg = ssh_get_error(sshc->ssh_session);
failf(conn->data, "%s", err_msg); failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
} }
@ -1819,7 +1822,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session); rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) { if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session); err_msg = ssh_get_error(sshc->ssh_session);
failf(conn->data, "%s", err_msg); failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
} }
@ -1828,7 +1831,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
(int)data->set.new_file_perms); (int)data->set.new_file_perms);
if(rc != SSH_OK) { if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session); err_msg = ssh_get_error(sshc->ssh_session);
failf(conn->data, "%s", err_msg); failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
} }
@ -1856,7 +1859,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session); rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) { if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session); err_msg = ssh_get_error(sshc->ssh_session);
failf(conn->data, "%s", err_msg); failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
} }
state(conn, SSH_SCP_DOWNLOAD); state(conn, SSH_SCP_DOWNLOAD);
@ -1868,7 +1871,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_pull_request(sshc->scp_session); rc = ssh_scp_pull_request(sshc->scp_session);
if(rc != SSH_SCP_REQUEST_NEWFILE) { if(rc != SSH_SCP_REQUEST_NEWFILE) {
err_msg = ssh_get_error(sshc->ssh_session); err_msg = ssh_get_error(sshc->ssh_session);
failf(conn->data, "%s", err_msg); failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND); MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
break; break;
} }
@ -1938,7 +1941,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_disconnect(sshc->ssh_session); ssh_disconnect(sshc->ssh_session);
SSH_STRING_FREE_CHAR(sshc->homedir); SSH_STRING_FREE_CHAR(sshc->homedir);
conn->data->state.most_recent_ftp_entrypath = NULL; data->state.most_recent_ftp_entrypath = NULL;
state(conn, SSH_SESSION_FREE); state(conn, SSH_SESSION_FREE);
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -2015,10 +2018,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and /* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
static int myssh_perform_getsock(const struct connectdata *conn, static int myssh_getsock(struct Curl_easy *data,
curl_socket_t *sock) struct connectdata *conn,
curl_socket_t *sock)
{ {
int bitmap = GETSOCK_BLANK; int bitmap = GETSOCK_BLANK;
(void)data;
sock[0] = conn->sock[FIRSTSOCKET]; sock[0] = conn->sock[FIRSTSOCKET];
if(conn->waitfor & KEEP_RECV) if(conn->waitfor & KEEP_RECV)
@ -2030,16 +2035,6 @@ static int myssh_perform_getsock(const struct connectdata *conn,
return bitmap; return bitmap;
} }
/* Generic function called by the multi interface to figure out what socket(s)
to wait for and for what actions during the DOING and PROTOCONNECT states*/
static int myssh_getsock(struct connectdata *conn,
curl_socket_t *sock)
{
/* if we know the direction we can use the generic *_getsock() function even
for the protocol_connect and doing states */
return myssh_perform_getsock(conn, sock);
}
static void myssh_block2waitfor(struct connectdata *conn, bool block) static void myssh_block2waitfor(struct connectdata *conn, bool block)
{ {
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
@ -2061,13 +2056,14 @@ static void myssh_block2waitfor(struct connectdata *conn, bool block)
} }
/* called repeatedly until done from multi.c */ /* called repeatedly until done from multi.c */
static CURLcode myssh_multi_statemach(struct connectdata *conn, static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done) bool *done)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
bool block; /* we store the status and use that to provide a ssh_getsock() bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */ implementation */
CURLcode result = myssh_statemach_act(conn, &block); CURLcode result = myssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE; *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
myssh_block2waitfor(conn, block); myssh_block2waitfor(conn, block);
@ -2075,19 +2071,19 @@ static CURLcode myssh_multi_statemach(struct connectdata *conn,
return result; return result;
} }
static CURLcode myssh_block_statemach(struct connectdata *conn, static CURLcode myssh_block_statemach(struct Curl_easy *data,
bool disconnect) bool disconnect)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) { while((sshc->state != SSH_STOP) && !result) {
bool block; bool block;
timediff_t left = 1000; timediff_t left = 1000;
struct curltime now = Curl_now(); struct curltime now = Curl_now();
result = myssh_statemach_act(conn, &block); result = myssh_statemach_act(data, &block);
if(result) if(result)
break; break;
@ -2121,11 +2117,13 @@ static CURLcode myssh_block_statemach(struct connectdata *conn,
/* /*
* SSH setup connection * SSH setup connection
*/ */
static CURLcode myssh_setup_connection(struct connectdata *conn) static CURLcode myssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct SSHPROTO *ssh; struct SSHPROTO *ssh;
(void)conn;
conn->data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh) if(!ssh)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -2139,17 +2137,17 @@ static Curl_send scp_send, sftp_send;
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. * do protocol-specific actions at connect-time.
*/ */
static CURLcode myssh_connect(struct connectdata *conn, bool *done) static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
{ {
struct ssh_conn *ssh; struct ssh_conn *ssh;
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
struct Curl_easy *data = conn->data;
int rc; int rc;
/* initialize per-handle data if not already */ /* initialize per-handle data if not already */
if(!data->req.p.ssh) if(!data->req.p.ssh)
myssh_setup_connection(conn); myssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect /* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */ function to make the re-use checks properly be able to check this bit. */
@ -2244,20 +2242,20 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done)
state(conn, SSH_INIT); state(conn, SSH_INIT);
result = myssh_multi_statemach(conn, done); result = myssh_multi_statemach(data, done);
return result; return result;
} }
/* called from multi.c while DOing */ /* called from multi.c while DOing */
static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done) static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
{ {
CURLcode result; CURLcode result;
result = myssh_multi_statemach(conn, dophase_done); result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
@ -2272,34 +2270,35 @@ static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
*/ */
static static
CURLcode scp_perform(struct connectdata *conn, CURLcode scp_perform(struct Curl_easy *data,
bool *connected, bool *dophase_done) bool *connected, bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */ /* start the first command in the DO phase */
state(conn, SSH_SCP_TRANS_INIT); state(conn, SSH_SCP_TRANS_INIT);
result = myssh_multi_statemach(conn, dophase_done); result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET]; *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
static CURLcode myssh_do_it(struct connectdata *conn, bool *done) static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
{ {
CURLcode result; CURLcode result;
bool connected = 0; bool connected = 0;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
@ -2316,9 +2315,9 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1); Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP) if(conn->handler->protocol & CURLPROTO_SCP)
result = scp_perform(conn, &connected, done); result = scp_perform(data, &connected, done);
else else
result = sftp_perform(conn, &connected, done); result = sftp_perform(data, &connected, done);
return result; return result;
} }
@ -2326,7 +2325,8 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
/* BLOCKING, but the function is using the state machine so the only reason /* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */ disconnecting operations that takes a while */
static CURLcode scp_disconnect(struct connectdata *conn, static CURLcode scp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection) bool dead_connection)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -2338,7 +2338,7 @@ static CURLcode scp_disconnect(struct connectdata *conn,
state(conn, SSH_SESSION_DISCONNECT); state(conn, SSH_SESSION_DISCONNECT);
result = myssh_block_statemach(conn, TRUE); result = myssh_block_statemach(data, TRUE);
} }
return result; return result;
@ -2346,44 +2346,45 @@ static CURLcode scp_disconnect(struct connectdata *conn,
/* generic done function for both SCP and SFTP called from their specific /* generic done function for both SCP and SFTP called from their specific
done functions */ done functions */
static CURLcode myssh_done(struct connectdata *conn, CURLcode status) static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SSHPROTO *protop = conn->data->req.p.ssh; struct SSHPROTO *protop = data->req.p.ssh;
if(!status) { if(!status) {
/* run the state-machine */ /* run the state-machine */
result = myssh_block_statemach(conn, FALSE); result = myssh_block_statemach(data, FALSE);
} }
else else
result = status; result = status;
if(protop) if(protop)
Curl_safefree(protop->path); Curl_safefree(protop->path);
if(Curl_pgrsDone(conn)) if(Curl_pgrsDone(data->conn))
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
conn->data->req.keepon = 0; /* clear all bits */ data->req.keepon = 0; /* clear all bits */
return result; return result;
} }
static CURLcode scp_done(struct connectdata *conn, CURLcode status, static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
(void) premature; /* not used */ (void) premature; /* not used */
if(!status) if(!status)
state(conn, SSH_SCP_DONE); state(data->conn, SSH_SCP_DONE);
return myssh_done(conn, status); return myssh_done(data, status);
} }
static ssize_t scp_send(struct connectdata *conn, int sockindex, static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err) const void *mem, size_t len, CURLcode *err)
{ {
int rc; int rc;
struct connectdata *conn = data->conn;
(void) sockindex; /* we only support SCP on the fixed known primary socket */ (void) sockindex; /* we only support SCP on the fixed known primary socket */
(void) err; (void) err;
@ -2409,10 +2410,11 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return len; return len;
} }
static ssize_t scp_recv(struct connectdata *conn, int sockindex, static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err) char *mem, size_t len, CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
struct connectdata *conn = data->conn;
(void) err; (void) err;
(void) sockindex; /* we only support SCP on the fixed known primary socket */ (void) sockindex; /* we only support SCP on the fixed known primary socket */
@ -2448,13 +2450,14 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/ */
static static
CURLcode sftp_perform(struct connectdata *conn, CURLcode sftp_perform(struct Curl_easy *data,
bool *connected, bool *connected,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
@ -2462,24 +2465,24 @@ CURLcode sftp_perform(struct connectdata *conn,
state(conn, SSH_SFTP_QUOTE_INIT); state(conn, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */ /* run the state-machine */
result = myssh_multi_statemach(conn, dophase_done); result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET]; *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
/* called from multi.c while DOing */ /* called from multi.c while DOing */
static CURLcode sftp_doing(struct connectdata *conn, static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = myssh_multi_statemach(conn, dophase_done); CURLcode result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
@ -2487,46 +2490,50 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* BLOCKING, but the function is using the state machine so the only reason /* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */ disconnecting operations that takes a while */
static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) static CURLcode sftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
(void) dead_connection; (void) dead_connection;
DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) { if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */ /* only if there's a session still around to use! */
state(conn, SSH_SFTP_SHUTDOWN); state(conn, SSH_SFTP_SHUTDOWN);
result = myssh_block_statemach(conn, TRUE); result = myssh_block_statemach(data, TRUE);
} }
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result; return result;
} }
static CURLcode sftp_done(struct connectdata *conn, CURLcode status, static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
if(!status) { if(!status) {
/* Post quote commands are executed after the SFTP_CLOSE state to avoid /* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE errors that could happen due to open file handles during POSTQUOTE
operation */ operation */
if(!premature && conn->data->set.postquote && !conn->bits.retry) if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
} }
return myssh_done(conn, status); return myssh_done(data, status);
} }
/* return number of sent bytes */ /* return number of sent bytes */
static ssize_t sftp_send(struct connectdata *conn, int sockindex, static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err) const void *mem, size_t len, CURLcode *err)
{ {
ssize_t nwrite; ssize_t nwrite;
struct connectdata *conn = data->conn;
(void)sockindex; (void)sockindex;
nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len); nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
@ -2552,10 +2559,11 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes * Return number of received (decrypted) bytes
* or <0 on error * or <0 on error
*/ */
static ssize_t sftp_recv(struct connectdata *conn, int sockindex, static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err) char *mem, size_t len, CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
struct connectdata *conn = data->conn;
(void)sockindex; (void)sockindex;
DEBUGASSERT(len < CURL_MAX_READ_SIZE); DEBUGASSERT(len < CURL_MAX_READ_SIZE);
@ -2563,8 +2571,8 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
switch(conn->proto.sshc.sftp_recv_state) { switch(conn->proto.sshc.sftp_recv_state) {
case 0: case 0:
conn->proto.sshc.sftp_file_index = conn->proto.sshc.sftp_file_index =
sftp_async_read_begin(conn->proto.sshc.sftp_file, sftp_async_read_begin(conn->proto.sshc.sftp_file,
(uint32_t)len); (uint32_t)len);
if(conn->proto.sshc.sftp_file_index < 0) { if(conn->proto.sshc.sftp_file_index < 0) {
*err = CURLE_RECV_ERROR; *err = CURLE_RECV_ERROR;
return -1; return -1;
@ -2638,7 +2646,7 @@ static void sftp_quote(struct connectdata *conn)
/* this sends an FTP-like "header" to the header callback so that the /* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when current directory can be read very similar to how it is read when
using ordinary FTP. */ using ordinary FTP. */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp); free(tmp);
if(result) { if(result) {
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);

View file

@ -104,29 +104,23 @@ static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free); static LIBSSH2_FREE_FUNC(my_libssh2_free);
static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn); static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn);
static CURLcode ssh_connect(struct connectdata *conn, bool *done); static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
static CURLcode ssh_do(struct connectdata *conn, bool *done); static CURLcode ssh_do(struct Curl_easy *data, bool *done);
static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature);
static CURLcode scp_done(struct connectdata *conn, static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
CURLcode, bool premature); static CURLcode scp_disconnect(struct Curl_easy *data,
static CURLcode scp_doing(struct connectdata *conn, struct connectdata *conn, bool dead_connection);
bool *dophase_done); static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature);
static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection); static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode sftp_disconnect(struct Curl_easy *data,
static CURLcode sftp_done(struct connectdata *conn, struct connectdata *conn, bool dead);
CURLcode, bool premature); static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
static CURLcode sftp_doing(struct connectdata *conn, bool *dophase_done);
bool *dophase_done); static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); curl_socket_t *sock);
static static CURLcode ssh_setup_connection(struct Curl_easy *data,
CURLcode sftp_perform(struct connectdata *conn, struct connectdata *conn);
bool *connected,
bool *dophase_done);
static int ssh_getsock(struct connectdata *conn, curl_socket_t *sock);
static int ssh_perform_getsock(const struct connectdata *conn,
curl_socket_t *sock);
static CURLcode ssh_setup_connection(struct connectdata *conn);
/* /*
* SCP protocol handler. * SCP protocol handler.
@ -144,7 +138,7 @@ const struct Curl_handler Curl_handler_scp = {
ssh_getsock, /* proto_getsock */ ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */ ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
ssh_perform_getsock, /* perform_getsock */ ssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */ scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */ ZERO_NULL, /* connection_check */
@ -172,7 +166,7 @@ const struct Curl_handler Curl_handler_sftp = {
ssh_getsock, /* proto_getsock */ ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */ ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* domore_getsock */
ssh_perform_getsock, /* perform_getsock */ ssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */ sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */ ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */ ZERO_NULL, /* connection_check */
@ -794,10 +788,10 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
* meaning it wants to be called again when the socket is ready * meaning it wants to be called again when the socket is ready
*/ */
static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct SSHPROTO *sftp_scp = data->req.p.ssh; struct SSHPROTO *sftp_scp = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
@ -1196,7 +1190,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/ */
infof(data, "Authentication complete\n"); infof(data, "Authentication complete\n");
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
conn->sockfd = sock; conn->sockfd = sock;
conn->writesockfd = CURL_SOCKET_BAD; conn->writesockfd = CURL_SOCKET_BAD;
@ -1253,7 +1247,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_OUT_OF_MEMORY; sshc->actualcode = CURLE_OUT_OF_MEMORY;
break; break;
} }
conn->data->state.most_recent_ftp_entrypath = sshc->homedir; data->state.most_recent_ftp_entrypath = sshc->homedir;
} }
else { else {
/* Return the error type */ /* Return the error type */
@ -1349,7 +1343,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* this sends an FTP-like "header" to the header callback so that the /* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when current directory can be read very similar to how it is read when
using ordinary FTP. */ using ordinary FTP. */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp); free(tmp);
if(result) { if(result) {
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
@ -1802,7 +1796,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break; break;
} }
result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp); free(tmp);
if(result) { if(result) {
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
@ -2151,11 +2145,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_filename[readdir_len] = '\0'; sshc->readdir_filename[readdir_len] = '\0';
if(data->set.ftp_list_only) { if(data->set.ftp_list_only) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
sshc->readdir_filename, sshc->readdir_filename,
readdir_len); readdir_len);
if(!result) if(!result)
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)"\n", 1); (char *)"\n", 1);
if(result) { if(result) {
state(conn, SSH_STOP); state(conn, SSH_STOP);
@ -2243,7 +2237,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_BOTTOM: case SSH_SFTP_READDIR_BOTTOM:
result = Curl_dyn_addn(&sshc->readdir, "\n", 1); result = Curl_dyn_addn(&sshc->readdir, "\n", 1);
if(!result) if(!result)
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&sshc->readdir), Curl_dyn_ptr(&sshc->readdir),
Curl_dyn_len(&sshc->readdir)); Curl_dyn_len(&sshc->readdir));
@ -2335,14 +2329,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME; return CURLE_BAD_DOWNLOAD_RESUME;
} }
if(conn->data->state.use_range) { if(data->state.use_range) {
curl_off_t from, to; curl_off_t from, to;
char *ptr; char *ptr;
char *ptr2; char *ptr2;
CURLofft to_t; CURLofft to_t;
CURLofft from_t; CURLofft from_t;
from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW) if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR; return CURLE_RANGE_ERROR;
while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
@ -2503,7 +2497,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
} }
Curl_safefree(sshc->homedir); Curl_safefree(sshc->homedir);
conn->data->state.most_recent_ftp_entrypath = NULL; data->state.most_recent_ftp_entrypath = NULL;
state(conn, SSH_SESSION_DISCONNECT); state(conn, SSH_SESSION_DISCONNECT);
break; break;
@ -2552,7 +2546,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0)); &err_msg, NULL, 0));
failf(conn->data, "%s", err_msg); failf(data, "%s", err_msg);
state(conn, SSH_SCP_CHANNEL_FREE); state(conn, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
/* Map generic errors to upload failed */ /* Map generic errors to upload failed */
@ -2627,7 +2621,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0)); &err_msg, NULL, 0));
failf(conn->data, "%s", err_msg); failf(data, "%s", err_msg);
state(conn, SSH_SCP_CHANNEL_FREE); state(conn, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
break; break;
@ -2768,7 +2762,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
} }
Curl_safefree(sshc->homedir); Curl_safefree(sshc->homedir);
conn->data->state.most_recent_ftp_entrypath = NULL; data->state.most_recent_ftp_entrypath = NULL;
state(conn, SSH_SESSION_FREE); state(conn, SSH_SESSION_FREE);
break; break;
@ -2877,10 +2871,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and /* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
static int ssh_perform_getsock(const struct connectdata *conn, static int ssh_getsock(struct Curl_easy *data,
curl_socket_t *sock) struct connectdata *conn,
curl_socket_t *sock)
{ {
int bitmap = GETSOCK_BLANK; int bitmap = GETSOCK_BLANK;
(void)data;
sock[0] = conn->sock[FIRSTSOCKET]; sock[0] = conn->sock[FIRSTSOCKET];
@ -2893,16 +2889,6 @@ static int ssh_perform_getsock(const struct connectdata *conn,
return bitmap; return bitmap;
} }
/* Generic function called by the multi interface to figure out what socket(s)
to wait for and for what actions during the DOING and PROTOCONNECT states*/
static int ssh_getsock(struct connectdata *conn,
curl_socket_t *sock)
{
/* if we know the direction we can use the generic *_getsock() function even
for the protocol_connect and doing states */
return ssh_perform_getsock(conn, sock);
}
/* /*
* When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
* function is used to figure out in what direction and stores this info so * function is used to figure out in what direction and stores this info so
@ -2929,14 +2915,15 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
} }
/* called repeatedly until done from multi.c */ /* called repeatedly until done from multi.c */
static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock() bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */ implementation */
do { do {
result = ssh_statemach_act(conn, &block); result = ssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE; *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */ try again */
@ -2946,19 +2933,19 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
return result; return result;
} }
static CURLcode ssh_block_statemach(struct connectdata *conn, static CURLcode ssh_block_statemach(struct Curl_easy *data,
bool duringconnect) bool duringconnect)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) { while((sshc->state != SSH_STOP) && !result) {
bool block; bool block;
timediff_t left = 1000; timediff_t left = 1000;
struct curltime now = Curl_now(); struct curltime now = Curl_now();
result = ssh_statemach_act(conn, &block); result = ssh_statemach_act(data, &block);
if(result) if(result)
break; break;
@ -2996,11 +2983,13 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
/* /*
* SSH setup and connection * SSH setup and connection
*/ */
static CURLcode ssh_setup_connection(struct connectdata *conn) static CURLcode ssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{ {
struct SSHPROTO *ssh; struct SSHPROTO *ssh;
(void)conn;
conn->data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh) if(!ssh)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -3024,7 +3013,7 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
/* swap in the TLS reader function for this call only, and then swap back /* swap in the TLS reader function for this call only, and then swap back
the SSH one again */ the SSH one again */
conn->recv[0] = ssh->tls_recv; conn->recv[0] = ssh->tls_recv;
result = Curl_read(conn, sock, buffer, length, &nread); result = Curl_read(conn->data, sock, buffer, length, &nread);
conn->recv[0] = backup; conn->recv[0] = backup;
if(result == CURLE_AGAIN) if(result == CURLE_AGAIN)
return -EAGAIN; /* magic return code for libssh2 */ return -EAGAIN; /* magic return code for libssh2 */
@ -3047,7 +3036,7 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
/* swap in the TLS writer function for this call only, and then swap back /* swap in the TLS writer function for this call only, and then swap back
the SSH one again */ the SSH one again */
conn->send[0] = ssh->tls_send; conn->send[0] = ssh->tls_send;
result = Curl_write(conn, sock, buffer, length, &nwrite); result = Curl_write(conn->data, sock, buffer, length, &nwrite);
conn->send[0] = backup; conn->send[0] = backup;
if(result == CURLE_AGAIN) if(result == CURLE_AGAIN)
return -EAGAIN; /* magic return code for libssh2 */ return -EAGAIN; /* magic return code for libssh2 */
@ -3062,18 +3051,18 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. * do protocol-specific actions at connect-time.
*/ */
static CURLcode ssh_connect(struct connectdata *conn, bool *done) static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
{ {
#ifdef CURL_LIBSSH2_DEBUG #ifdef CURL_LIBSSH2_DEBUG
curl_socket_t sock; curl_socket_t sock;
#endif #endif
struct ssh_conn *ssh; struct ssh_conn *ssh;
CURLcode result; CURLcode result;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
/* initialize per-handle data if not already */ /* initialize per-handle data if not already */
if(!data->req.p.ssh) if(!data->req.p.ssh)
ssh_setup_connection(conn); ssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect /* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */ function to make the re-use checks properly be able to check this bit. */
@ -3187,7 +3176,7 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
state(conn, SSH_INIT); state(conn, SSH_INIT);
result = ssh_multi_statemach(conn, done); result = ssh_multi_statemach(data, done);
return result; return result;
} }
@ -3202,13 +3191,14 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
*/ */
static static
CURLcode scp_perform(struct connectdata *conn, CURLcode scp_perform(struct Curl_easy *data,
bool *connected, bool *connected,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
@ -3216,7 +3206,7 @@ CURLcode scp_perform(struct connectdata *conn,
state(conn, SSH_SCP_TRANS_INIT); state(conn, SSH_SCP_TRANS_INIT);
/* run the state-machine */ /* run the state-machine */
result = ssh_multi_statemach(conn, dophase_done); result = ssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET]; *connected = conn->bits.tcpconnect[FIRSTSOCKET];
@ -3228,14 +3218,14 @@ CURLcode scp_perform(struct connectdata *conn,
} }
/* called from multi.c while DOing */ /* called from multi.c while DOing */
static CURLcode scp_doing(struct connectdata *conn, static CURLcode scp_doing(struct Curl_easy *data,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result; CURLcode result;
result = ssh_multi_statemach(conn, dophase_done); result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
@ -3245,11 +3235,11 @@ static CURLcode scp_doing(struct connectdata *conn,
* separate ones but this way means less duplicated code. * separate ones but this way means less duplicated code.
*/ */
static CURLcode ssh_do(struct connectdata *conn, bool *done) static CURLcode ssh_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result; CURLcode result;
bool connected = 0; bool connected = 0;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
@ -3266,9 +3256,9 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1); Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP) if(conn->handler->protocol & CURLPROTO_SCP)
result = scp_perform(conn, &connected, done); result = scp_perform(data, &connected, done);
else else
result = sftp_perform(conn, &connected, done); result = sftp_perform(data, &connected, done);
return result; return result;
} }
@ -3276,7 +3266,9 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
/* BLOCKING, but the function is using the state machine so the only reason /* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */ disconnecting operations that takes a while */
static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) static CURLcode scp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct ssh_conn *ssh = &conn->proto.sshc; struct ssh_conn *ssh = &conn->proto.sshc;
@ -3287,7 +3279,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
state(conn, SSH_SESSION_DISCONNECT); state(conn, SSH_SESSION_DISCONNECT);
result = ssh_block_statemach(conn, FALSE); result = ssh_block_statemach(data, FALSE);
} }
return result; return result;
@ -3295,44 +3287,45 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
/* generic done function for both SCP and SFTP called from their specific /* generic done function for both SCP and SFTP called from their specific
done functions */ done functions */
static CURLcode ssh_done(struct connectdata *conn, CURLcode status) static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SSHPROTO *sftp_scp = conn->data->req.p.ssh; struct SSHPROTO *sftp_scp = data->req.p.ssh;
if(!status) { if(!status) {
/* run the state-machine */ /* run the state-machine */
result = ssh_block_statemach(conn, FALSE); result = ssh_block_statemach(data, FALSE);
} }
else else
result = status; result = status;
if(sftp_scp) if(sftp_scp)
Curl_safefree(sftp_scp->path); Curl_safefree(sftp_scp->path);
if(Curl_pgrsDone(conn)) if(Curl_pgrsDone(data->conn))
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
conn->data->req.keepon = 0; /* clear all bits */ data->req.keepon = 0; /* clear all bits */
return result; return result;
} }
static CURLcode scp_done(struct connectdata *conn, CURLcode status, static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
(void)premature; /* not used */ (void)premature; /* not used */
if(!status) if(!status)
state(conn, SSH_SCP_DONE); state(data->conn, SSH_SCP_DONE);
return ssh_done(conn, status); return ssh_done(data, status);
} }
static ssize_t scp_send(struct connectdata *conn, int sockindex, static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err) const void *mem, size_t len, CURLcode *err)
{ {
ssize_t nwrite; ssize_t nwrite;
struct connectdata *conn = data->conn;
(void)sockindex; /* we only support SCP on the fixed known primary socket */ (void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_write() returns int! */ /* libssh2_channel_write() returns int! */
@ -3353,10 +3346,11 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return nwrite; return nwrite;
} }
static ssize_t scp_recv(struct connectdata *conn, int sockindex, static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err) char *mem, size_t len, CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
struct connectdata *conn = data->conn;
(void)sockindex; /* we only support SCP on the fixed known primary socket */ (void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_read() returns int */ /* libssh2_channel_read() returns int */
@ -3386,39 +3380,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/ */
static static
CURLcode sftp_perform(struct connectdata *conn, CURLcode sftp_perform(struct Curl_easy *data,
bool *connected, bool *connected,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */ /* start the first command in the DO phase */
state(conn, SSH_SFTP_QUOTE_INIT); state(data->conn, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */ /* run the state-machine */
result = ssh_multi_statemach(conn, dophase_done); result = ssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET]; *connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
/* called from multi.c while DOing */ /* called from multi.c while DOing */
static CURLcode sftp_doing(struct connectdata *conn, static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = ssh_multi_statemach(conn, dophase_done); CURLcode result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
@ -3426,28 +3420,30 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* BLOCKING, but the function is using the state machine so the only reason /* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */ disconnecting operations that takes a while */
static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) static CURLcode sftp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
(void) dead_connection; (void) dead_connection;
DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) { if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */ /* only if there's a session still around to use! */
state(conn, SSH_SFTP_SHUTDOWN); state(conn, SSH_SFTP_SHUTDOWN);
result = ssh_block_statemach(conn, FALSE); result = ssh_block_statemach(data, FALSE);
} }
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result; return result;
} }
static CURLcode sftp_done(struct connectdata *conn, CURLcode status, static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
bool premature) bool premature)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
if(!status) { if(!status) {
@ -3458,16 +3454,15 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
} }
return ssh_done(conn, status); return ssh_done(data, status);
} }
/* return number of sent bytes */ /* return number of sent bytes */
static ssize_t sftp_send(struct connectdata *conn, int sockindex, static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err) const void *mem, size_t len, CURLcode *err)
{ {
ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 ssize_t nwrite;
but is changed to ssize_t in 0.15. These days we don't struct connectdata *conn = data->conn;
support libssh2 0.15*/
(void)sockindex; (void)sockindex;
nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len); nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
@ -3490,10 +3485,11 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes * Return number of received (decrypted) bytes
* or <0 on error * or <0 on error
*/ */
static ssize_t sftp_recv(struct connectdata *conn, int sockindex, static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err) char *mem, size_t len, CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
struct connectdata *conn = data->conn;
(void)sockindex; (void)sockindex;
nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len); nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);

View file

@ -45,27 +45,28 @@
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
static CURLcode wssh_connect(struct connectdata *conn, bool *done); static CURLcode wssh_connect(struct Curl_easy *data, bool *done);
static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done); static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done);
static CURLcode wssh_do(struct connectdata *conn, bool *done); static CURLcode wssh_do(struct Curl_easy *data, bool *done);
#if 0 #if 0
static CURLcode wscp_done(struct connectdata *conn, static CURLcode wscp_done(struct Curl_easy *data,
CURLcode, bool premature); CURLcode, bool premature);
static CURLcode wscp_doing(struct connectdata *conn, static CURLcode wscp_doing(struct Curl_easy *data,
bool *dophase_done); bool *dophase_done);
static CURLcode wscp_disconnect(struct connectdata *conn, static CURLcode wscp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection); bool dead_connection);
#endif #endif
static CURLcode wsftp_done(struct connectdata *conn, static CURLcode wsftp_done(struct Curl_easy *data,
CURLcode, bool premature); CURLcode, bool premature);
static CURLcode wsftp_doing(struct connectdata *conn, static CURLcode wsftp_doing(struct Curl_easy *data,
bool *dophase_done); bool *dophase_done);
static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead); static CURLcode wsftp_disconnect(struct Curl_easy *data, bool dead);
static int wssh_getsock(struct connectdata *conn, static int wssh_getsock(struct connectdata *conn,
curl_socket_t *sock); curl_socket_t *sock);
static int wssh_perform_getsock(const struct connectdata *conn, static int wssh_perform_getsock(struct connectdata *conn,
curl_socket_t *sock); curl_socket_t *sock);
static CURLcode wssh_setup_connection(struct connectdata *conn); static CURLcode wssh_setup_connection(struct Curl_easy *data);
#if 0 #if 0
/* /*
@ -118,6 +119,7 @@ const struct Curl_handler Curl_handler_sftp = {
ZERO_NULL, /* connection_check */ ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */ PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */ | PROTOPT_NOURLQUERY /* flags */
}; };
@ -318,11 +320,11 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
/* /*
* SSH setup and connection * SSH setup and connection
*/ */
static CURLcode wssh_setup_connection(struct connectdata *conn) static CURLcode wssh_setup_connection(struct Curl_easy *data)
{ {
struct SSHPROTO *ssh; struct SSHPROTO *ssh;
conn->data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh) if(!ssh)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -348,16 +350,16 @@ static int userauth(byte authtype,
return 0; return 0;
} }
static CURLcode wssh_connect(struct connectdata *conn, bool *done) static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct ssh_conn *sshc; struct ssh_conn *sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc; int rc;
/* initialize per-handle data if not already */ /* initialize per-handle data if not already */
if(!data->req.p.ssh) if(!data->req.p.ssh)
wssh_setup_connection(conn); wssh_setup_connection(data);
/* We default to persistent connections. We set this already in this connect /* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */ function to make the re-use checks properly be able to check this bit. */
@ -410,7 +412,7 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
else else
state(conn, SSH_SFTP_INIT); state(conn, SSH_SFTP_INIT);
return wssh_multi_statemach(conn, done); return wssh_multi_statemach(data, done);
error: error:
wolfSSH_free(sshc->ssh_session); wolfSSH_free(sshc->ssh_session);
wolfSSH_CTX_free(sshc->ctx); wolfSSH_CTX_free(sshc->ctx);
@ -424,11 +426,11 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
* wants to be called again when the socket is ready * wants to be called again when the socket is ready
*/ */
static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block) static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
struct Curl_easy *data = conn->data;
struct SSHPROTO *sftp_scp = data->req.p.ssh; struct SSHPROTO *sftp_scp = data->req.p.ssh;
WS_SFTPNAME *name; WS_SFTPNAME *name;
int rc = 0; int rc = 0;
@ -762,7 +764,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
/* We cannot seek with wolfSSH so resuming and range requests are not /* We cannot seek with wolfSSH so resuming and range requests are not
possible */ possible */
if(conn->data->state.use_range || data->state.resume_from) { if(data->state.use_range || data->state.resume_from) {
infof(data, "wolfSSH cannot do range/seek on SFTP\n"); infof(data, "wolfSSH cannot do range/seek on SFTP\n");
return CURLE_BAD_DOWNLOAD_RESUME; return CURLE_BAD_DOWNLOAD_RESUME;
} }
@ -887,19 +889,20 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
} }
/* called repeatedly until done from multi.c */ /* called repeatedly until done from multi.c */
static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done) static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock() bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */ implementation */
do { do {
result = wssh_statemach_act(conn, &block); result = wssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE; *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */ try again */
if(*done) { if(*done) {
DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n")); DEBUGF(infof(data, "wssh_statemach_act says DONE\n"));
} }
} while(!result && !*done && !block); } while(!result && !*done && !block);
@ -907,24 +910,25 @@ static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done)
} }
static static
CURLcode wscp_perform(struct connectdata *conn, CURLcode wscp_perform(struct Curl_easy *data,
bool *connected, bool *connected,
bool *dophase_done) bool *dophase_done)
{ {
(void)conn; (void)data;
(void)connected; (void)connected;
(void)dophase_done; (void)dophase_done;
return CURLE_OK; return CURLE_OK;
} }
static static
CURLcode wsftp_perform(struct connectdata *conn, CURLcode wsftp_perform(struct Curl_easy *data,
bool *connected, bool *connected,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
@ -932,12 +936,12 @@ CURLcode wsftp_perform(struct connectdata *conn,
state(conn, SSH_SFTP_QUOTE_INIT); state(conn, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */ /* run the state-machine */
result = wssh_multi_statemach(conn, dophase_done); result = wssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET]; *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
@ -946,11 +950,11 @@ CURLcode wsftp_perform(struct connectdata *conn,
/* /*
* The DO function is generic for both protocols. * The DO function is generic for both protocols.
*/ */
static CURLcode wssh_do(struct connectdata *conn, bool *done) static CURLcode wssh_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result; CURLcode result;
bool connected = 0; bool connected = 0;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
@ -965,26 +969,26 @@ static CURLcode wssh_do(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1); Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP) if(conn->handler->protocol & CURLPROTO_SCP)
result = wscp_perform(conn, &connected, done); result = wscp_perform(data, &connected, done);
else else
result = wsftp_perform(conn, &connected, done); result = wsftp_perform(data, &connected, done);
return result; return result;
} }
static CURLcode wssh_block_statemach(struct connectdata *conn, static CURLcode wssh_block_statemach(struct Curl_easy *data,
bool disconnect) bool disconnect)
{ {
struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) { while((sshc->state != SSH_STOP) && !result) {
bool block; bool block;
timediff_t left = 1000; timediff_t left = 1000;
struct curltime now = Curl_now(); struct curltime now = Curl_now();
result = wssh_statemach_act(conn, &block); result = wssh_statemach_act(data, &block);
if(result) if(result)
break; break;
@ -1024,14 +1028,15 @@ static CURLcode wssh_block_statemach(struct connectdata *conn,
/* generic done function for both SCP and SFTP called from their specific /* generic done function for both SCP and SFTP called from their specific
done functions */ done functions */
static CURLcode wssh_done(struct connectdata *conn, CURLcode status) static CURLcode wssh_done(struct Curl_easy *data, CURLcode status)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SSHPROTO *sftp_scp = conn->data->req.p.ssh; struct connectdata *conn = data->conn;
struct SSHPROTO *sftp_scp = data->req.p.ssh;
if(!status) { if(!status) {
/* run the state-machine */ /* run the state-machine */
result = wssh_block_statemach(conn, FALSE); result = wssh_block_statemach(data, FALSE);
} }
else else
result = status; result = status;
@ -1041,12 +1046,12 @@ static CURLcode wssh_done(struct connectdata *conn, CURLcode status)
if(Curl_pgrsDone(conn)) if(Curl_pgrsDone(conn))
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
conn->data->req.keepon = 0; /* clear all bits */ data->req.keepon = 0; /* clear all bits */
return result; return result;
} }
#if 0 #if 0
static CURLcode wscp_done(struct connectdata *conn, static CURLcode wscp_done(struct Curl_easy *data,
CURLcode code, bool premature) CURLcode code, bool premature)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1057,7 +1062,7 @@ static CURLcode wscp_done(struct connectdata *conn,
return result; return result;
} }
static CURLcode wscp_doing(struct connectdata *conn, static CURLcode wscp_doing(struct Curl_easy *data,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1067,9 +1072,11 @@ static CURLcode wscp_doing(struct connectdata *conn,
return result; return result;
} }
static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection) static CURLcode wscp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
(void)data;
(void)conn; (void)conn;
(void)dead_connection; (void)dead_connection;
@ -1077,40 +1084,41 @@ static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)
} }
#endif #endif
static CURLcode wsftp_done(struct connectdata *conn, static CURLcode wsftp_done(struct Curl_easy *data,
CURLcode code, bool premature) CURLcode code, bool premature)
{ {
(void)premature; (void)premature;
state(conn, SSH_SFTP_CLOSE); state(data->conn, SSH_SFTP_CLOSE);
return wssh_done(conn, code); return wssh_done(data, code);
} }
static CURLcode wsftp_doing(struct connectdata *conn, static CURLcode wsftp_doing(struct Curl_easy *data,
bool *dophase_done) bool *dophase_done)
{ {
CURLcode result = wssh_multi_statemach(conn, dophase_done); CURLcode result = wssh_multi_statemach(data, dophase_done);
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(data, "DO phase is complete\n"));
} }
return result; return result;
} }
static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead) static CURLcode wsftp_disconnect(struct Curl_easy *data, bool dead)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
(void)dead; (void)dead;
DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) { if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */ /* only if there's a session still around to use! */
state(conn, SSH_SFTP_SHUTDOWN); state(conn, SSH_SFTP_SHUTDOWN);
result = wssh_block_statemach(conn, TRUE); result = wssh_block_statemach(data, TRUE);
} }
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result; return result;
} }
@ -1120,7 +1128,7 @@ static int wssh_getsock(struct connectdata *conn,
return wssh_perform_getsock(conn, sock); return wssh_perform_getsock(conn, sock);
} }
static int wssh_perform_getsock(const struct connectdata *conn, static int wssh_perform_getsock(struct connectdata *conn,
curl_socket_t *sock) curl_socket_t *sock)
{ {
int bitmap = GETSOCK_BLANK; int bitmap = GETSOCK_BLANK;

View file

@ -552,7 +552,7 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
conn->negnpn = CURL_HTTP_VERSION_1_1; conn->negnpn = CURL_HTTP_VERSION_1_1;
else else
infof(data, "ALPN, unrecognized protocol %s\n", protocol); infof(data, "ALPN, unrecognized protocol %s\n", protocol);
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
} }
else else
@ -585,10 +585,10 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
return CURLE_OK; return CURLE_OK;
} }
static ssize_t bearssl_send(struct connectdata *conn, int sockindex, static ssize_t bearssl_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err) const void *buf, size_t len, CURLcode *err)
{ {
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
unsigned char *app; unsigned char *app;
@ -618,9 +618,10 @@ static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
} }
} }
static ssize_t bearssl_recv(struct connectdata *conn, int sockindex, static ssize_t bearssl_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t len, CURLcode *err) char *buf, size_t len, CURLcode *err)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
unsigned char *app; unsigned char *app;

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -301,10 +301,9 @@ static CURLcode set_callback(struct Curl_easy *data,
} }
static CURLcode set_ciphers(struct connectdata *conn, static CURLcode set_ciphers(struct Curl_easy *data,
gsk_handle h, unsigned int *protoflags) gsk_handle h, unsigned int *protoflags)
{ {
struct Curl_easy *data = conn->data;
const char *cipherlist = SSL_CONN_CONFIG(cipher_list); const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
const char *clp; const char *clp;
const struct gskit_cipher *ctp; const struct gskit_cipher *ctp;
@ -435,7 +434,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
} }
static int Curl_gskit_init(void) static int gskit_init(void)
{ {
/* No initialisation needed. */ /* No initialisation needed. */
@ -443,7 +442,7 @@ static int Curl_gskit_init(void)
} }
static void Curl_gskit_cleanup(void) static void gskit_cleanup(void)
{ {
/* Nothing to do. */ /* Nothing to do. */
} }
@ -587,11 +586,11 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
} }
static void close_one(struct ssl_connect_data *connssl, static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
struct connectdata *conn, int sockindex) struct connectdata *conn, int sockindex)
{ {
if(BACKEND->handle) { if(BACKEND->handle) {
gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle), gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
"gsk_secure_soc_close()", 0); "gsk_secure_soc_close()", 0);
/* Last chance to drain output. */ /* Last chance to drain output. */
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
@ -611,11 +610,11 @@ static void close_one(struct ssl_connect_data *connssl,
} }
static ssize_t gskit_send(struct connectdata *conn, int sockindex, static ssize_t real_gskit_send(struct Curl_easy *data,
const void *mem, size_t len, CURLcode *curlcode) struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
CURLcode cc = CURLE_SEND_ERROR; CURLcode cc = CURLE_SEND_ERROR;
int written; int written;
@ -635,12 +634,18 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
return (ssize_t) written; /* number of bytes */ return (ssize_t) written; /* number of bytes */
} }
static ssize_t gskit_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *curlcode)
{
return real_gskit_send(conn->data, conn, sockindex, mem, len, curlcode);
}
static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
size_t buffersize, CURLcode *curlcode) static ssize_t real_gskit_recv(struct Curl_easy *data,
struct connectdata *conn, int num, char *buf,
size_t buffersize, CURLcode *curlcode)
{ {
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
struct Curl_easy *data = conn->data;
int nread; int nread;
CURLcode cc = CURLE_RECV_ERROR; CURLcode cc = CURLE_RECV_ERROR;
@ -663,10 +668,15 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
return (ssize_t) nread; return (ssize_t) nread;
} }
static CURLcode static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn) size_t buffersize, CURLcode *curlcode)
{
return real_gskit_recv(conn->data, conn, num, buf, buffersize, curlcode);
}
static CURLcode
set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
{ {
struct Curl_easy *data = conn->data;
long ssl_version = SSL_CONN_CONFIG(version); long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max); long ssl_version_max = SSL_CONN_CONFIG(version_max);
long i = ssl_version; long i = ssl_version;
@ -696,9 +706,9 @@ set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) static CURLcode gskit_connect_step1(struct Curl_easy *data,
struct connectdata *conn, int sockindex)
{ {
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
gsk_handle envir; gsk_handle envir;
CURLcode result; CURLcode result;
@ -798,7 +808,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3: case CURL_SSLVERSION_TLSv1_3:
result = set_ssl_version_min_max(&protoflags, conn); result = set_ssl_version_min_max(&protoflags, data);
if(result != CURLE_OK) if(result != CURLE_OK)
return result; return result;
break; break;
@ -832,7 +842,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
BACKEND->localfd: conn->sock[sockindex]); BACKEND->localfd: conn->sock[sockindex]);
if(!result) if(!result)
result = set_ciphers(conn, BACKEND->handle, &protoflags); result = set_ciphers(data, BACKEND->handle, &protoflags);
if(!protoflags) { if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled"); failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER; result = CURLE_SSL_CIPHER;
@ -915,15 +925,15 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
} }
/* Error: rollback. */ /* Error: rollback. */
close_one(connssl, conn, sockindex); close_one(connssl, data, conn, sockindex);
return result; return result;
} }
static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, static CURLcode gskit_connect_step2(struct Curl_easy *data,
struct connectdata *conn, int sockindex,
bool nonblocking) bool nonblocking)
{ {
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
Qso_OverlappedIO_t cstat; Qso_OverlappedIO_t cstat;
struct timeval stmv; struct timeval stmv;
@ -971,9 +981,9 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
} }
static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) static CURLcode gskit_connect_step3(struct Curl_easy *data,
struct connectdata *conn, int sockindex)
{ {
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
const gsk_cert_data_elem *cdev; const gsk_cert_data_elem *cdev;
int cdec; int cdec;
@ -1016,7 +1026,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
} }
/* Verify host. */ /* Verify host. */
result = Curl_verifyhost(conn, cert, certend); result = Curl_verifyhost(data, conn, cert, certend);
if(result) if(result)
return result; return result;
@ -1031,7 +1041,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
return result; return result;
if(cert) { if(cert) {
result = Curl_extract_certinfo(conn, 0, cert, certend); result = Curl_extract_certinfo(data, 0, cert, certend);
if(result) if(result)
return result; return result;
} }
@ -1059,10 +1069,10 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
} }
static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, static CURLcode gskit_connect_common(struct Curl_easy *data,
struct connectdata *conn, int sockindex,
bool nonblocking, bool *done) bool nonblocking, bool *done)
{ {
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
timediff_t timeout_ms; timediff_t timeout_ms;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1082,7 +1092,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = CURLE_OPERATION_TIMEDOUT; result = CURLE_OPERATION_TIMEDOUT;
} }
else else
result = gskit_connect_step1(conn, sockindex); result = gskit_connect_step1(data, conn, sockindex);
} }
/* Handle handshake pipelining. */ /* Handle handshake pipelining. */
@ -1101,7 +1111,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = CURLE_OPERATION_TIMEDOUT; result = CURLE_OPERATION_TIMEDOUT;
} }
else else
result = gskit_connect_step2(conn, sockindex, nonblocking); result = gskit_connect_step2(data, conn, sockindex, nonblocking);
} }
/* Handle handshake pipelining. */ /* Handle handshake pipelining. */
@ -1111,10 +1121,10 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
/* Step 3: gather certificate info, verify host. */ /* Step 3: gather certificate info, verify host. */
if(!result && connssl->connecting_state == ssl_connect_3) if(!result && connssl->connecting_state == ssl_connect_3)
result = gskit_connect_step3(conn, sockindex); result = gskit_connect_step3(data, conn, sockindex);
if(result) if(result)
close_one(connssl, conn, sockindex); close_one(connssl, data, conn, sockindex);
else if(connssl->connecting_state == ssl_connect_done) { else if(connssl->connecting_state == ssl_connect_done) {
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
connssl->connecting_state = ssl_connect_1; connssl->connecting_state = ssl_connect_1;
@ -1127,25 +1137,33 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
} }
static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, static CURLcode real_gskit_connect_nonblocking(struct Curl_easy *data,
struct connectdata *conn,
int sockindex, bool *done) int sockindex, bool *done)
{ {
CURLcode result; CURLcode result;
result = gskit_connect_common(conn, sockindex, TRUE, done); result = gskit_connect_common(data, conn, sockindex, TRUE, done);
if(*done || result) if(*done || result)
conn->ssl[sockindex].connecting_state = ssl_connect_1; conn->ssl[sockindex].connecting_state = ssl_connect_1;
return result; return result;
} }
static CURLcode gskit_connect_nonblocking(struct connectdata *conn,
int sockindex, bool *done)
{
return real_gskit_connect_nonblocking(conn->data, conn, sockindex, done);
}
static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
static CURLcode real_gskit_connect(struct Curl_easy *data,
struct connectdata *conn, int sockindex)
{ {
CURLcode result; CURLcode result;
bool done; bool done;
conn->ssl[sockindex].connecting_state = ssl_connect_1; conn->ssl[sockindex].connecting_state = ssl_connect_1;
result = gskit_connect_common(conn, sockindex, FALSE, &done); result = gskit_connect_common(data, conn, sockindex, FALSE, &done);
if(result) if(result)
return result; return result;
@ -1154,18 +1172,29 @@ static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode gskit_connect(struct connectdata *conn, int sockindex)
static void Curl_gskit_close(struct connectdata *conn, int sockindex)
{ {
close_one(&conn->ssl[sockindex], conn, sockindex); return real_gskit_connect(conn->data, conn, sockindex);
close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
} }
static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) static void real_gskit_close(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
close_one(&conn->ssl[sockindex], data, conn, sockindex);
close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
}
static void gskit_close(struct connectdata *conn, int sockindex)
{
real_gskit_close(conn->data, conn, sockindex);
}
static int real_gskit_shutdown(struct Curl_easy *data,
struct connectdata *conn, int sockindex)
{ {
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
int what; int what;
int rc; int rc;
char buf[120]; char buf[120];
@ -1178,7 +1207,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
return 0; return 0;
#endif #endif
close_one(connssl, conn, sockindex); close_one(connssl, data, conn, sockindex);
rc = 0; rc = 0;
what = SOCKET_READABLE(conn->sock[sockindex], what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT); SSL_SHUTDOWN_TIMEOUT);
@ -1218,14 +1247,19 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
return rc; return rc;
} }
static int gskit_shutdown(struct connectdata *conn, int sockindex)
{
return real_gskit_shutdown(conn->data, conn, sockindex);
}
static size_t Curl_gskit_version(char *buffer, size_t size)
static size_t gskit_version(char *buffer, size_t size)
{ {
return msnprintf(buffer, size, "GSKit"); return msnprintf(buffer, size, "GSKit");
} }
static int Curl_gskit_check_cxn(struct connectdata *cxn) static int gskit_check_cxn(struct connectdata *cxn)
{ {
struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET]; struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
int err; int err;
@ -1247,8 +1281,8 @@ static int Curl_gskit_check_cxn(struct connectdata *cxn)
return -1; /* connection status unknown */ return -1; /* connection status unknown */
} }
static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl, static void *gskit_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
(void)info; (void)info;
return BACKEND->handle; return BACKEND->handle;
@ -1262,18 +1296,18 @@ const struct Curl_ssl Curl_ssl_gskit = {
sizeof(struct ssl_backend_data), sizeof(struct ssl_backend_data),
Curl_gskit_init, /* init */ gskit_init, /* init */
Curl_gskit_cleanup, /* cleanup */ gskit_cleanup, /* cleanup */
Curl_gskit_version, /* version */ gskit_version, /* version */
Curl_gskit_check_cxn, /* check_cxn */ gskit_check_cxn, /* check_cxn */
Curl_gskit_shutdown, /* shutdown */ gskit_shutdown, /* shutdown */
Curl_none_data_pending, /* data_pending */ Curl_none_data_pending, /* data_pending */
Curl_none_random, /* random */ Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */ Curl_none_cert_status_request, /* cert_status_request */
Curl_gskit_connect, /* connect */ gskit_connect, /* connect */
Curl_gskit_connect_nonblocking, /* connect_nonblocking */ gskit_connect_nonblocking, /* connect_nonblocking */
Curl_gskit_get_internals, /* get_internals */ gskit_get_internals, /* get_internals */
Curl_gskit_close, /* close_one */ gskit_close, /* close_one */
Curl_none_close_all, /* close_all */ Curl_none_close_all, /* close_all */
/* No session handling for GSKit */ /* No session handling for GSKit */
Curl_none_session_free, /* session_free */ Curl_none_session_free, /* session_free */

View file

@ -885,7 +885,7 @@ gtls_connect_step3(struct connectdata *conn,
const char *beg = (const char *) chainp[i].data; const char *beg = (const char *) chainp[i].data;
const char *end = beg + chainp[i].size; const char *end = beg + chainp[i].size;
result = Curl_extract_certinfo(conn, i, beg, end); result = Curl_extract_certinfo(data, i, beg, end);
if(result) if(result)
return result; return result;
} }
@ -1263,7 +1263,7 @@ gtls_connect_step3(struct connectdata *conn,
else else
infof(data, "ALPN, server did not agree to a protocol\n"); infof(data, "ALPN, server did not agree to a protocol\n");
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
} }
@ -1399,12 +1399,13 @@ static bool gtls_data_pending(const struct connectdata *conn,
return res; return res;
} }
static ssize_t gtls_send(struct connectdata *conn, static ssize_t gtls_send(struct Curl_easy *data,
int sockindex, int sockindex,
const void *mem, const void *mem,
size_t len, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
ssize_t rc = gnutls_record_send(backend->session, mem, len); ssize_t rc = gnutls_record_send(backend->session, mem, len);
@ -1526,12 +1527,13 @@ static int gtls_shutdown(struct connectdata *conn, int sockindex)
return retval; return retval;
} }
static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
int num, /* socketindex */ int num, /* socketindex */
char *buf, /* store read data here */ char *buf, /* store read data here */
size_t buffersize, /* max amount to read */ size_t buffersize, /* max amount to read */
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
ssize_t ret; ssize_t ret;

View file

@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
* Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -701,7 +701,7 @@ mbed_connect_step2(struct connectdata *conn,
else { else {
infof(data, "ALPN, server did not agree to a protocol\n"); infof(data, "ALPN, server did not agree to a protocol\n");
} }
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
} }
#endif #endif
@ -763,16 +763,16 @@ mbed_connect_step3(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static ssize_t mbed_send(struct connectdata *conn, int sockindex, static ssize_t mbed_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, const void *mem, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
int ret = -1; int ret = -1;
ret = mbedtls_ssl_write(&backend->ssl, ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
(unsigned char *)mem, len);
if(ret < 0) { if(ret < 0) {
*curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
@ -804,16 +804,16 @@ static void mbedtls_close(struct connectdata *conn, int sockindex)
#endif /* THREADING_SUPPORT */ #endif /* THREADING_SUPPORT */
} }
static ssize_t mbed_recv(struct connectdata *conn, int num, static ssize_t mbed_recv(struct Curl_easy *data, int num,
char *buf, size_t buffersize, char *buf, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
int ret = -1; int ret = -1;
ssize_t len = -1; ssize_t len = -1;
memset(buf, 0, buffersize);
ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
buffersize); buffersize);

View file

@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com> * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -378,9 +378,10 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
} }
static ssize_t static ssize_t
mesalink_send(struct connectdata *conn, int sockindex, const void *mem, mesalink_send(struct Curl_easy *data, int sockindex, const void *mem,
size_t len, CURLcode *curlcode) size_t len, CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
char error_buffer[MESALINK_MAX_ERROR_SZ]; char error_buffer[MESALINK_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
@ -395,7 +396,7 @@ mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
return -1; return -1;
default: default:
failf(conn->data, failf(data,
"SSL write: %s, errno %d", "SSL write: %s, errno %d",
ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
SOCKERRNO); SOCKERRNO);
@ -423,9 +424,10 @@ Curl_mesalink_close(struct connectdata *conn, int sockindex)
} }
static ssize_t static ssize_t
mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, mesalink_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
char error_buffer[MESALINK_MAX_ERROR_SZ]; char error_buffer[MESALINK_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
@ -444,7 +446,7 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
return -1; return -1;
default: default:
failf(conn->data, failf(data,
"SSL read: %s, errno %d", "SSL read: %s, errno %d",
ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
SOCKERRNO); SOCKERRNO);

View file

@ -814,6 +814,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
static void HandshakeCallback(PRFileDesc *sock, void *arg) static void HandshakeCallback(PRFileDesc *sock, void *arg)
{ {
struct connectdata *conn = (struct connectdata*) arg; struct connectdata *conn = (struct connectdata*) arg;
struct Curl_easy *data = conn->data;
unsigned int buflenmax = 50; unsigned int buflenmax = 50;
unsigned char buf[50]; unsigned char buf[50];
unsigned int buflen; unsigned int buflen;
@ -833,15 +834,15 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
#endif #endif
case SSL_NEXT_PROTO_NO_SUPPORT: case SSL_NEXT_PROTO_NO_SUPPORT:
case SSL_NEXT_PROTO_NO_OVERLAP: case SSL_NEXT_PROTO_NO_OVERLAP:
infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); infof(data, "ALPN/NPN, server did not agree to a protocol\n");
return; return;
#ifdef SSL_ENABLE_ALPN #ifdef SSL_ENABLE_ALPN
case SSL_NEXT_PROTO_SELECTED: case SSL_NEXT_PROTO_SELECTED:
infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf); infof(data, "ALPN, server accepted to use %.*s\n", buflen, buf);
break; break;
#endif #endif
case SSL_NEXT_PROTO_NEGOTIATED: case SSL_NEXT_PROTO_NEGOTIATED:
infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf); infof(data, "NPN, server accepted to use %.*s\n", buflen, buf);
break; break;
} }
@ -856,7 +857,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
!memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
conn->negnpn = CURL_HTTP_VERSION_1_1; conn->negnpn = CURL_HTTP_VERSION_1_1;
} }
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(conn->data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
} }
} }
@ -952,6 +953,7 @@ static void display_cert_info(struct Curl_easy *data,
static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
SSLChannelInfo channel; SSLChannelInfo channel;
SSLCipherSuiteInfo suite; SSLCipherSuiteInfo suite;
CERTCertificate *cert; CERTCertificate *cert;
@ -965,16 +967,16 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
channel.cipherSuite) { channel.cipherSuite) {
if(SSL_GetCipherSuiteInfo(channel.cipherSuite, if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
&suite, sizeof(suite)) == SECSuccess) { &suite, sizeof(suite)) == SECSuccess) {
infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName); infof(data, "SSL connection using %s\n", suite.cipherSuiteName);
} }
} }
cert = SSL_PeerCertificate(sock); cert = SSL_PeerCertificate(sock);
if(cert) { if(cert) {
infof(conn->data, "Server certificate:\n"); infof(data, "Server certificate:\n");
if(!conn->data->set.ssl.certinfo) { if(!data->set.ssl.certinfo) {
display_cert_info(conn->data, cert); display_cert_info(data, cert);
CERT_DestroyCertificate(cert); CERT_DestroyCertificate(cert);
} }
else { else {
@ -995,10 +997,10 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
} }
} }
result = Curl_ssl_init_certinfo(conn->data, i); result = Curl_ssl_init_certinfo(data, i);
if(!result) { if(!result) {
for(i = 0; cert; cert = cert2) { for(i = 0; cert; cert = cert2) {
result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data, result = Curl_extract_certinfo(data, i++, (char *)cert->derCert.data,
(char *)cert->derCert.data + (char *)cert->derCert.data +
cert->derCert.len); cert->derCert.len);
if(result) if(result)
@ -2260,19 +2262,20 @@ static CURLcode nss_connect_nonblocking(struct connectdata *conn,
return nss_connect_common(conn, sockindex, done); return nss_connect_common(conn, sockindex, done);
} }
static ssize_t nss_send(struct connectdata *conn, /* connection data */ static ssize_t nss_send(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */ int sockindex, /* socketindex */
const void *mem, /* send this data */ const void *mem, /* send this data */
size_t len, /* amount to write */ size_t len, /* amount to write */
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
ssize_t rc; ssize_t rc;
/* The SelectClientCert() hook uses this for infof() and failf() but the /* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */ handle stored in nss_setup_connect() could have already been freed. */
backend->data = conn->data; backend->data = data;
rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
if(rc < 0) { if(rc < 0) {
@ -2282,7 +2285,7 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
else { else {
/* print the error number and error string */ /* print the error number and error string */
const char *err_name = nss_error_to_name(err); const char *err_name = nss_error_to_name(err);
infof(conn->data, "SSL write: error %d (%s)\n", err, err_name); infof(data, "SSL write: error %d (%s)\n", err, err_name);
/* print a human-readable message describing the error if available */ /* print a human-readable message describing the error if available */
nss_print_error_message(conn->data, err); nss_print_error_message(conn->data, err);
@ -2298,19 +2301,20 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
return rc; /* number of bytes */ return rc; /* number of bytes */
} }
static ssize_t nss_recv(struct connectdata *conn, /* connection data */ static ssize_t nss_recv(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */ int sockindex, /* socketindex */
char *buf, /* store read data here */ char *buf, /* store read data here */
size_t buffersize, /* max amount to read */ size_t buffersize, /* max amount to read */
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
ssize_t nread; ssize_t nread;
/* The SelectClientCert() hook uses this for infof() and failf() but the /* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */ handle stored in nss_setup_connect() could have already been freed. */
backend->data = conn->data; backend->data = data;
nread = PR_Recv(backend->handle, buf, (int)buffersize, 0, nread = PR_Recv(backend->handle, buf, (int)buffersize, 0,
PR_INTERVAL_NO_WAIT); PR_INTERVAL_NO_WAIT);
@ -2323,7 +2327,7 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
else { else {
/* print the error number and error string */ /* print the error number and error string */
const char *err_name = nss_error_to_name(err); const char *err_name = nss_error_to_name(err);
infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name); infof(data, "SSL read: errno %d (%s)\n", err, err_name);
/* print a human-readable message describing the error if available */ /* print a human-readable message describing the error if available */
nss_print_error_message(conn->data, err); nss_print_error_message(conn->data, err);

View file

@ -1433,7 +1433,7 @@ static int ossl_shutdown(struct connectdata *conn, int sockindex)
default: default:
/* openssl/ssl.h says "look at error stack/return value/errno" */ /* openssl/ssl.h says "look at error stack/return value/errno" */
sslerror = ERR_get_error(); sslerror = ERR_get_error();
failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d", failf(data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
(sslerror ? (sslerror ?
ossl_strerror(sslerror, buf, sizeof(buf)) : ossl_strerror(sslerror, buf, sizeof(buf)) :
SSL_ERROR_to_str(err)), SSL_ERROR_to_str(err)),
@ -2206,15 +2206,15 @@ select_next_proto_cb(SSL *ssl,
const unsigned char *in, unsigned int inlen, const unsigned char *in, unsigned int inlen,
void *arg) void *arg)
{ {
struct connectdata *conn = (struct connectdata*) arg; struct Curl_easy *data = (struct Curl_easy *)arg;
struct connectdata *conn = data->conn;
(void)ssl; (void)ssl;
#ifdef USE_NGHTTP2 #ifdef USE_NGHTTP2
if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 && if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
!select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID,
NGHTTP2_PROTO_VERSION_ID_LEN)) { NGHTTP2_PROTO_VERSION_ID_LEN)) {
infof(conn->data, "NPN, negotiated HTTP2 (%s)\n", infof(data, "NPN, negotiated HTTP2 (%s)\n",
NGHTTP2_PROTO_VERSION_ID); NGHTTP2_PROTO_VERSION_ID);
conn->negnpn = CURL_HTTP_VERSION_2; conn->negnpn = CURL_HTTP_VERSION_2;
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
@ -2223,12 +2223,12 @@ select_next_proto_cb(SSL *ssl,
if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1, if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
ALPN_HTTP_1_1_LENGTH)) { ALPN_HTTP_1_1_LENGTH)) {
infof(conn->data, "NPN, negotiated HTTP1.1\n"); infof(data, "NPN, negotiated HTTP1.1\n");
conn->negnpn = CURL_HTTP_VERSION_1_1; conn->negnpn = CURL_HTTP_VERSION_1_1;
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
infof(conn->data, "NPN, no overlap, use HTTP1.1\n"); infof(data, "NPN, no overlap, use HTTP1.1\n");
*out = (unsigned char *)ALPN_HTTP_1_1; *out = (unsigned char *)ALPN_HTTP_1_1;
*outlen = ALPN_HTTP_1_1_LENGTH; *outlen = ALPN_HTTP_1_1_LENGTH;
conn->negnpn = CURL_HTTP_VERSION_1_1; conn->negnpn = CURL_HTTP_VERSION_1_1;
@ -2729,7 +2729,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_NPN #ifdef HAS_NPN
if(conn->bits.tls_enable_npn) if(conn->bits.tls_enable_npn)
SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, conn); SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data);
#endif #endif
#ifdef HAS_ALPN #ifdef HAS_ALPN
@ -3385,7 +3385,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
else else
infof(data, "ALPN, server did not agree to a protocol\n"); infof(data, "ALPN, server did not agree to a protocol\n");
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
} }
#endif #endif
@ -4130,7 +4130,7 @@ static bool ossl_data_pending(const struct connectdata *conn,
static size_t ossl_version(char *buffer, size_t size); static size_t ossl_version(char *buffer, size_t size);
static ssize_t ossl_send(struct connectdata *conn, static ssize_t ossl_send(struct Curl_easy *data,
int sockindex, int sockindex,
const void *mem, const void *mem,
size_t len, size_t len,
@ -4143,6 +4143,7 @@ static ssize_t ossl_send(struct connectdata *conn,
unsigned long sslerror; unsigned long sslerror;
int memlen; int memlen;
int rc; int rc;
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
@ -4174,7 +4175,7 @@ static ssize_t ossl_send(struct connectdata *conn,
strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer)); strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
error_buffer[sizeof(error_buffer) - 1] = '\0'; error_buffer[sizeof(error_buffer) - 1] = '\0';
} }
failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d", failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
error_buffer, sockerr); error_buffer, sockerr);
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1; return -1;
@ -4192,17 +4193,16 @@ static ssize_t ossl_send(struct connectdata *conn,
) { ) {
char ver[120]; char ver[120];
ossl_version(ver, 120); ossl_version(ver, 120);
failf(conn->data, "Error: %s does not support double SSL tunneling.", failf(data, "Error: %s does not support double SSL tunneling.", ver);
ver);
} }
else else
failf(conn->data, "SSL_write() error: %s", failf(data, "SSL_write() error: %s",
ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1; return -1;
} }
/* a true error */ /* a true error */
failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d", failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
SSL_ERROR_to_str(err), SOCKERRNO); SSL_ERROR_to_str(err), SOCKERRNO);
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1; return -1;
@ -4211,7 +4211,7 @@ static ssize_t ossl_send(struct connectdata *conn,
return (ssize_t)rc; /* number of bytes */ return (ssize_t)rc; /* number of bytes */
} }
static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ static ssize_t ossl_recv(struct Curl_easy *data, /* transfer */
int num, /* socketindex */ int num, /* socketindex */
char *buf, /* store read data here */ char *buf, /* store read data here */
size_t buffersize, /* max amount to read */ size_t buffersize, /* max amount to read */
@ -4221,6 +4221,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
unsigned long sslerror; unsigned long sslerror;
ssize_t nread; ssize_t nread;
int buffsize; int buffsize;
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;

View file

@ -5,9 +5,9 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de> * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com> * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -956,7 +956,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"sending %lu bytes...\n", outbuf.cbBuffer)); "sending %lu bytes...\n", outbuf.cbBuffer));
/* send initial handshake data which is now stored in output buffer */ /* send initial handshake data which is now stored in output buffer */
result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
outbuf.cbBuffer, &written); outbuf.cbBuffer, &written);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
@ -1153,7 +1153,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
"sending %lu bytes...\n", outbuf[i].cbBuffer)); "sending %lu bytes...\n", outbuf[i].cbBuffer));
/* send handshake token to server */ /* send handshake token to server */
result = Curl_write_plain(conn, conn->sock[sockindex], result = Curl_write_plain(data, conn->sock[sockindex],
outbuf[i].pvBuffer, outbuf[i].cbBuffer, outbuf[i].pvBuffer, outbuf[i].cbBuffer,
&written); &written);
if((result != CURLE_OK) || if((result != CURLE_OK) ||
@ -1305,7 +1305,7 @@ cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
struct Adder_args struct Adder_args
{ {
struct connectdata *conn; struct Curl_easy *data;
CURLcode result; CURLcode result;
int idx; int idx;
int certs_count; int certs_count;
@ -1320,7 +1320,8 @@ add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
const char *beg = (const char *) ccert_context->pbCertEncoded; const char *beg = (const char *) ccert_context->pbCertEncoded;
const char *end = beg + ccert_context->cbCertEncoded; const char *end = beg + ccert_context->cbCertEncoded;
int insert_index = (args->certs_count - 1) - args->idx; int insert_index = (args->certs_count - 1) - args->idx;
args->result = Curl_extract_certinfo(args->conn, insert_index, beg, end); args->result = Curl_extract_certinfo(args->data, insert_index,
beg, end);
args->idx++; args->idx++;
} }
return args->result == CURLE_OK; return args->result == CURLE_OK;
@ -1400,7 +1401,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
} }
else else
infof(data, "ALPN, server did not agree to a protocol\n"); infof(data, "ALPN, server did not agree to a protocol\n");
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
} }
#endif #endif
@ -1458,7 +1459,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
result = Curl_ssl_init_certinfo(data, certs_count); result = Curl_ssl_init_certinfo(data, certs_count);
if(!result) { if(!result) {
struct Adder_args args; struct Adder_args args;
args.conn = conn; args.data = data;
args.idx = 0; args.idx = 0;
args.certs_count = certs_count; args.certs_count = certs_count;
traverse_cert_store(ccert_context, add_cert_to_certinfo, &args); traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
@ -1597,12 +1598,13 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
} }
static ssize_t static ssize_t
schannel_send(struct connectdata *conn, int sockindex, schannel_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err) const void *buf, size_t len, CURLcode *err)
{ {
ssize_t written = -1; ssize_t written = -1;
size_t data_len = 0; size_t data_len = 0;
unsigned char *data = NULL; unsigned char *ptr = NULL;
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SecBuffer outbuf[4]; SecBuffer outbuf[4];
SecBufferDesc outbuf_desc; SecBufferDesc outbuf_desc;
@ -1629,19 +1631,19 @@ schannel_send(struct connectdata *conn, int sockindex,
/* calculate the complete message length and allocate a buffer for it */ /* calculate the complete message length and allocate a buffer for it */
data_len = BACKEND->stream_sizes.cbHeader + len + data_len = BACKEND->stream_sizes.cbHeader + len +
BACKEND->stream_sizes.cbTrailer; BACKEND->stream_sizes.cbTrailer;
data = (unsigned char *) malloc(data_len); ptr = (unsigned char *) malloc(data_len);
if(data == NULL) { if(!ptr) {
*err = CURLE_OUT_OF_MEMORY; *err = CURLE_OUT_OF_MEMORY;
return -1; return -1;
} }
/* setup output buffers (header, data, trailer, empty) */ /* setup output buffers (header, data, trailer, empty) */
InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
data, BACKEND->stream_sizes.cbHeader); ptr, BACKEND->stream_sizes.cbHeader);
InitSecBuffer(&outbuf[1], SECBUFFER_DATA, InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len)); ptr + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
data + BACKEND->stream_sizes.cbHeader + len, ptr + BACKEND->stream_sizes.cbHeader + len,
BACKEND->stream_sizes.cbTrailer); BACKEND->stream_sizes.cbTrailer);
InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 4); InitSecBufferDesc(&outbuf_desc, outbuf, 4);
@ -1680,10 +1682,10 @@ schannel_send(struct connectdata *conn, int sockindex,
while(len > (size_t)written) { while(len > (size_t)written) {
ssize_t this_write = 0; ssize_t this_write = 0;
int what; int what;
timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, FALSE); timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE);
if(timeout_ms < 0) { if(timeout_ms < 0) {
/* we already got the timeout */ /* we already got the timeout */
failf(conn->data, "schannel: timed out sending data " failf(data, "schannel: timed out sending data "
"(bytes sent: %zd)", written); "(bytes sent: %zd)", written);
*err = CURLE_OPERATION_TIMEDOUT; *err = CURLE_OPERATION_TIMEDOUT;
written = -1; written = -1;
@ -1694,13 +1696,13 @@ schannel_send(struct connectdata *conn, int sockindex,
what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms); what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
if(what < 0) { if(what < 0) {
/* fatal error */ /* fatal error */
failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
written = -1; written = -1;
break; break;
} }
else if(0 == what) { else if(0 == what) {
failf(conn->data, "schannel: timed out sending data " failf(data, "schannel: timed out sending data "
"(bytes sent: %zd)", written); "(bytes sent: %zd)", written);
*err = CURLE_OPERATION_TIMEDOUT; *err = CURLE_OPERATION_TIMEDOUT;
written = -1; written = -1;
@ -1708,7 +1710,7 @@ schannel_send(struct connectdata *conn, int sockindex,
} }
/* socket is writable */ /* socket is writable */
result = Curl_write_plain(conn, conn->sock[sockindex], data + written, result = Curl_write_plain(data, conn->sock[sockindex], ptr + written,
len - written, &this_write); len - written, &this_write);
if(result == CURLE_AGAIN) if(result == CURLE_AGAIN)
continue; continue;
@ -1728,7 +1730,7 @@ schannel_send(struct connectdata *conn, int sockindex,
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
} }
Curl_safefree(data); Curl_safefree(ptr);
if(len == (size_t)written) if(len == (size_t)written)
/* Encrypted message including header, data and trailer entirely sent. /* Encrypted message including header, data and trailer entirely sent.
@ -1739,12 +1741,12 @@ schannel_send(struct connectdata *conn, int sockindex,
} }
static ssize_t static ssize_t
schannel_recv(struct connectdata *conn, int sockindex, schannel_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t len, CURLcode *err) char *buf, size_t len, CURLcode *err)
{ {
size_t size = 0; size_t size = 0;
ssize_t nread = -1; ssize_t nread = -1;
struct Curl_easy *data = conn->data; struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned char *reallocated_buffer; unsigned char *reallocated_buffer;
size_t reallocated_length; size_t reallocated_length;
@ -2181,7 +2183,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */ /* send close message which is in output buffer */
ssize_t written; ssize_t written;
result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
outbuf.cbBuffer, &written); outbuf.cbBuffer, &written);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);

View file

@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>. * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
* Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -2693,7 +2693,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
else else
infof(data, "ALPN, server did not agree to a protocol\n"); infof(data, "ALPN, server did not agree to a protocol\n");
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
/* chosenProtocol is a reference to the string within alpnArr /* chosenProtocol is a reference to the string within alpnArr
@ -3157,13 +3157,13 @@ static bool Curl_sectransp_false_start(void)
return FALSE; return FALSE;
} }
static ssize_t sectransp_send(struct connectdata *conn, static ssize_t sectransp_send(struct Curl_easy *data,
int sockindex, int sockindex,
const void *mem, const void *mem,
size_t len, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
/*struct Curl_easy *data = conn->data;*/ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
size_t processed = 0UL; size_t processed = 0UL;
@ -3215,7 +3215,7 @@ static ssize_t sectransp_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
return -1L; return -1L;
default: default:
failf(conn->data, "SSLWrite() returned error %d", err); failf(data, "SSLWrite() returned error %d", err);
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
return -1L; return -1L;
} }
@ -3224,13 +3224,13 @@ static ssize_t sectransp_send(struct connectdata *conn,
return (ssize_t)processed; return (ssize_t)processed;
} }
static ssize_t sectransp_recv(struct connectdata *conn, static ssize_t sectransp_recv(struct Curl_easy *data,
int num, int num,
char *buf, char *buf,
size_t buffersize, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
/*struct Curl_easy *data = conn->data;*/ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
size_t processed = 0UL; size_t processed = 0UL;
@ -3269,7 +3269,7 @@ static ssize_t sectransp_recv(struct connectdata *conn,
} }
goto again; goto again;
default: default:
failf(conn->data, "SSLRead() return error %d", err); failf(data, "SSLRead() return error %d", err);
*curlcode = CURLE_RECV_ERROR; *curlcode = CURLE_RECV_ERROR;
return -1L; return -1L;
break; break;

View file

@ -735,7 +735,7 @@ wolfssl_connect_step2(struct connectdata *conn,
else else
infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
protocol); protocol);
Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
} }
else if(rc == SSL_ALPN_NOT_FOUND) else if(rc == SSL_ALPN_NOT_FOUND)
@ -807,12 +807,13 @@ wolfssl_connect_step3(struct connectdata *conn,
} }
static ssize_t wolfssl_send(struct connectdata *conn, static ssize_t wolfssl_send(struct Curl_easy *data,
int sockindex, int sockindex,
const void *mem, const void *mem,
size_t len, size_t len,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ]; char error_buffer[WOLFSSL_MAX_ERROR_SZ];
@ -829,7 +830,7 @@ static ssize_t wolfssl_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
return -1; return -1;
default: default:
failf(conn->data, "SSL write: %s, errno %d", failf(data, "SSL write: %s, errno %d",
ERR_error_string(err, error_buffer), ERR_error_string(err, error_buffer),
SOCKERRNO); SOCKERRNO);
*curlcode = CURLE_SEND_ERROR; *curlcode = CURLE_SEND_ERROR;
@ -855,12 +856,13 @@ static void wolfssl_close(struct connectdata *conn, int sockindex)
} }
} }
static ssize_t wolfssl_recv(struct connectdata *conn, static ssize_t wolfssl_recv(struct Curl_easy *data,
int num, int num,
char *buf, char *buf,
size_t buffersize, size_t buffersize,
CURLcode *curlcode) CURLcode *curlcode)
{ {
struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num]; struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend; struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ]; char error_buffer[WOLFSSL_MAX_ERROR_SZ];
@ -879,9 +881,8 @@ static ssize_t wolfssl_recv(struct connectdata *conn,
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;
return -1; return -1;
default: default:
failf(conn->data, "SSL read: %s, errno %d", failf(data, "SSL read: %s, errno %d",
ERR_error_string(err, error_buffer), ERR_error_string(err, error_buffer), SOCKERRNO);
SOCKERRNO);
*curlcode = CURLE_RECV_ERROR; *curlcode = CURLE_RECV_ERROR;
return -1; return -1;
} }

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -945,13 +945,12 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
} }
} }
CURLcode Curl_extract_certinfo(struct connectdata *conn, CURLcode Curl_extract_certinfo(struct Curl_easy *data,
int certnum, int certnum,
const char *beg, const char *beg,
const char *end) const char *end)
{ {
struct Curl_X509certificate cert; struct Curl_X509certificate cert;
struct Curl_easy *data = conn->data;
struct Curl_asn1Element param; struct Curl_asn1Element param;
const char *ccp; const char *ccp;
char *cp1; char *cp1;
@ -1132,10 +1131,9 @@ static const char *checkOID(const char *beg, const char *end,
return matched? ccp: NULL; return matched? ccp: NULL;
} }
CURLcode Curl_verifyhost(struct connectdata *conn, CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
const char *beg, const char *end) const char *beg, const char *end)
{ {
struct Curl_easy *data = conn->data;
struct Curl_X509certificate cert; struct Curl_X509certificate cert;
struct Curl_asn1Element dn; struct Curl_asn1Element dn;
struct Curl_asn1Element elem; struct Curl_asn1Element elem;

View file

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -125,9 +125,9 @@ const char *Curl_ASN1tostr(struct Curl_asn1Element *elem, int type);
const char *Curl_DNtostr(struct Curl_asn1Element *dn); const char *Curl_DNtostr(struct Curl_asn1Element *dn);
int Curl_parseX509(struct Curl_X509certificate *cert, int Curl_parseX509(struct Curl_X509certificate *cert,
const char *beg, const char *end); const char *beg, const char *end);
CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
const char *beg, const char *end); const char *beg, const char *end);
CURLcode Curl_verifyhost(struct connectdata *conn, CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
const char *beg, const char *end); const char *beg, const char *end);
#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */ #endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */
#endif /* HEADER_CURL_X509ASN1_H */ #endif /* HEADER_CURL_X509ASN1_H */

View file

@ -29,6 +29,7 @@ imap://%HOSTIP:%IMAPPORT/660
<verify> <verify>
<protocol> <protocol>
A001 CAPABILITY A001 CAPABILITY
A002 LOGOUT
</protocol> </protocol>
</verify> </verify>
</testcase> </testcase>

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -346,7 +346,6 @@ static unsigned char cert[] = {
UNITTEST_START UNITTEST_START
{ {
CURLcode result; CURLcode result;
struct connectdata conn;
const char *beg = (const char *)&cert[0]; const char *beg = (const char *)&cert[0];
const char *end = (const char *)&cert[sizeof(cert)]; const char *end = (const char *)&cert[sizeof(cert)];
struct Curl_easy *data = curl_easy_init(); struct Curl_easy *data = curl_easy_init();
@ -355,11 +354,7 @@ UNITTEST_START
if(!data) if(!data)
return 2; return 2;
memset(&conn, 0, sizeof(struct connectdata)); result = Curl_extract_certinfo(data, 0, beg, end);
/* this is a lot of assuming, but we expect the parsing function to only
really need the easy handle pointer */
conn.data = data;
result = Curl_extract_certinfo(&conn, 0, beg, end);
fail_unless(result == CURLE_OK, "Curl_extract_certinfo returned error"); fail_unless(result == CURLE_OK, "Curl_extract_certinfo returned error");
@ -369,7 +364,7 @@ UNITTEST_START
for(i = 0; i < 45; i++) { for(i = 0; i < 45; i++) {
char backup = cert[i]; char backup = cert[i];
cert[i] = (unsigned char) (byte & 0xff); cert[i] = (unsigned char) (byte & 0xff);
(void) Curl_extract_certinfo(&conn, 0, beg, end); (void) Curl_extract_certinfo(data, 0, beg, end);
cert[i] = backup; cert[i] = backup;
} }
} }