mirror of
https://github.com/curl/curl.git
synced 2025-09-17 17:42:49 +03:00
parent
43a50a2580
commit
b46cfbc068
|
@ -22,7 +22,6 @@
|
||||||
1.4 signal-based resolver timeouts
|
1.4 signal-based resolver timeouts
|
||||||
1.5 get rid of PATH_MAX
|
1.5 get rid of PATH_MAX
|
||||||
1.6 Modified buffer size approach
|
1.6 Modified buffer size approach
|
||||||
1.7 Detect when called from within callbacks
|
|
||||||
1.8 CURLOPT_RESOLVE for any port number
|
1.8 CURLOPT_RESOLVE for any port number
|
||||||
1.9 Cache negative name resolves
|
1.9 Cache negative name resolves
|
||||||
1.10 auto-detect proxy
|
1.10 auto-detect proxy
|
||||||
|
@ -239,12 +238,6 @@
|
||||||
Dynamically allocate buffer size depending on protocol in use in combination
|
Dynamically allocate buffer size depending on protocol in use in combination
|
||||||
with freeing it after each individual transfer? Other suggestions?
|
with freeing it after each individual transfer? Other suggestions?
|
||||||
|
|
||||||
1.7 Detect when called from within callbacks
|
|
||||||
|
|
||||||
We should set a state variable before calling callbacks, so that we
|
|
||||||
subsequently can add code within libcurl that returns error if called within
|
|
||||||
callbacks for when that's not supported.
|
|
||||||
|
|
||||||
1.8 CURLOPT_RESOLVE for any port number
|
1.8 CURLOPT_RESOLVE for any port number
|
||||||
|
|
||||||
This option allows applications to set a replacement IP address for a given
|
This option allows applications to set a replacement IP address for a given
|
||||||
|
|
|
@ -252,6 +252,8 @@ Failed to match the pinned key specified with \fICURLOPT_PINNEDPUBLICKEY(3)\fP.
|
||||||
Status returned failure when asked with \fICURLOPT_SSL_VERIFYSTATUS(3)\fP.
|
Status returned failure when asked with \fICURLOPT_SSL_VERIFYSTATUS(3)\fP.
|
||||||
.IP "CURLE_HTTP2_STREAM (92)"
|
.IP "CURLE_HTTP2_STREAM (92)"
|
||||||
Stream error in the HTTP/2 framing layer.
|
Stream error in the HTTP/2 framing layer.
|
||||||
|
.IP "CURLE_RECURSIVE_API_CALL (93)"
|
||||||
|
An API function was called from inside a callback.
|
||||||
.IP "CURLE_OBSOLETE*"
|
.IP "CURLE_OBSOLETE*"
|
||||||
These error codes will never be returned. They were used in an old libcurl
|
These error codes will never be returned. They were used in an old libcurl
|
||||||
version and are currently unused.
|
version and are currently unused.
|
||||||
|
@ -285,6 +287,8 @@ curl_multi_setopt() with unsupported option
|
||||||
.IP "CURLM_ADDED_ALREADY (7)"
|
.IP "CURLM_ADDED_ALREADY (7)"
|
||||||
An easy handle already added to a multi handle was attempted to get added a
|
An easy handle already added to a multi handle was attempted to get added a
|
||||||
second time. (Added in 7.32.1)
|
second time. (Added in 7.32.1)
|
||||||
|
.IP "CURLM_RECURSIVE_API_CALL (8)"
|
||||||
|
An API function was called from inside a callback.
|
||||||
.SH "CURLSHcode"
|
.SH "CURLSHcode"
|
||||||
The "share" interface will return a CURLSHcode to indicate when an error has
|
The "share" interface will return a CURLSHcode to indicate when an error has
|
||||||
occurred. Also consider \fIcurl_share_strerror(3)\fP.
|
occurred. Also consider \fIcurl_share_strerror(3)\fP.
|
||||||
|
|
|
@ -101,6 +101,7 @@ CURLE_QUOTE_ERROR 7.17.0
|
||||||
CURLE_RANGE_ERROR 7.17.0
|
CURLE_RANGE_ERROR 7.17.0
|
||||||
CURLE_READ_ERROR 7.1
|
CURLE_READ_ERROR 7.1
|
||||||
CURLE_RECV_ERROR 7.10
|
CURLE_RECV_ERROR 7.10
|
||||||
|
CURLE_RECURSIVE_API_CALL 7.59.0
|
||||||
CURLE_REMOTE_ACCESS_DENIED 7.17.0
|
CURLE_REMOTE_ACCESS_DENIED 7.17.0
|
||||||
CURLE_REMOTE_DISK_FULL 7.17.0
|
CURLE_REMOTE_DISK_FULL 7.17.0
|
||||||
CURLE_REMOTE_FILE_EXISTS 7.17.0
|
CURLE_REMOTE_FILE_EXISTS 7.17.0
|
||||||
|
@ -323,6 +324,7 @@ CURLM_CALL_MULTI_SOCKET 7.15.5
|
||||||
CURLM_INTERNAL_ERROR 7.9.6
|
CURLM_INTERNAL_ERROR 7.9.6
|
||||||
CURLM_OK 7.9.6
|
CURLM_OK 7.9.6
|
||||||
CURLM_OUT_OF_MEMORY 7.9.6
|
CURLM_OUT_OF_MEMORY 7.9.6
|
||||||
|
CURLM_RECURSIVE_API_CALL 7.59.0
|
||||||
CURLM_UNKNOWN_OPTION 7.15.4
|
CURLM_UNKNOWN_OPTION 7.15.4
|
||||||
CURLOPTTYPE_FUNCTIONPOINT 7.1
|
CURLOPTTYPE_FUNCTIONPOINT 7.1
|
||||||
CURLOPTTYPE_LONG 7.1
|
CURLOPTTYPE_LONG 7.1
|
||||||
|
|
|
@ -577,6 +577,8 @@ typedef enum {
|
||||||
CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
|
CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
|
||||||
CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
|
CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
|
||||||
*/
|
*/
|
||||||
|
CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from
|
||||||
|
inside a callback */
|
||||||
CURL_LAST /* never use! */
|
CURL_LAST /* never use! */
|
||||||
} CURLcode;
|
} CURLcode;
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,8 @@ typedef enum {
|
||||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||||
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
|
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
|
||||||
attempted to get added - again */
|
attempted to get added - again */
|
||||||
|
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
|
||||||
|
callback */
|
||||||
CURLM_LAST
|
CURLM_LAST
|
||||||
} CURLMcode;
|
} CURLMcode;
|
||||||
|
|
||||||
|
|
|
@ -1033,9 +1033,11 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||||
|
|
||||||
if(data->set.fsockopt) {
|
if(data->set.fsockopt) {
|
||||||
/* activate callback for setting socket options */
|
/* activate callback for setting socket options */
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
error = data->set.fsockopt(data->set.sockopt_client,
|
error = data->set.fsockopt(data->set.sockopt_client,
|
||||||
sockfd,
|
sockfd,
|
||||||
CURLSOCKTYPE_IPCXN);
|
CURLSOCKTYPE_IPCXN);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
|
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
|
||||||
isconnected = TRUE;
|
isconnected = TRUE;
|
||||||
|
@ -1311,8 +1313,12 @@ int Curl_closesocket(struct connectdata *conn,
|
||||||
status */
|
status */
|
||||||
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
|
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
|
||||||
else {
|
else {
|
||||||
|
int rc;
|
||||||
Curl_multi_closed(conn, sock);
|
Curl_multi_closed(conn, sock);
|
||||||
return conn->fclosesocket(conn->closesocket_client, sock);
|
Curl_set_in_callback(conn->data, true);
|
||||||
|
rc = conn->fclosesocket(conn->closesocket_client, sock);
|
||||||
|
Curl_set_in_callback(conn->data, false);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1363,7 +1369,7 @@ CURLcode Curl_socket(struct connectdata *conn,
|
||||||
addr->addrlen = sizeof(struct Curl_sockaddr_storage);
|
addr->addrlen = sizeof(struct Curl_sockaddr_storage);
|
||||||
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
|
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
|
||||||
|
|
||||||
if(data->set.fopensocket)
|
if(data->set.fopensocket) {
|
||||||
/*
|
/*
|
||||||
* If the opensocket callback is set, all the destination address
|
* If the opensocket callback is set, all the destination address
|
||||||
* information is passed to the callback. Depending on this information the
|
* information is passed to the callback. Depending on this information the
|
||||||
|
@ -1373,9 +1379,12 @@ CURLcode Curl_socket(struct connectdata *conn,
|
||||||
* might have been changed and this 'new' address will actually be used
|
* might have been changed and this 'new' address will actually be used
|
||||||
* here to connect.
|
* here to connect.
|
||||||
*/
|
*/
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
*sockfd = data->set.fopensocket(data->set.opensocket_client,
|
*sockfd = data->set.fopensocket(data->set.opensocket_client,
|
||||||
CURLSOCKTYPE_IPCXN,
|
CURLSOCKTYPE_IPCXN,
|
||||||
(struct curl_sockaddr *)addr);
|
(struct curl_sockaddr *)addr);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
/* opensocket callback not set, so simply create the socket now */
|
/* opensocket callback not set, so simply create the socket now */
|
||||||
*sockfd = socket(addr->family, addr->socktype, addr->protocol);
|
*sockfd = socket(addr->family, addr->socktype, addr->protocol);
|
||||||
|
|
13
lib/easy.c
13
lib/easy.c
|
@ -61,6 +61,7 @@
|
||||||
#include "strdup.h"
|
#include "strdup.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "easyif.h"
|
#include "easyif.h"
|
||||||
|
#include "multiif.h"
|
||||||
#include "select.h"
|
#include "select.h"
|
||||||
#include "sendf.h" /* for failf function prototype */
|
#include "sendf.h" /* for failf function prototype */
|
||||||
#include "connect.h" /* for Curl_getconnectinfo */
|
#include "connect.h" /* for Curl_getconnectinfo */
|
||||||
|
@ -761,6 +762,9 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
|
||||||
data->multi_easy = multi;
|
data->multi_easy = multi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLE_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
/* Copy the MAXCONNECTS option to the multi handle */
|
/* Copy the MAXCONNECTS option to the multi handle */
|
||||||
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
|
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
|
||||||
|
|
||||||
|
@ -1030,6 +1034,9 @@ void curl_easy_reset(struct Curl_easy *data)
|
||||||
* the pausing, you may get your write callback called at this point.
|
* the pausing, you may get your write callback called at this point.
|
||||||
*
|
*
|
||||||
* Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
|
* Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
|
||||||
|
*
|
||||||
|
* NOTE: This is one of few API functions that are allowed to be called from
|
||||||
|
* within a callback.
|
||||||
*/
|
*/
|
||||||
CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||||
{
|
{
|
||||||
|
@ -1134,6 +1141,9 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
|
||||||
ssize_t n1;
|
ssize_t n1;
|
||||||
struct connectdata *c;
|
struct connectdata *c;
|
||||||
|
|
||||||
|
if(Curl_is_in_callback(data))
|
||||||
|
return CURLE_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
result = easy_connection(data, &sfd, &c);
|
result = easy_connection(data, &sfd, &c);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
@ -1161,6 +1171,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
|
||||||
ssize_t n1;
|
ssize_t n1;
|
||||||
struct connectdata *c = NULL;
|
struct connectdata *c = NULL;
|
||||||
|
|
||||||
|
if(Curl_is_in_callback(data))
|
||||||
|
return CURLE_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
result = easy_connection(data, &sfd, &c);
|
result = easy_connection(data, &sfd, &c);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
16
lib/ftp.c
16
lib/ftp.c
|
@ -311,9 +311,11 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
/* activate callback for setting socket options */
|
/* activate callback for setting socket options */
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
error = data->set.fsockopt(data->set.sockopt_client,
|
error = data->set.fsockopt(data->set.sockopt_client,
|
||||||
s,
|
s,
|
||||||
CURLSOCKTYPE_ACCEPT);
|
CURLSOCKTYPE_ACCEPT);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
if(error) {
|
if(error) {
|
||||||
close_secondarysocket(conn);
|
close_secondarysocket(conn);
|
||||||
|
@ -1616,8 +1618,10 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
|
||||||
|
|
||||||
/* Let's read off the proper amount of bytes from the input. */
|
/* Let's read off the proper amount of bytes from the input. */
|
||||||
if(conn->seek_func) {
|
if(conn->seek_func) {
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
||||||
SEEK_SET);
|
SEEK_SET);
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seekerr != CURL_SEEKFUNC_OK) {
|
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||||
|
@ -3181,7 +3185,9 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||||
|
|
||||||
if(data->state.wildcardmatch) {
|
if(data->state.wildcardmatch) {
|
||||||
if(data->set.chunk_end && ftpc->file) {
|
if(data->set.chunk_end && ftpc->file) {
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
data->set.chunk_end(data->wildcard.customptr);
|
data->set.chunk_end(data->wildcard.customptr);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
}
|
}
|
||||||
ftpc->known_filesize = -1;
|
ftpc->known_filesize = -1;
|
||||||
}
|
}
|
||||||
|
@ -3834,8 +3840,11 @@ static CURLcode wc_statemach(struct connectdata *conn)
|
||||||
|
|
||||||
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
|
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
|
||||||
if(conn->data->set.chunk_bgn) {
|
if(conn->data->set.chunk_bgn) {
|
||||||
long userresponse = conn->data->set.chunk_bgn(
|
long userresponse;
|
||||||
|
Curl_set_in_callback(conn->data, true);
|
||||||
|
userresponse = conn->data->set.chunk_bgn(
|
||||||
finfo, wildcard->customptr, (int)wildcard->filelist.size);
|
finfo, wildcard->customptr, (int)wildcard->filelist.size);
|
||||||
|
Curl_set_in_callback(conn->data, false);
|
||||||
switch(userresponse) {
|
switch(userresponse) {
|
||||||
case CURL_CHUNK_BGN_FUNC_SKIP:
|
case CURL_CHUNK_BGN_FUNC_SKIP:
|
||||||
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
|
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
|
||||||
|
@ -3871,8 +3880,11 @@ static CURLcode wc_statemach(struct connectdata *conn)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case CURLWC_SKIP: {
|
case CURLWC_SKIP: {
|
||||||
if(conn->data->set.chunk_end)
|
if(conn->data->set.chunk_end) {
|
||||||
|
Curl_set_in_callback(conn->data, true);
|
||||||
conn->data->set.chunk_end(conn->data->wildcard.customptr);
|
conn->data->set.chunk_end(conn->data->wildcard.customptr);
|
||||||
|
Curl_set_in_callback(conn->data, false);
|
||||||
|
}
|
||||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||||
wildcard->state = (wildcard->filelist.size == 0) ?
|
wildcard->state = (wildcard->filelist.size == 0) ?
|
||||||
CURLWC_CLEAN : CURLWC_DOWNLOADING;
|
CURLWC_CLEAN : CURLWC_DOWNLOADING;
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "ftplistparser.h"
|
#include "ftplistparser.h"
|
||||||
#include "curl_fnmatch.h"
|
#include "curl_fnmatch.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
|
#include "multiif.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
@ -294,6 +295,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
|
||||||
compare = Curl_fnmatch;
|
compare = Curl_fnmatch;
|
||||||
|
|
||||||
/* filter pattern-corresponding filenames */
|
/* filter pattern-corresponding filenames */
|
||||||
|
Curl_set_in_callback(conn->data, true);
|
||||||
if(compare(conn->data->set.fnmatch_data, wc->pattern,
|
if(compare(conn->data->set.fnmatch_data, wc->pattern,
|
||||||
finfo->filename) == 0) {
|
finfo->filename) == 0) {
|
||||||
/* discard symlink which is containing multiple " -> " */
|
/* discard symlink which is containing multiple " -> " */
|
||||||
|
@ -305,6 +307,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
|
||||||
else {
|
else {
|
||||||
add = FALSE;
|
add = FALSE;
|
||||||
}
|
}
|
||||||
|
Curl_set_in_callback(conn->data, false);
|
||||||
|
|
||||||
if(add) {
|
if(add) {
|
||||||
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
|
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
|
||||||
|
|
|
@ -2191,8 +2191,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||||
/* Now, let's read off the proper amount of bytes from the
|
/* Now, let's read off the proper amount of bytes from the
|
||||||
input. */
|
input. */
|
||||||
if(conn->seek_func) {
|
if(conn->seek_func) {
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
||||||
SEEK_SET);
|
SEEK_SET);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seekerr != CURL_SEEKFUNC_OK) {
|
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||||
|
|
|
@ -464,9 +464,11 @@ static int push_promise(struct Curl_easy *data,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
rv = data->multi->push_cb(data, newhandle,
|
rv = data->multi->push_cb(data, newhandle,
|
||||||
stream->push_headers_used, &heads,
|
stream->push_headers_used, &heads,
|
||||||
data->multi->push_userp);
|
data->multi->push_userp);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
/* free the headers again */
|
/* free the headers again */
|
||||||
for(i = 0; i<stream->push_headers_used; i++)
|
for(i = 0; i<stream->push_headers_used; i++)
|
||||||
|
|
65
lib/multi.c
65
lib/multi.c
|
@ -366,6 +366,9 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||||
if(data->multi)
|
if(data->multi)
|
||||||
return CURLM_ADDED_ALREADY;
|
return CURLM_ADDED_ALREADY;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
/* Initialize timeout list for this handle */
|
/* Initialize timeout list for this handle */
|
||||||
Curl_llist_init(&data->state.timeoutlist, NULL);
|
Curl_llist_init(&data->state.timeoutlist, NULL);
|
||||||
|
|
||||||
|
@ -640,6 +643,9 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||||
if(!data->multi)
|
if(!data->multi)
|
||||||
return CURLM_OK; /* it is already removed so let's say it is fine! */
|
return CURLM_OK; /* it is already removed so let's say it is fine! */
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
|
premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
|
||||||
easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
|
easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
|
||||||
TRUE : FALSE;
|
TRUE : FALSE;
|
||||||
|
@ -903,6 +909,9 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
data = multi->easyp;
|
data = multi->easyp;
|
||||||
while(data) {
|
while(data) {
|
||||||
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
|
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
|
||||||
|
@ -956,6 +965,9 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
/* If the internally desired timeout is actually shorter than requested from
|
/* If the internally desired timeout is actually shorter than requested from
|
||||||
the outside, then use the shorter time! But only if the internal timer
|
the outside, then use the shorter time! But only if the internal timer
|
||||||
is actually larger than -1! */
|
is actually larger than -1! */
|
||||||
|
@ -1121,6 +1133,9 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
|
||||||
{
|
{
|
||||||
CURLMcode rc;
|
CURLMcode rc;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
rc = curl_multi_add_handle(multi, data);
|
rc = curl_multi_add_handle(multi, data);
|
||||||
if(!rc) {
|
if(!rc) {
|
||||||
struct SingleRequest *k = &data->req;
|
struct SingleRequest *k = &data->req;
|
||||||
|
@ -2127,6 +2142,9 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
data = multi->easyp;
|
data = multi->easyp;
|
||||||
while(data) {
|
while(data) {
|
||||||
CURLMcode result;
|
CURLMcode result;
|
||||||
|
@ -2174,6 +2192,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
|
||||||
struct Curl_easy *nextdata;
|
struct Curl_easy *nextdata;
|
||||||
|
|
||||||
if(GOOD_MULTI_HANDLE(multi)) {
|
if(GOOD_MULTI_HANDLE(multi)) {
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
multi->type = 0; /* not good anymore */
|
multi->type = 0; /* not good anymore */
|
||||||
|
|
||||||
/* Firsrt remove all remaining easy handles */
|
/* Firsrt remove all remaining easy handles */
|
||||||
|
@ -2234,7 +2255,9 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
|
||||||
|
|
||||||
*msgs_in_queue = 0; /* default to none */
|
*msgs_in_queue = 0; /* default to none */
|
||||||
|
|
||||||
if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(&multi->msglist)) {
|
if(GOOD_MULTI_HANDLE(multi) &&
|
||||||
|
!multi->in_callback &&
|
||||||
|
Curl_llist_count(&multi->msglist)) {
|
||||||
/* there is one or more messages in the list */
|
/* there is one or more messages in the list */
|
||||||
struct curl_llist_element *e;
|
struct curl_llist_element *e;
|
||||||
|
|
||||||
|
@ -2624,6 +2647,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
va_start(param, option);
|
va_start(param, option);
|
||||||
|
|
||||||
switch(option) {
|
switch(option) {
|
||||||
|
@ -2688,7 +2714,10 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
|
||||||
CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
|
CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
|
||||||
int *running_handles)
|
int *running_handles)
|
||||||
{
|
{
|
||||||
CURLMcode result = multi_socket(multi, FALSE, s, 0, running_handles);
|
CURLMcode result;
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
result = multi_socket(multi, FALSE, s, 0, running_handles);
|
||||||
if(CURLM_OK >= result)
|
if(CURLM_OK >= result)
|
||||||
update_timer(multi);
|
update_timer(multi);
|
||||||
return result;
|
return result;
|
||||||
|
@ -2697,8 +2726,10 @@ CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
|
||||||
CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
|
CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
|
||||||
int ev_bitmask, int *running_handles)
|
int ev_bitmask, int *running_handles)
|
||||||
{
|
{
|
||||||
CURLMcode result = multi_socket(multi, FALSE, s,
|
CURLMcode result;
|
||||||
ev_bitmask, running_handles);
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
|
||||||
if(CURLM_OK >= result)
|
if(CURLM_OK >= result)
|
||||||
update_timer(multi);
|
update_timer(multi);
|
||||||
return result;
|
return result;
|
||||||
|
@ -2707,8 +2738,10 @@ CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
|
||||||
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
|
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
|
||||||
|
|
||||||
{
|
{
|
||||||
CURLMcode result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0,
|
CURLMcode result;
|
||||||
running_handles);
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
|
||||||
if(CURLM_OK >= result)
|
if(CURLM_OK >= result)
|
||||||
update_timer(multi);
|
update_timer(multi);
|
||||||
return result;
|
return result;
|
||||||
|
@ -2760,6 +2793,9 @@ CURLMcode curl_multi_timeout(struct Curl_multi *multi,
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
return multi_timeout(multi, timeout_ms);
|
return multi_timeout(multi, timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2992,6 +3028,9 @@ CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
|
||||||
{
|
{
|
||||||
struct Curl_sh_entry *there = NULL;
|
struct Curl_sh_entry *there = NULL;
|
||||||
|
|
||||||
|
if(multi->in_callback)
|
||||||
|
return CURLM_RECURSIVE_API_CALL;
|
||||||
|
|
||||||
there = sh_getentry(&multi->sockhash, s);
|
there = sh_getentry(&multi->sockhash, s);
|
||||||
|
|
||||||
if(!there)
|
if(!there)
|
||||||
|
@ -3054,6 +3093,20 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curl_set_in_callback(struct Curl_easy *easy, bool value)
|
||||||
|
{
|
||||||
|
if(easy->multi_easy)
|
||||||
|
easy->multi_easy->in_callback = value;
|
||||||
|
else if(easy->multi)
|
||||||
|
easy->multi->in_callback = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Curl_is_in_callback(struct Curl_easy *easy)
|
||||||
|
{
|
||||||
|
return ((easy->multi && easy->multi->in_callback) ||
|
||||||
|
(easy->multi_easy && easy->multi_easy->in_callback));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
void Curl_multi_dump(struct Curl_multi *multi)
|
void Curl_multi_dump(struct Curl_multi *multi)
|
||||||
{
|
{
|
||||||
|
|
|
@ -146,6 +146,7 @@ struct Curl_multi {
|
||||||
void *timer_userp;
|
void *timer_userp;
|
||||||
struct curltime timer_lastcall; /* the fixed time for the timeout for the
|
struct curltime timer_lastcall; /* the fixed time for the timeout for the
|
||||||
previous callback */
|
previous callback */
|
||||||
|
bool in_callback; /* true while executing a callback */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HEADER_CURL_MULTIHANDLE_H */
|
#endif /* HEADER_CURL_MULTIHANDLE_H */
|
||||||
|
|
|
@ -31,6 +31,8 @@ void Curl_expire_clear(struct Curl_easy *data);
|
||||||
void Curl_expire_done(struct Curl_easy *data, expire_id id);
|
void Curl_expire_done(struct Curl_easy *data, expire_id id);
|
||||||
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
|
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
|
||||||
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
|
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
|
||||||
|
void Curl_set_in_callback(struct Curl_easy *data, bool value);
|
||||||
|
bool Curl_is_in_callback(struct Curl_easy *easy);
|
||||||
|
|
||||||
/* Internal version of curl_multi_init() accepts size parameters for the
|
/* Internal version of curl_multi_init() accepts size parameters for the
|
||||||
socket and connection hashes */
|
socket and connection hashes */
|
||||||
|
|
|
@ -84,7 +84,10 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
|
||||||
{
|
{
|
||||||
if(data && data->set.convtonetwork) {
|
if(data && data->set.convtonetwork) {
|
||||||
/* use translation callback */
|
/* use translation callback */
|
||||||
CURLcode result = data->set.convtonetwork(buffer, length);
|
CURLcode result;
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
|
result = data->set.convtonetwork(buffer, length);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
if(result) {
|
if(result) {
|
||||||
failf(data,
|
failf(data,
|
||||||
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
|
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
|
||||||
|
@ -147,7 +150,10 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
|
||||||
{
|
{
|
||||||
if(data && data->set.convfromnetwork) {
|
if(data && data->set.convfromnetwork) {
|
||||||
/* use translation callback */
|
/* use translation callback */
|
||||||
CURLcode result = data->set.convfromnetwork(buffer, length);
|
CURLcode result;
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
|
result = data->set.convfromnetwork(buffer, length);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
if(result) {
|
if(result) {
|
||||||
failf(data,
|
failf(data,
|
||||||
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
|
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
|
||||||
|
@ -210,7 +216,10 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
|
||||||
{
|
{
|
||||||
if(data && data->set.convfromutf8) {
|
if(data && data->set.convfromutf8) {
|
||||||
/* use translation callback */
|
/* use translation callback */
|
||||||
CURLcode result = data->set.convfromutf8(buffer, length);
|
CURLcode result;
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
|
result = data->set.convfromutf8(buffer, length);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
if(result) {
|
if(result) {
|
||||||
failf(data,
|
failf(data,
|
||||||
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
|
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
|
#include "multiif.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "curl_printf.h"
|
#include "curl_printf.h"
|
||||||
|
|
||||||
|
@ -461,22 +462,26 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
||||||
|
|
||||||
if(data->set.fxferinfo) {
|
if(data->set.fxferinfo) {
|
||||||
/* There's a callback set, call that */
|
/* There's a callback set, call that */
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
result = data->set.fxferinfo(data->set.progress_client,
|
result = data->set.fxferinfo(data->set.progress_client,
|
||||||
data->progress.size_dl,
|
data->progress.size_dl,
|
||||||
data->progress.downloaded,
|
data->progress.downloaded,
|
||||||
data->progress.size_ul,
|
data->progress.size_ul,
|
||||||
data->progress.uploaded);
|
data->progress.uploaded);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
if(result)
|
if(result)
|
||||||
failf(data, "Callback aborted");
|
failf(data, "Callback aborted");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if(data->set.fprogress) {
|
if(data->set.fprogress) {
|
||||||
/* The older deprecated callback is set, call that */
|
/* The older deprecated callback is set, call that */
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
result = data->set.fprogress(data->set.progress_client,
|
result = data->set.fprogress(data->set.progress_client,
|
||||||
(double)data->progress.size_dl,
|
(double)data->progress.size_dl,
|
||||||
(double)data->progress.downloaded,
|
(double)data->progress.downloaded,
|
||||||
(double)data->progress.size_ul,
|
(double)data->progress.size_ul,
|
||||||
(double)data->progress.uploaded);
|
(double)data->progress.uploaded);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
if(result)
|
if(result)
|
||||||
failf(data, "Callback aborted");
|
failf(data, "Callback aborted");
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -770,7 +770,9 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
|
||||||
user_ptr = data->set.out;
|
user_ptr = data->set.out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
wrote = writeit(ptr, 1, len, user_ptr);
|
wrote = writeit(ptr, 1, len, user_ptr);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
if(CURL_WRITEFUNC_PAUSE == wrote) {
|
if(CURL_WRITEFUNC_PAUSE == wrote) {
|
||||||
failf(data, "Cannot pause RTP");
|
failf(data, "Cannot pause RTP");
|
||||||
|
|
11
lib/sendf.c
11
lib/sendf.c
|
@ -37,6 +37,7 @@
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "vtls/vtls.h"
|
#include "vtls/vtls.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
#include "easyif.h"
|
||||||
#include "multiif.h"
|
#include "multiif.h"
|
||||||
#include "non-ascii.h"
|
#include "non-ascii.h"
|
||||||
#include "strerror.h"
|
#include "strerror.h"
|
||||||
|
@ -598,7 +599,10 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writeheader) {
|
if(writeheader) {
|
||||||
size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
|
size_t wrote;
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
|
wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
if(CURL_WRITEFUNC_PAUSE == wrote)
|
if(CURL_WRITEFUNC_PAUSE == wrote)
|
||||||
/* here we pass in the HEADER bit only since if this was body as well
|
/* here we pass in the HEADER bit only since if this was body as well
|
||||||
|
@ -798,8 +802,11 @@ static int showit(struct Curl_easy *data, curl_infotype type,
|
||||||
}
|
}
|
||||||
#endif /* CURL_DOES_CONVERSIONS */
|
#endif /* CURL_DOES_CONVERSIONS */
|
||||||
|
|
||||||
if(data->set.fdebug)
|
if(data->set.fdebug) {
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
|
rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case CURLINFO_TEXT:
|
case CURLINFO_TEXT:
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "setopt.h"
|
#include "setopt.h"
|
||||||
|
#include "multiif.h"
|
||||||
|
|
||||||
/* The last 3 #include files should be in this order */
|
/* The last 3 #include files should be in this order */
|
||||||
#include "curl_printf.h"
|
#include "curl_printf.h"
|
||||||
|
@ -2544,6 +2545,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
|
||||||
/*
|
/*
|
||||||
* curl_easy_setopt() is the external interface for setting options on an
|
* curl_easy_setopt() is the external interface for setting options on an
|
||||||
* easy handle.
|
* easy handle.
|
||||||
|
*
|
||||||
|
* NOTE: This is one of few API functions that are allowed to be called from
|
||||||
|
* within a callback.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef curl_easy_setopt
|
#undef curl_easy_setopt
|
||||||
|
|
|
@ -383,8 +383,10 @@ static int myssh_is_known(struct connectdata *conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we don't have anything equivalent to knownkey. Always NULL */
|
/* we don't have anything equivalent to knownkey. Always NULL */
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
rc = func(data, NULL, &foundkey, /* from the remote host */
|
rc = func(data, NULL, &foundkey, /* from the remote host */
|
||||||
keymatch, data->set.ssh_keyfunc_userp);
|
keymatch, data->set.ssh_keyfunc_userp);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
switch(rc) {
|
switch(rc) {
|
||||||
case CURLKHSTAT_FINE_ADD_TO_FILE:
|
case CURLKHSTAT_FINE_ADD_TO_FILE:
|
||||||
|
@ -1128,8 +1130,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
|
||||||
if(data->state.resume_from > 0) {
|
if(data->state.resume_from > 0) {
|
||||||
/* Let's read off the proper amount of bytes from the input. */
|
/* Let's read off the proper amount of bytes from the input. */
|
||||||
if(conn->seek_func) {
|
if(conn->seek_func) {
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
||||||
SEEK_SET);
|
SEEK_SET);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seekerr != CURL_SEEKFUNC_OK) {
|
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||||
|
|
13
lib/ssh.c
13
lib/ssh.c
|
@ -523,9 +523,11 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
|
||||||
keymatch = (enum curl_khmatch)keycheck;
|
keymatch = (enum curl_khmatch)keycheck;
|
||||||
|
|
||||||
/* Ask the callback how to behave */
|
/* Ask the callback how to behave */
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
rc = func(data, knownkeyp, /* from the knownhosts file */
|
rc = func(data, knownkeyp, /* from the knownhosts file */
|
||||||
&foundkey, /* from the remote host */
|
&foundkey, /* from the remote host */
|
||||||
keymatch, data->set.ssh_keyfunc_userp);
|
keymatch, data->set.ssh_keyfunc_userp);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* no remotekey means failure! */
|
/* no remotekey means failure! */
|
||||||
|
@ -1747,8 +1749,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||||
if(data->state.resume_from > 0) {
|
if(data->state.resume_from > 0) {
|
||||||
/* Let's read off the proper amount of bytes from the input. */
|
/* Let's read off the proper amount of bytes from the input. */
|
||||||
if(conn->seek_func) {
|
if(conn->seek_func) {
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
||||||
SEEK_SET);
|
SEEK_SET);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seekerr != CURL_SEEKFUNC_OK) {
|
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||||
|
@ -1765,9 +1769,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||||
(size_t)data->set.buffer_size :
|
(size_t)data->set.buffer_size :
|
||||||
curlx_sotouz(data->state.resume_from - passed);
|
curlx_sotouz(data->state.resume_from - passed);
|
||||||
|
|
||||||
size_t actuallyread =
|
size_t actuallyread;
|
||||||
data->state.fread_func(data->state.buffer, 1,
|
Curl_set_in_callback(data, true);
|
||||||
readthisamountnow, data->state.in);
|
actuallyread = data->state.fread_func(data->state.buffer, 1,
|
||||||
|
readthisamountnow,
|
||||||
|
data->state.in);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
passed += actuallyread;
|
passed += actuallyread;
|
||||||
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
|
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
|
||||||
|
|
|
@ -312,6 +312,9 @@ curl_easy_strerror(CURLcode error)
|
||||||
case CURLE_HTTP2_STREAM:
|
case CURLE_HTTP2_STREAM:
|
||||||
return "Stream error in the HTTP/2 framing layer";
|
return "Stream error in the HTTP/2 framing layer";
|
||||||
|
|
||||||
|
case CURLE_RECURSIVE_API_CALL:
|
||||||
|
return "API function called from within callback";
|
||||||
|
|
||||||
/* error codes not used by current libcurl */
|
/* error codes not used by current libcurl */
|
||||||
case CURLE_OBSOLETE20:
|
case CURLE_OBSOLETE20:
|
||||||
case CURLE_OBSOLETE24:
|
case CURLE_OBSOLETE24:
|
||||||
|
@ -380,6 +383,9 @@ curl_multi_strerror(CURLMcode error)
|
||||||
case CURLM_ADDED_ALREADY:
|
case CURLM_ADDED_ALREADY:
|
||||||
return "The easy handle is already added to a multi handle";
|
return "The easy handle is already added to a multi handle";
|
||||||
|
|
||||||
|
case CURLM_RECURSIVE_API_CALL:
|
||||||
|
return "API function called from within callback";
|
||||||
|
|
||||||
case CURLM_LAST:
|
case CURLM_LAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,8 +135,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
|
||||||
|
|
||||||
/* this function returns a size_t, so we typecast to int to prevent warnings
|
/* this function returns a size_t, so we typecast to int to prevent warnings
|
||||||
with picky compilers */
|
with picky compilers */
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
nread = (int)data->state.fread_func(data->req.upload_fromhere, 1,
|
nread = (int)data->state.fread_func(data->req.upload_fromhere, 1,
|
||||||
buffersize, data->state.in);
|
buffersize, data->state.in);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
|
|
||||||
if(nread == CURL_READFUNC_ABORT) {
|
if(nread == CURL_READFUNC_ABORT) {
|
||||||
failf(data, "operation aborted by callback");
|
failf(data, "operation aborted by callback");
|
||||||
|
@ -302,7 +304,9 @@ CURLcode Curl_readrewind(struct connectdata *conn)
|
||||||
if(data->set.seek_func) {
|
if(data->set.seek_func) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
|
err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
if(err) {
|
if(err) {
|
||||||
failf(data, "seek callback returned error %d", (int)err);
|
failf(data, "seek callback returned error %d", (int)err);
|
||||||
return CURLE_SEND_FAIL_REWIND;
|
return CURLE_SEND_FAIL_REWIND;
|
||||||
|
@ -311,8 +315,10 @@ CURLcode Curl_readrewind(struct connectdata *conn)
|
||||||
else if(data->set.ioctl_func) {
|
else if(data->set.ioctl_func) {
|
||||||
curlioerr err;
|
curlioerr err;
|
||||||
|
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
|
err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
|
||||||
data->set.ioctl_client);
|
data->set.ioctl_client);
|
||||||
|
Curl_set_in_callback(data, false);
|
||||||
infof(data, "the ioctl callback returned %d\n", (int)err);
|
infof(data, "the ioctl callback returned %d\n", (int)err);
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
|
|
|
@ -171,7 +171,7 @@ test1520 test1521 \
|
||||||
test1525 test1526 test1527 test1528 test1529 test1530 test1531 test1532 \
|
test1525 test1526 test1527 test1528 test1529 test1530 test1531 test1532 \
|
||||||
test1533 test1534 test1535 test1536 test1537 test1538 \
|
test1533 test1534 test1535 test1536 test1537 test1538 \
|
||||||
test1540 \
|
test1540 \
|
||||||
test1550 test1551 test1552 test1553 test1554 \
|
test1550 test1551 test1552 test1553 test1554 test1555 \
|
||||||
test1600 test1601 test1602 test1603 test1604 test1605 test1606 \
|
test1600 test1601 test1602 test1603 test1604 test1605 test1606 \
|
||||||
\
|
\
|
||||||
test1700 test1701 test1702 \
|
test1700 test1701 test1702 \
|
||||||
|
|
|
@ -125,7 +125,8 @@ e89: The max connection limit is reached
|
||||||
e90: SSL public key does not match pinned public key
|
e90: SSL public key does not match pinned public key
|
||||||
e91: SSL server certificate status verification FAILED
|
e91: SSL server certificate status verification FAILED
|
||||||
e92: Stream error in the HTTP/2 framing layer
|
e92: Stream error in the HTTP/2 framing layer
|
||||||
e93: Unknown error
|
e93: API function called from within callback
|
||||||
|
e94: Unknown error
|
||||||
m-1: Please call curl_multi_perform() soon
|
m-1: Please call curl_multi_perform() soon
|
||||||
m0: No error
|
m0: No error
|
||||||
m1: Invalid multi handle
|
m1: Invalid multi handle
|
||||||
|
@ -135,7 +136,8 @@ m4: Internal error
|
||||||
m5: Invalid socket argument
|
m5: Invalid socket argument
|
||||||
m6: Unknown option
|
m6: Unknown option
|
||||||
m7: The easy handle is already added to a multi handle
|
m7: The easy handle is already added to a multi handle
|
||||||
m8: Unknown error
|
m8: API function called from within callback
|
||||||
|
m9: Unknown error
|
||||||
s0: No error
|
s0: No error
|
||||||
s1: Unknown share option
|
s1: Unknown share option
|
||||||
s2: Share currently in use
|
s2: Share currently in use
|
||||||
|
|
50
tests/data/test1555
Normal file
50
tests/data/test1555
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
RECURSIVE_API_CALL
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
HTTP/1.1 204 PARTIAL
|
||||||
|
X-Comment: partial response to keep the client waiting
|
||||||
|
</data>
|
||||||
|
<postcmd>
|
||||||
|
wait 10
|
||||||
|
</postcmd>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<tool>
|
||||||
|
lib1555
|
||||||
|
</tool>
|
||||||
|
<name>
|
||||||
|
verify api is protected against calls from callbacks
|
||||||
|
</name>
|
||||||
|
|
||||||
|
# this server/host won't be used for real
|
||||||
|
<command>
|
||||||
|
http://%HOSTIP:%HTTPPORT/1555
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
</protocol>
|
||||||
|
# 42 == CURLE_ABORTED_BY_CALLBACK
|
||||||
|
<errorcode>
|
||||||
|
42
|
||||||
|
</errorcode>
|
||||||
|
<stdout>
|
||||||
|
curl_easy_recv returned 93
|
||||||
|
curl_easy_send returned 93
|
||||||
|
</stdout>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
|
@ -27,7 +27,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
|
||||||
lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \
|
lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \
|
||||||
lib1534 lib1535 lib1536 lib1537 lib1538 \
|
lib1534 lib1535 lib1536 lib1537 lib1538 \
|
||||||
lib1540 \
|
lib1540 \
|
||||||
lib1550 lib1551 lib1552 lib1553 lib1554 \
|
lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 \
|
||||||
lib1900 \
|
lib1900 \
|
||||||
lib2033
|
lib2033
|
||||||
|
|
||||||
|
@ -477,6 +477,10 @@ lib1553_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
lib1554_SOURCES = lib1554.c $(SUPPORTFILES)
|
lib1554_SOURCES = lib1554.c $(SUPPORTFILES)
|
||||||
lib1554_CPPFLAGS = $(AM_CPPFLAGS)
|
lib1554_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
|
||||||
|
lib1555_SOURCES = lib1555.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
|
||||||
|
lib1555_LDADD = $(TESTUTIL_LIBS)
|
||||||
|
lib1555_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1555
|
||||||
|
|
||||||
lib1900_SOURCES = lib1900.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
|
lib1900_SOURCES = lib1900.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
|
||||||
lib1900_LDADD = $(TESTUTIL_LIBS)
|
lib1900_LDADD = $(TESTUTIL_LIBS)
|
||||||
lib1900_CPPFLAGS = $(AM_CPPFLAGS)
|
lib1900_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
|
77
tests/libtest/lib1555.c
Normal file
77
tests/libtest/lib1555.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2015, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
/*
|
||||||
|
* Verify that some API functions are locked from being called inside callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
static CURL *curl;
|
||||||
|
|
||||||
|
static int progressCallback(void *arg,
|
||||||
|
double dltotal,
|
||||||
|
double dlnow,
|
||||||
|
double ultotal,
|
||||||
|
double ulnow)
|
||||||
|
{
|
||||||
|
CURLcode res = 0;
|
||||||
|
(void)arg;
|
||||||
|
(void)dltotal;
|
||||||
|
(void)dlnow;
|
||||||
|
(void)ultotal;
|
||||||
|
(void)ulnow;
|
||||||
|
res = curl_easy_recv(curl, NULL, 0, NULL);
|
||||||
|
printf("curl_easy_recv returned %d\n", res);
|
||||||
|
res = curl_easy_send(curl, NULL, 0, NULL);
|
||||||
|
printf("curl_easy_send returned %d\n", res);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test(char *URL)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
global_init(CURL_GLOBAL_ALL);
|
||||||
|
|
||||||
|
easy_init(curl);
|
||||||
|
|
||||||
|
easy_setopt(curl, CURLOPT_URL, URL);
|
||||||
|
easy_setopt(curl, CURLOPT_TIMEOUT, (long)7);
|
||||||
|
easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
|
||||||
|
easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressCallback);
|
||||||
|
easy_setopt(curl, CURLOPT_PROGRESSDATA, NULL);
|
||||||
|
easy_setopt(curl, CURLOPT_NOPROGRESS, (long)0);
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
test_cleanup:
|
||||||
|
|
||||||
|
/* undocumented cleanup sequence - type UA */
|
||||||
|
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
curl_global_cleanup();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user