mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
always-multi: always use non-blocking internals
Remove internal separated behavior of the easy vs multi intercace. curl_easy_perform() is now using the multi interface itself. Several minor multi interface quirks and bugs have been fixed in the process. Much help with debugging this has been provided by: Yang Tse
This commit is contained in:
parent
9fd88abb70
commit
c43127414d
14
docs/TODO
14
docs/TODO
@ -21,8 +21,7 @@
|
|||||||
|
|
||||||
2. libcurl - multi interface
|
2. libcurl - multi interface
|
||||||
2.1 More non-blocking
|
2.1 More non-blocking
|
||||||
2.2 Remove easy interface internally
|
2.2 Fix HTTP Pipelining for PUT
|
||||||
2.4 Fix HTTP Pipelining for PUT
|
|
||||||
|
|
||||||
3. Documentation
|
3. Documentation
|
||||||
3.1 More and better
|
3.1 More and better
|
||||||
@ -191,16 +190,7 @@
|
|||||||
- The "DONE" operation (post transfer protocol-specific actions) for the
|
- The "DONE" operation (post transfer protocol-specific actions) for the
|
||||||
protocols SFTP, SMTP, FTP. Fixing Curl_done() for this is a worthy task.
|
protocols SFTP, SMTP, FTP. Fixing Curl_done() for this is a worthy task.
|
||||||
|
|
||||||
2.2 Remove easy interface internally
|
2.2 Fix HTTP Pipelining for PUT
|
||||||
|
|
||||||
Make curl_easy_perform() a wrapper-function that simply creates a multi
|
|
||||||
handle, adds the easy handle to it, runs curl_multi_perform() until the
|
|
||||||
transfer is done, then detach the easy handle, destroy the multi handle and
|
|
||||||
return the easy handle's return code. This will thus make everything
|
|
||||||
internally use and assume the multi interface. The select()-loop should use
|
|
||||||
curl_multi_socket().
|
|
||||||
|
|
||||||
2.4 Fix HTTP Pipelining for PUT
|
|
||||||
|
|
||||||
HTTP Pipelining can be a way to greatly enhance performance for multiple
|
HTTP Pipelining can be a way to greatly enhance performance for multiple
|
||||||
serial requests and currently libcurl only supports that for HEAD and GET
|
serial requests and currently libcurl only supports that for HEAD and GET
|
||||||
|
@ -43,4 +43,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
|
|||||||
gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h curl_ntlm.h \
|
gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h curl_ntlm.h \
|
||||||
curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h curl_ntlm_msgs.h \
|
curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h curl_ntlm_msgs.h \
|
||||||
curl_sasl.h curl_schannel.h curl_multibyte.h curl_darwinssl.h \
|
curl_sasl.h curl_schannel.h curl_multibyte.h curl_darwinssl.h \
|
||||||
hostcheck.h bundles.h conncache.h curl_setup_once.h
|
hostcheck.h bundles.h conncache.h curl_setup_once.h multihandle.h
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
|
* Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
|
||||||
* Copyright (C) 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2012 - 2013, 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
|
||||||
@ -47,7 +47,7 @@ static void free_bundle_hash_entry(void *freethis)
|
|||||||
Curl_bundle_destroy(b);
|
Curl_bundle_destroy(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct conncache *Curl_conncache_init(conncachetype type)
|
struct conncache *Curl_conncache_init(void)
|
||||||
{
|
{
|
||||||
struct conncache *connc;
|
struct conncache *connc;
|
||||||
|
|
||||||
@ -63,9 +63,6 @@ struct conncache *Curl_conncache_init(conncachetype type)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
connc->type = type;
|
|
||||||
connc->num_connections = 0;
|
|
||||||
|
|
||||||
return connc;
|
return connc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
|
* Copyright (C) 2012, 2013, 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
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -22,18 +22,12 @@
|
|||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CONNCACHE_PRIVATE, /* used for an easy handle alone */
|
|
||||||
CONNCACHE_MULTI /* shared within a multi handle */
|
|
||||||
} conncachetype;
|
|
||||||
|
|
||||||
struct conncache {
|
struct conncache {
|
||||||
struct curl_hash *hash;
|
struct curl_hash *hash;
|
||||||
conncachetype type;
|
|
||||||
size_t num_connections;
|
size_t num_connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct conncache *Curl_conncache_init(conncachetype type);
|
struct conncache *Curl_conncache_init(void);
|
||||||
|
|
||||||
void Curl_conncache_destroy(struct conncache *connc);
|
void Curl_conncache_destroy(struct conncache *connc);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -74,6 +74,8 @@
|
|||||||
#include "sslgen.h" /* for Curl_ssl_check_cxn() */
|
#include "sslgen.h" /* for Curl_ssl_check_cxn() */
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "warnless.h"
|
#include "warnless.h"
|
||||||
|
#include "conncache.h"
|
||||||
|
#include "multihandle.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
@ -980,8 +982,7 @@ singleipconnect(struct connectdata *conn,
|
|||||||
|
|
||||||
/* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
|
/* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
|
||||||
connect(). We can be sure of this since connect() cannot return 1. */
|
connect(). We can be sure of this since connect() cannot return 1. */
|
||||||
if((WAITCONN_TIMEOUT == rc) &&
|
if(WAITCONN_TIMEOUT == rc) {
|
||||||
(data->state.used_interface == Curl_if_multi)) {
|
|
||||||
/* Timeout when running the multi interface */
|
/* Timeout when running the multi interface */
|
||||||
*sockp = sockfd;
|
*sockp = sockfd;
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
@ -1072,9 +1073,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
|
|
||||||
/* start connecting to the IP curr_addr points to */
|
/* start connecting to the IP curr_addr points to */
|
||||||
res = singleipconnect(conn, curr_addr,
|
res = singleipconnect(conn, curr_addr,
|
||||||
/* don't hang when doing multi */
|
0, /* don't hang when doing multi */
|
||||||
(data->state.used_interface == Curl_if_multi)?0:
|
&sockfd, connected);
|
||||||
conn->timeoutms_per_addr, &sockfd, connected);
|
|
||||||
if(res)
|
if(res)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
@ -1112,6 +1112,21 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct connfind {
|
||||||
|
struct connectdata *tofind;
|
||||||
|
bool found;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int conn_is_conn(struct connectdata *conn, void *param)
|
||||||
|
{
|
||||||
|
struct connfind *f = (struct connfind *)param;
|
||||||
|
if(conn == f->tofind) {
|
||||||
|
f->found = TRUE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used to extract socket and connectdata struct for the most recent
|
* Used to extract socket and connectdata struct for the most recent
|
||||||
* transfer on the given SessionHandle.
|
* transfer on the given SessionHandle.
|
||||||
@ -1125,8 +1140,21 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
|
|||||||
|
|
||||||
DEBUGASSERT(data);
|
DEBUGASSERT(data);
|
||||||
|
|
||||||
if(data->state.lastconnect) {
|
/* this only works for an easy handle that has been used for
|
||||||
|
curl_easy_perform()! */
|
||||||
|
if(data->state.lastconnect && data->multi_easy) {
|
||||||
struct connectdata *c = data->state.lastconnect;
|
struct connectdata *c = data->state.lastconnect;
|
||||||
|
struct connfind find;
|
||||||
|
find.tofind = data->state.lastconnect;
|
||||||
|
find.found = FALSE;
|
||||||
|
|
||||||
|
Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn);
|
||||||
|
|
||||||
|
if(!find.found) {
|
||||||
|
data->state.lastconnect = NULL;
|
||||||
|
return CURL_SOCKET_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
if(connp)
|
if(connp)
|
||||||
/* only store this if the caller cares for it */
|
/* only store this if the caller cares for it */
|
||||||
*connp = c;
|
*connp = c;
|
||||||
|
163
lib/easy.c
163
lib/easy.c
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -385,40 +385,46 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CURL_MULTIEASY
|
/*
|
||||||
/***************************************************************************
|
* curl_easy_perform() is the external interface that performs a blocking
|
||||||
* This function is still only for testing purposes. It makes a great way
|
* transfer as previously setup.
|
||||||
* to run the full test suite on the multi interface instead of the easy one.
|
|
||||||
***************************************************************************
|
|
||||||
*
|
*
|
||||||
* The *new* curl_easy_perform() is the external interface that performs a
|
* CONCEPT: This function creates a multi handle, adds the easy handle to it,
|
||||||
* transfer previously setup.
|
|
||||||
*
|
|
||||||
* Wrapper-function that: creates a multi handle, adds the easy handle to it,
|
|
||||||
* runs curl_multi_perform() until the transfer is done, then detaches the
|
* runs curl_multi_perform() until the transfer is done, then detaches the
|
||||||
* easy handle, destroys the multi handle and returns the easy handle's return
|
* easy handle, destroys the multi handle and returns the easy handle's return
|
||||||
* code. This will make everything internally use and assume multi interface.
|
* code.
|
||||||
|
*
|
||||||
|
* REALITY: it can't just create and destroy the multi handle that easily. It
|
||||||
|
* needs to keep it around since if this easy handle is used again by this
|
||||||
|
* function, the same multi handle must be re-used so that the same pools and
|
||||||
|
* caches can be used.
|
||||||
*/
|
*/
|
||||||
CURLcode curl_easy_perform(CURL *easy)
|
CURLcode curl_easy_perform(CURL *easy)
|
||||||
{
|
{
|
||||||
CURLM *multi;
|
CURLM *multi;
|
||||||
CURLMcode mcode;
|
CURLMcode mcode;
|
||||||
CURLcode code = CURLE_OK;
|
CURLcode code = CURLE_OK;
|
||||||
int still_running;
|
|
||||||
struct timeval timeout;
|
|
||||||
int rc;
|
|
||||||
CURLMsg *msg;
|
CURLMsg *msg;
|
||||||
fd_set fdread;
|
bool done = FALSE;
|
||||||
fd_set fdwrite;
|
int rc;
|
||||||
fd_set fdexcep;
|
struct SessionHandle *data = easy;
|
||||||
int maxfd;
|
|
||||||
|
|
||||||
if(!easy)
|
if(!easy)
|
||||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
|
|
||||||
multi = curl_multi_init();
|
if(data->multi) {
|
||||||
if(!multi)
|
failf(data, "easy handled already used in multi handle");
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_FAILED_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->multi_easy)
|
||||||
|
multi = data->multi_easy;
|
||||||
|
else {
|
||||||
|
multi = curl_multi_init();
|
||||||
|
if(!multi)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
data->multi_easy = multi;
|
||||||
|
}
|
||||||
|
|
||||||
mcode = curl_multi_add_handle(multi, easy);
|
mcode = curl_multi_add_handle(multi, easy);
|
||||||
if(mcode) {
|
if(mcode) {
|
||||||
@ -429,108 +435,33 @@ CURLcode curl_easy_perform(CURL *easy)
|
|||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
/* assign this after curl_multi_add_handle() since that function checks for
|
||||||
|
it and rejects this handle otherwise */
|
||||||
|
data->multi = multi;
|
||||||
|
|
||||||
do {
|
while(!done && !mcode) {
|
||||||
while(CURLM_CALL_MULTI_PERFORM ==
|
int still_running;
|
||||||
curl_multi_perform(multi, &still_running));
|
|
||||||
|
|
||||||
if(!still_running)
|
mcode = curl_multi_wait(multi, NULL, 0, 1000, NULL);
|
||||||
break;
|
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
if(mcode == CURLM_OK)
|
||||||
FD_ZERO(&fdwrite);
|
mcode = curl_multi_perform(multi, &still_running);
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* timeout once per second */
|
/* only read 'still_running' if curl_multi_perform() return OK */
|
||||||
timeout.tv_sec = 1;
|
if((mcode == CURLM_OK) && !still_running) {
|
||||||
timeout.tv_usec = 0;
|
msg = curl_multi_info_read(multi, &rc);
|
||||||
|
if(msg) {
|
||||||
/* Old deprecated style: get file descriptors from the transfers */
|
code = msg->data.result;
|
||||||
curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
|
done = TRUE;
|
||||||
rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
}
|
||||||
|
}
|
||||||
/* The way is to extract the sockets and wait for them without using
|
}
|
||||||
select. This whole alternative version should probably rather use the
|
|
||||||
curl_multi_socket() approach. */
|
|
||||||
|
|
||||||
if(rc == -1)
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* timeout or data to send/receive => loop! */
|
|
||||||
} while(still_running);
|
|
||||||
|
|
||||||
msg = curl_multi_info_read(multi, &rc);
|
|
||||||
if(msg)
|
|
||||||
code = msg->data.result;
|
|
||||||
|
|
||||||
mcode = curl_multi_remove_handle(multi, easy);
|
mcode = curl_multi_remove_handle(multi, easy);
|
||||||
/* what to do if it fails? */
|
|
||||||
|
|
||||||
mcode = curl_multi_cleanup(multi);
|
|
||||||
/* what to do if it fails? */
|
|
||||||
|
|
||||||
|
/* The multi handle is kept alive, owned by the easy handle */
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* curl_easy_perform() is the external interface that performs a transfer
|
|
||||||
* previously setup.
|
|
||||||
*/
|
|
||||||
CURLcode curl_easy_perform(CURL *curl)
|
|
||||||
{
|
|
||||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
|
||||||
|
|
||||||
if(!data)
|
|
||||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
|
||||||
|
|
||||||
if(! (data->share && data->share->hostcache)) {
|
|
||||||
/* this handle is not using a shared dns cache */
|
|
||||||
|
|
||||||
if(data->set.global_dns_cache &&
|
|
||||||
(data->dns.hostcachetype != HCACHE_GLOBAL)) {
|
|
||||||
/* global dns cache was requested but still isn't */
|
|
||||||
struct curl_hash *ptr;
|
|
||||||
|
|
||||||
if(data->dns.hostcachetype == HCACHE_PRIVATE) {
|
|
||||||
/* if the current cache is private, kill it first */
|
|
||||||
Curl_hash_destroy(data->dns.hostcache);
|
|
||||||
data->dns.hostcachetype = HCACHE_NONE;
|
|
||||||
data->dns.hostcache = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = Curl_global_host_cache_init();
|
|
||||||
if(ptr) {
|
|
||||||
/* only do this if the global cache init works */
|
|
||||||
data->dns.hostcache = ptr;
|
|
||||||
data->dns.hostcachetype = HCACHE_GLOBAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!data->dns.hostcache) {
|
|
||||||
data->dns.hostcachetype = HCACHE_PRIVATE;
|
|
||||||
data->dns.hostcache = Curl_mk_dnscache();
|
|
||||||
|
|
||||||
if(!data->dns.hostcache)
|
|
||||||
/* While we possibly could survive and do good without a host cache,
|
|
||||||
the fact that creating it failed indicates that things are truly
|
|
||||||
screwed up and we should bail out! */
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!data->state.conn_cache) {
|
|
||||||
/* Oops, no connection cache, create one */
|
|
||||||
data->state.conn_cache = Curl_conncache_init(CONNCACHE_PRIVATE);
|
|
||||||
if(!data->state.conn_cache)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Curl_perform(data);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
|
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
|
||||||
@ -553,10 +484,6 @@ void Curl_easy_addmulti(struct SessionHandle *data,
|
|||||||
void *multi)
|
void *multi)
|
||||||
{
|
{
|
||||||
data->multi = multi;
|
data->multi = multi;
|
||||||
if(multi == NULL)
|
|
||||||
/* the association is cleared, mark the easy handle as not used by an
|
|
||||||
interface */
|
|
||||||
data->state.used_interface = Curl_if_none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curl_easy_initHandleData(struct SessionHandle *data)
|
void Curl_easy_initHandleData(struct SessionHandle *data)
|
||||||
|
168
lib/ftp.c
168
lib/ftp.c
@ -101,8 +101,17 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Local API functions */
|
/* Local API functions */
|
||||||
static void state(struct connectdata *conn,
|
#ifndef DEBUGBUILD
|
||||||
ftpstate newstate);
|
static void _state(struct connectdata *conn,
|
||||||
|
ftpstate newstate);
|
||||||
|
#define state(x,y) _state(x,y)
|
||||||
|
#else
|
||||||
|
static void _state(struct connectdata *conn,
|
||||||
|
ftpstate newstate,
|
||||||
|
int lineno);
|
||||||
|
#define state(x,y) _state(x,y,__LINE__)
|
||||||
|
#endif
|
||||||
|
|
||||||
static CURLcode ftp_sendquote(struct connectdata *conn,
|
static CURLcode ftp_sendquote(struct connectdata *conn,
|
||||||
struct curl_slist *quote);
|
struct curl_slist *quote);
|
||||||
static CURLcode ftp_quit(struct connectdata *conn);
|
static CURLcode ftp_quit(struct connectdata *conn);
|
||||||
@ -149,6 +158,8 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
|||||||
struct pingpong *pp,
|
struct pingpong *pp,
|
||||||
int *ftpcode,
|
int *ftpcode,
|
||||||
size_t *size);
|
size_t *size);
|
||||||
|
static CURLcode ftp_dophase_done(struct connectdata *conn,
|
||||||
|
bool connected);
|
||||||
|
|
||||||
/* easy-to-use macro: */
|
/* easy-to-use macro: */
|
||||||
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z)) != CURLE_OK) \
|
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z)) != CURLE_OK) \
|
||||||
@ -411,7 +422,7 @@ static long ftp_timeleft_accept(struct SessionHandle *data)
|
|||||||
* connection for a negative response regarding a failure in connecting
|
* connection for a negative response regarding a failure in connecting
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static CURLcode ReceivedServerConnect(struct connectdata* conn, bool* received)
|
static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
|
curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
|
||||||
@ -514,8 +525,8 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
|
|||||||
else {
|
else {
|
||||||
/* FTP download: */
|
/* FTP download: */
|
||||||
Curl_setup_transfer(conn, SECONDARYSOCKET,
|
Curl_setup_transfer(conn, SECONDARYSOCKET,
|
||||||
conn->proto.ftpc.retr_size_saved, FALSE,
|
conn->proto.ftpc.retr_size_saved, FALSE,
|
||||||
ftp->bytecountp, -1, NULL); /* no upload here */
|
ftp->bytecountp, -1, NULL); /* no upload here */
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
|
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
|
||||||
@ -528,18 +539,15 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
|
|||||||
*
|
*
|
||||||
* AllowServerConnect()
|
* AllowServerConnect()
|
||||||
*
|
*
|
||||||
* When we've issue the PORT command, we have told the server to connect
|
* When we've issue the PORT command, we have told the server to connect to
|
||||||
* to us. This function
|
* us. This function checks whether data connection is established if so it is
|
||||||
* - will sit and wait here until the server has connected for easy interface
|
* accepted.
|
||||||
* - will check whether data connection is established if so it is accepted
|
|
||||||
* for multi interface
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
|
static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
long timeout_ms;
|
long timeout_ms;
|
||||||
long interval_ms;
|
|
||||||
CURLcode ret = CURLE_OK;
|
CURLcode ret = CURLE_OK;
|
||||||
|
|
||||||
*connected = FALSE;
|
*connected = FALSE;
|
||||||
@ -548,50 +556,34 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
|
|||||||
/* Save the time we start accepting server connect */
|
/* Save the time we start accepting server connect */
|
||||||
Curl_pgrsTime(data, TIMER_STARTACCEPT);
|
Curl_pgrsTime(data, TIMER_STARTACCEPT);
|
||||||
|
|
||||||
for(;;) {
|
timeout_ms = ftp_timeleft_accept(data);
|
||||||
timeout_ms = ftp_timeleft_accept(data);
|
if(timeout_ms < 0) {
|
||||||
if(timeout_ms < 0) {
|
/* if a timeout was already reached, bail out */
|
||||||
/* if a timeout was already reached, bail out */
|
failf(data, "Accept timeout occurred while waiting server connect");
|
||||||
failf(data, "Accept timeout occurred while waiting server connect");
|
return CURLE_FTP_ACCEPT_TIMEOUT;
|
||||||
return CURLE_FTP_ACCEPT_TIMEOUT;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* see if the connection request is already here */
|
/* see if the connection request is already here */
|
||||||
ret = ReceivedServerConnect(conn, connected);
|
ret = ReceivedServerConnect(conn, connected);
|
||||||
|
if(ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if(*connected) {
|
||||||
|
ret = AcceptServerConnect(conn);
|
||||||
if(ret)
|
if(ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if(*connected) {
|
ret = InitiateTransfer(conn);
|
||||||
ret = AcceptServerConnect(conn);
|
if(ret)
|
||||||
if(ret)
|
return ret;
|
||||||
return ret;
|
}
|
||||||
|
else {
|
||||||
ret = InitiateTransfer(conn);
|
/* Add timeout to multi handle and break out of the loop */
|
||||||
if(ret)
|
if(ret == CURLE_OK && *connected == FALSE) {
|
||||||
return ret;
|
if(data->set.accepttimeout > 0)
|
||||||
|
Curl_expire(data, data->set.accepttimeout);
|
||||||
break; /* connection is accepted, break the loop */
|
else
|
||||||
}
|
Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
|
||||||
else {
|
|
||||||
if(data->state.used_interface == Curl_if_easy) {
|
|
||||||
interval_ms = 1000;
|
|
||||||
if(timeout_ms < interval_ms)
|
|
||||||
interval_ms = timeout_ms;
|
|
||||||
|
|
||||||
/* sleep for 1 second and then continue */
|
|
||||||
Curl_socket_ready(CURL_SOCKET_BAD, CURL_SOCKET_BAD, interval_ms);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Add timeout to multi handle and break out of the loop */
|
|
||||||
if(ret == CURLE_OK && *connected == FALSE) {
|
|
||||||
if(data->set.accepttimeout > 0)
|
|
||||||
Curl_expire(data, data->set.accepttimeout);
|
|
||||||
else
|
|
||||||
Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
break; /* connection was not accepted immediately */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,8 +779,12 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* This is the ONLY way to change FTP state! */
|
/* This is the ONLY way to change FTP state! */
|
||||||
static void state(struct connectdata *conn,
|
static void _state(struct connectdata *conn,
|
||||||
ftpstate newstate)
|
ftpstate newstate
|
||||||
|
#ifdef DEBUGBUILD
|
||||||
|
, int lineno
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||||
/* for debug purposes */
|
/* for debug purposes */
|
||||||
@ -833,8 +829,8 @@ static void state(struct connectdata *conn,
|
|||||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||||
if(ftpc->state != newstate)
|
if(ftpc->state != newstate)
|
||||||
infof(conn->data, "FTP %p state change from %s to %s\n",
|
infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
|
||||||
ftpc, names[ftpc->state], names[newstate]);
|
ftpc, lineno, names[ftpc->state], names[newstate]);
|
||||||
#endif
|
#endif
|
||||||
ftpc->state = newstate;
|
ftpc->state = newstate;
|
||||||
}
|
}
|
||||||
@ -2071,10 +2067,19 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
|||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
|
||||||
|
/* the CONNECT procedure is not complete, the tunnel is not yet up */
|
||||||
|
state(conn, FTP_STOP); /* this phase is completed */
|
||||||
|
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
|
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
|
||||||
|
|
||||||
|
conn->bits.do_more = TRUE;
|
||||||
state(conn, FTP_STOP); /* this phase is completed */
|
state(conn, FTP_STOP); /* this phase is completed */
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -2108,6 +2113,7 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn,
|
|||||||
else {
|
else {
|
||||||
infof(data, "Connect data stream actively\n");
|
infof(data, "Connect data stream actively\n");
|
||||||
state(conn, FTP_STOP); /* end of DO phase */
|
state(conn, FTP_STOP); /* end of DO phase */
|
||||||
|
result = ftp_dophase_done(conn, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -3206,7 +3212,6 @@ static CURLcode ftp_connect(struct connectdata *conn,
|
|||||||
{
|
{
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||||
struct SessionHandle *data=conn->data;
|
|
||||||
struct pingpong *pp = &ftpc->pp;
|
struct pingpong *pp = &ftpc->pp;
|
||||||
|
|
||||||
*done = FALSE; /* default to not done yet */
|
*done = FALSE; /* default to not done yet */
|
||||||
@ -3240,13 +3245,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
|
|||||||
response */
|
response */
|
||||||
state(conn, FTP_WAIT220);
|
state(conn, FTP_WAIT220);
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_multi)
|
result = ftp_multi_statemach(conn, done);
|
||||||
result = ftp_multi_statemach(conn, done);
|
|
||||||
else {
|
|
||||||
result = ftp_easy_statemach(conn);
|
|
||||||
if(!result)
|
|
||||||
*done = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -3681,6 +3680,14 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
|||||||
|
|
||||||
/* if the second connection isn't done yet, wait for it */
|
/* if the second connection isn't done yet, wait for it */
|
||||||
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
|
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
|
||||||
|
if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
|
||||||
|
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
|
||||||
|
aren't used so we blank their arguments. TODO: make this nicer */
|
||||||
|
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
|
result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
|
||||||
|
|
||||||
/* Ready to do more? */
|
/* Ready to do more? */
|
||||||
@ -3691,9 +3698,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((data->state.used_interface == Curl_if_multi) &&
|
if(ftpc->state) {
|
||||||
ftpc->state) {
|
/* already in a state so skip the intial commands.
|
||||||
/* multi interface and already in a state so skip the intial commands.
|
|
||||||
They are only done to kickstart the do_more state */
|
They are only done to kickstart the do_more state */
|
||||||
result = ftp_multi_statemach(conn, complete);
|
result = ftp_multi_statemach(conn, complete);
|
||||||
|
|
||||||
@ -3701,6 +3707,12 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
|||||||
immediately */
|
immediately */
|
||||||
if(result || (ftpc->wait_data_conn != TRUE))
|
if(result || (ftpc->wait_data_conn != TRUE))
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
if(ftpc->wait_data_conn)
|
||||||
|
/* if we reach the end of the FTP state machine here, *complete will be
|
||||||
|
TRUE but so is ftpc->wait_data_conn, which says we need to wait for
|
||||||
|
the data connection and therefore we're not actually complete */
|
||||||
|
*complete = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ftp->transfer <= FTPTRANSFER_INFO) {
|
if(ftp->transfer <= FTPTRANSFER_INFO) {
|
||||||
@ -3729,6 +3741,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
|||||||
result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
|
result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
result = ftp_multi_statemach(conn, complete);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* download */
|
/* download */
|
||||||
@ -3755,14 +3769,10 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
|||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(data->state.used_interface == Curl_if_multi) {
|
|
||||||
result = ftp_multi_statemach(conn, complete);
|
|
||||||
|
|
||||||
return result;
|
result = ftp_multi_statemach(conn, complete);
|
||||||
}
|
}
|
||||||
else
|
return result;
|
||||||
result = ftp_easy_statemach(conn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((result == CURLE_OK) && (ftp->transfer != FTPTRANSFER_BODY))
|
if((result == CURLE_OK) && (ftp->transfer != FTPTRANSFER_BODY))
|
||||||
@ -3805,7 +3815,6 @@ CURLcode ftp_perform(struct connectdata *conn,
|
|||||||
ftp->transfer = FTPTRANSFER_INFO;
|
ftp->transfer = FTPTRANSFER_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
*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 */
|
||||||
@ -3814,16 +3823,12 @@ CURLcode ftp_perform(struct connectdata *conn,
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* run the state-machine */
|
/* run the state-machine */
|
||||||
if(conn->data->state.used_interface == Curl_if_multi)
|
result = ftp_multi_statemach(conn, dophase_done);
|
||||||
result = ftp_multi_statemach(conn, dophase_done);
|
|
||||||
else {
|
|
||||||
result = ftp_easy_statemach(conn);
|
|
||||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
|
||||||
}
|
|
||||||
*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(conn->data, "DO phase is complete1\n"));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -4476,7 +4481,7 @@ static CURLcode ftp_doing(struct connectdata *conn,
|
|||||||
else if(*dophase_done) {
|
else if(*dophase_done) {
|
||||||
result = ftp_dophase_done(conn, FALSE /* not connected */);
|
result = ftp_dophase_done(conn, FALSE /* not connected */);
|
||||||
|
|
||||||
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
DEBUGF(infof(conn->data, "DO phase is complete2\n"));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -4521,6 +4526,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
result = ftp_dophase_done(conn, connected);
|
result = ftp_dophase_done(conn, connected);
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
34
lib/http.c
34
lib/http.c
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -1295,22 +1295,16 @@ Curl_compareheader(const char *headerline, /* line to check */
|
|||||||
*/
|
*/
|
||||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data;
|
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
|
||||||
data=conn->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. */
|
||||||
conn->bits.close = FALSE;
|
conn->bits.close = FALSE;
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_multi) {
|
/* the CONNECT procedure might not have been completed */
|
||||||
/* when the multi interface is used, the CONNECT procedure might not have
|
result = Curl_proxy_connect(conn);
|
||||||
been completed */
|
if(result)
|
||||||
result = Curl_proxy_connect(conn);
|
return result;
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
|
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
|
||||||
/* 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. */
|
||||||
@ -1318,22 +1312,12 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
|||||||
|
|
||||||
if(conn->given->flags & PROTOPT_SSL) {
|
if(conn->given->flags & PROTOPT_SSL) {
|
||||||
/* perform SSL initialization */
|
/* perform SSL initialization */
|
||||||
if(data->state.used_interface == Curl_if_multi) {
|
result = https_connecting(conn, done);
|
||||||
result = https_connecting(conn, done);
|
if(result)
|
||||||
if(result)
|
return result;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* BLOCKING */
|
|
||||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
*done = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
*done = TRUE;
|
*done = TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -87,13 +87,6 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
|
|||||||
* Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
|
* Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
|
||||||
* function will issue the necessary commands to get a seamless tunnel through
|
* function will issue the necessary commands to get a seamless tunnel through
|
||||||
* this proxy. After that, the socket can be used just as a normal socket.
|
* this proxy. After that, the socket can be used just as a normal socket.
|
||||||
*
|
|
||||||
* This badly needs to be rewritten. CONNECT should be sent and dealt with
|
|
||||||
* like any ordinary HTTP request, and not specially crafted like this. This
|
|
||||||
* function only remains here like this for now since the rewrite is a bit too
|
|
||||||
* much work to do at the moment.
|
|
||||||
*
|
|
||||||
* This function is BLOCKING which is nasty for all multi interface using apps.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||||
@ -244,19 +237,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
return CURLE_RECV_ERROR;
|
return CURLE_RECV_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we're in multi-mode and we would block, return instead for a retry */
|
if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
|
||||||
if(Curl_if_multi == data->state.used_interface) {
|
/* return so we'll be called again polling-style */
|
||||||
if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
|
return CURLE_OK;
|
||||||
/* return so we'll be called again polling-style */
|
|
||||||
return CURLE_OK;
|
|
||||||
else {
|
|
||||||
DEBUGF(infof(data,
|
|
||||||
"Multi mode finished polling for response from "
|
|
||||||
"proxy CONNECT\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
DEBUGF(infof(data, "Easy mode waiting response from proxy CONNECT\n"));
|
DEBUGF(infof(data,
|
||||||
|
"Multi mode finished polling for response from "
|
||||||
|
"proxy CONNECT\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* at this point, either:
|
/* at this point, either:
|
||||||
@ -572,6 +559,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
if(closeConnection && data->req.newurl)
|
if(closeConnection && data->req.newurl)
|
||||||
conn->bits.proxy_connect_closed = TRUE;
|
conn->bits.proxy_connect_closed = TRUE;
|
||||||
|
|
||||||
|
if(data->req.newurl) {
|
||||||
|
/* this won't be used anymore for the CONNECT so free it now */
|
||||||
|
free(data->req.newurl);
|
||||||
|
data->req.newurl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* to back to init state */
|
/* to back to init state */
|
||||||
conn->tunnel_state[sockindex] = TUNNEL_INIT;
|
conn->tunnel_state[sockindex] = TUNNEL_INIT;
|
||||||
|
|
||||||
|
45
lib/imap.c
45
lib/imap.c
@ -633,19 +633,9 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn,
|
|||||||
result = imap_state_capability(conn);
|
result = imap_state_capability(conn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(data->state.used_interface == Curl_if_multi) {
|
state(conn, IMAP_UPGRADETLS);
|
||||||
state(conn, IMAP_UPGRADETLS);
|
return imap_state_upgrade_tls(conn);
|
||||||
result = imap_state_upgrade_tls(conn);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
|
||||||
if(CURLE_OK == result) {
|
|
||||||
imap_to_imaps(conn);
|
|
||||||
result = imap_state_capability(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1358,7 +1348,6 @@ static CURLcode imap_connect(struct connectdata *conn,
|
|||||||
{
|
{
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
struct imap_conn *imapc = &conn->proto.imapc;
|
struct imap_conn *imapc = &conn->proto.imapc;
|
||||||
struct SessionHandle *data=conn->data;
|
|
||||||
struct pingpong *pp = &imapc->pp;
|
struct pingpong *pp = &imapc->pp;
|
||||||
|
|
||||||
*done = FALSE; /* default to not done yet */
|
*done = FALSE; /* default to not done yet */
|
||||||
@ -1379,17 +1368,7 @@ static CURLcode imap_connect(struct connectdata *conn,
|
|||||||
pp->endofresp = imap_endofresp;
|
pp->endofresp = imap_endofresp;
|
||||||
pp->conn = conn;
|
pp->conn = conn;
|
||||||
|
|
||||||
if((conn->handler->flags & PROTOPT_SSL) &&
|
Curl_pp_init(pp); /* init generic pingpong data */
|
||||||
data->state.used_interface != Curl_if_multi) {
|
|
||||||
/* IMAPS is simply imap with SSL for the control channel */
|
|
||||||
/* so perform the SSL initialization for this socket */
|
|
||||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise the response reader stuff */
|
|
||||||
Curl_pp_init(pp);
|
|
||||||
|
|
||||||
/* Start off waiting for the server greeting response */
|
/* Start off waiting for the server greeting response */
|
||||||
state(conn, IMAP_SERVERGREET);
|
state(conn, IMAP_SERVERGREET);
|
||||||
@ -1397,13 +1376,7 @@ static CURLcode imap_connect(struct connectdata *conn,
|
|||||||
/* Start off with an id of '*' */
|
/* Start off with an id of '*' */
|
||||||
imapc->idstr = "*";
|
imapc->idstr = "*";
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_multi)
|
result = imap_multi_statemach(conn, done);
|
||||||
result = imap_multi_statemach(conn, done);
|
|
||||||
else {
|
|
||||||
result = imap_easy_statemach(conn);
|
|
||||||
if(!result)
|
|
||||||
*done = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1473,13 +1446,9 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
|
|||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* Run the state-machine */
|
/* run the state-machine */
|
||||||
if(conn->data->state.used_interface == Curl_if_multi)
|
result = imap_multi_statemach(conn, dophase_done);
|
||||||
result = imap_multi_statemach(conn, dophase_done);
|
|
||||||
else {
|
|
||||||
result = imap_easy_statemach(conn);
|
|
||||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
|
||||||
}
|
|
||||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||||
|
|
||||||
if(*dophase_done)
|
if(*dophase_done)
|
||||||
|
183
lib/multi.c
183
lib/multi.c
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -39,6 +39,7 @@
|
|||||||
#include "speedcheck.h"
|
#include "speedcheck.h"
|
||||||
#include "conncache.h"
|
#include "conncache.h"
|
||||||
#include "bundles.h"
|
#include "bundles.h"
|
||||||
|
#include "multihandle.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@ -56,62 +57,6 @@
|
|||||||
#define CURL_SOCKET_HASH_TABLE_SIZE 911
|
#define CURL_SOCKET_HASH_TABLE_SIZE 911
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Curl_message {
|
|
||||||
/* the 'CURLMsg' is the part that is visible to the external user */
|
|
||||||
struct CURLMsg extmsg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* NOTE: if you add a state here, add the name to the statename[] array as
|
|
||||||
well!
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
CURLM_STATE_INIT, /* 0 - start in this state */
|
|
||||||
CURLM_STATE_CONNECT, /* 1 - resolve/connect has been sent off */
|
|
||||||
CURLM_STATE_WAITRESOLVE, /* 2 - awaiting the resolve to finalize */
|
|
||||||
CURLM_STATE_WAITCONNECT, /* 3 - awaiting the connect to finalize */
|
|
||||||
CURLM_STATE_WAITPROXYCONNECT, /* 4 - awaiting proxy CONNECT to finalize */
|
|
||||||
CURLM_STATE_PROTOCONNECT, /* 5 - completing the protocol-specific connect
|
|
||||||
phase */
|
|
||||||
CURLM_STATE_WAITDO, /* 6 - wait for our turn to send the request */
|
|
||||||
CURLM_STATE_DO, /* 7 - start send off the request (part 1) */
|
|
||||||
CURLM_STATE_DOING, /* 8 - sending off the request (part 1) */
|
|
||||||
CURLM_STATE_DO_MORE, /* 9 - send off the request (part 2) */
|
|
||||||
CURLM_STATE_DO_DONE, /* 10 - done sending off request */
|
|
||||||
CURLM_STATE_WAITPERFORM, /* 11 - wait for our turn to read the response */
|
|
||||||
CURLM_STATE_PERFORM, /* 12 - transfer data */
|
|
||||||
CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */
|
|
||||||
CURLM_STATE_DONE, /* 14 - post data transfer operation */
|
|
||||||
CURLM_STATE_COMPLETED, /* 15 - operation complete */
|
|
||||||
CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */
|
|
||||||
CURLM_STATE_LAST /* 17 - not a true state, never use this */
|
|
||||||
} CURLMstate;
|
|
||||||
|
|
||||||
/* we support N sockets per easy handle. Set the corresponding bit to what
|
|
||||||
action we should wait for */
|
|
||||||
#define MAX_SOCKSPEREASYHANDLE 5
|
|
||||||
#define GETSOCK_READABLE (0x00ff)
|
|
||||||
#define GETSOCK_WRITABLE (0xff00)
|
|
||||||
|
|
||||||
struct Curl_one_easy {
|
|
||||||
/* first, two fields for the linked list of these */
|
|
||||||
struct Curl_one_easy *next;
|
|
||||||
struct Curl_one_easy *prev;
|
|
||||||
|
|
||||||
struct SessionHandle *easy_handle; /* the easy handle for this unit */
|
|
||||||
struct connectdata *easy_conn; /* the "unit's" connection */
|
|
||||||
|
|
||||||
CURLMstate state; /* the handle's state */
|
|
||||||
CURLcode result; /* previous result */
|
|
||||||
|
|
||||||
struct Curl_message msg; /* A single posted message. */
|
|
||||||
|
|
||||||
/* Array with the plain socket numbers this handle takes care of, in no
|
|
||||||
particular order. Note that all sockets are added to the sockhash, where
|
|
||||||
the state etc are also kept. This array is mostly used to detect when a
|
|
||||||
socket is to be removed from the hash. See singlesocket(). */
|
|
||||||
curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
|
|
||||||
int numsocks;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CURL_MULTI_HANDLE 0x000bab1e
|
#define CURL_MULTI_HANDLE 0x000bab1e
|
||||||
|
|
||||||
@ -120,57 +65,6 @@ struct Curl_one_easy {
|
|||||||
#define GOOD_EASY_HANDLE(x) \
|
#define GOOD_EASY_HANDLE(x) \
|
||||||
((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
|
((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
|
||||||
|
|
||||||
/* This is the struct known as CURLM on the outside */
|
|
||||||
struct Curl_multi {
|
|
||||||
/* First a simple identifier to easier detect if a user mix up
|
|
||||||
this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
|
|
||||||
long type;
|
|
||||||
|
|
||||||
/* We have a doubly-linked circular list with easy handles */
|
|
||||||
struct Curl_one_easy easy;
|
|
||||||
|
|
||||||
int num_easy; /* amount of entries in the linked list above. */
|
|
||||||
int num_alive; /* amount of easy handles that are added but have not yet
|
|
||||||
reached COMPLETE state */
|
|
||||||
|
|
||||||
struct curl_llist *msglist; /* a list of messages from completed transfers */
|
|
||||||
|
|
||||||
/* callback function and user data pointer for the *socket() API */
|
|
||||||
curl_socket_callback socket_cb;
|
|
||||||
void *socket_userp;
|
|
||||||
|
|
||||||
/* Hostname cache */
|
|
||||||
struct curl_hash *hostcache;
|
|
||||||
|
|
||||||
/* timetree points to the splay-tree of time nodes to figure out expire
|
|
||||||
times of all currently set timers */
|
|
||||||
struct Curl_tree *timetree;
|
|
||||||
|
|
||||||
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
|
|
||||||
the pluralis form, there can be more than one easy handle waiting on the
|
|
||||||
same actual socket) */
|
|
||||||
struct curl_hash *sockhash;
|
|
||||||
|
|
||||||
/* Whether pipelining is enabled for this multi handle */
|
|
||||||
bool pipelining_enabled;
|
|
||||||
|
|
||||||
/* Shared connection cache (bundles)*/
|
|
||||||
struct conncache *conn_cache;
|
|
||||||
|
|
||||||
/* This handle will be used for closing the cached connections in
|
|
||||||
curl_multi_cleanup() */
|
|
||||||
struct SessionHandle *closure_handle;
|
|
||||||
|
|
||||||
long maxconnects; /* if >0, a fixed limit of the maximum number of entries
|
|
||||||
we're allowed to grow the connection cache to */
|
|
||||||
|
|
||||||
/* timer callback and user data pointer for the *socket() API */
|
|
||||||
curl_multi_timer_callback timer_cb;
|
|
||||||
void *timer_userp;
|
|
||||||
struct timeval timer_lastcall; /* the fixed time for the timeout for the
|
|
||||||
previous callback */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void singlesocket(struct Curl_multi *multi,
|
static void singlesocket(struct Curl_multi *multi,
|
||||||
struct Curl_one_easy *easy);
|
struct Curl_one_easy *easy);
|
||||||
static int update_timer(struct Curl_multi *multi);
|
static int update_timer(struct Curl_multi *multi);
|
||||||
@ -213,7 +107,11 @@ static const char * const statename[]={
|
|||||||
static void multi_freetimeout(void *a, void *b);
|
static void multi_freetimeout(void *a, void *b);
|
||||||
|
|
||||||
/* always use this function to change state, to make debugging easier */
|
/* always use this function to change state, to make debugging easier */
|
||||||
static void multistate(struct Curl_one_easy *easy, CURLMstate state)
|
static void mstate(struct Curl_one_easy *easy, CURLMstate state
|
||||||
|
#ifdef DEBUGBUILD
|
||||||
|
, int lineno
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
long connection_id = -5000;
|
long connection_id = -5000;
|
||||||
@ -233,9 +131,9 @@ static void multistate(struct Curl_one_easy *easy, CURLMstate state)
|
|||||||
connection_id = easy->easy_conn->connection_id;
|
connection_id = easy->easy_conn->connection_id;
|
||||||
|
|
||||||
infof(easy->easy_handle,
|
infof(easy->easy_handle,
|
||||||
"STATE: %s => %s handle %p; (connection #%ld) \n",
|
"STATE: %s => %s handle %p; line %d (connection #%ld) \n",
|
||||||
statename[oldstate], statename[easy->state],
|
statename[oldstate], statename[easy->state],
|
||||||
(char *)easy, connection_id);
|
(char *)easy, lineno, connection_id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(state == CURLM_STATE_COMPLETED)
|
if(state == CURLM_STATE_COMPLETED)
|
||||||
@ -243,6 +141,12 @@ static void multistate(struct Curl_one_easy *easy, CURLMstate state)
|
|||||||
easy->easy_handle->multi->num_alive--;
|
easy->easy_handle->multi->num_alive--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DEBUGBUILD
|
||||||
|
#define multistate(x,y) mstate(x,y)
|
||||||
|
#else
|
||||||
|
#define multistate(x,y) mstate(x,y, __LINE__)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We add one of these structs to the sockhash for a particular socket
|
* We add one of these structs to the sockhash for a particular socket
|
||||||
*/
|
*/
|
||||||
@ -396,7 +300,7 @@ CURLM *curl_multi_init(void)
|
|||||||
if(!multi->sockhash)
|
if(!multi->sockhash)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
multi->conn_cache = Curl_conncache_init(CONNCACHE_MULTI);
|
multi->conn_cache = Curl_conncache_init();
|
||||||
if(!multi->conn_cache)
|
if(!multi->conn_cache)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -516,29 +420,14 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
|||||||
easy->easy_handle->multi_pos = easy;
|
easy->easy_handle->multi_pos = easy;
|
||||||
|
|
||||||
/* for multi interface connections, we share DNS cache automatically if the
|
/* for multi interface connections, we share DNS cache automatically if the
|
||||||
easy handle's one is currently private. */
|
easy handle's one is currently not set. */
|
||||||
if(easy->easy_handle->dns.hostcache &&
|
|
||||||
(easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) {
|
|
||||||
Curl_hash_destroy(easy->easy_handle->dns.hostcache);
|
|
||||||
easy->easy_handle->dns.hostcache = NULL;
|
|
||||||
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!easy->easy_handle->dns.hostcache ||
|
if(!easy->easy_handle->dns.hostcache ||
|
||||||
(easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
|
(easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
|
||||||
easy->easy_handle->dns.hostcache = multi->hostcache;
|
easy->easy_handle->dns.hostcache = multi->hostcache;
|
||||||
easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
|
easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On a multi stack the connection cache, owned by the multi handle,
|
/* Point to the multi's connection cache */
|
||||||
is shared between all easy handles within the multi handle.
|
|
||||||
Therefore we free the private connection cache if there is one */
|
|
||||||
if(easy->easy_handle->state.conn_cache &&
|
|
||||||
easy->easy_handle->state.conn_cache->type == CONNCACHE_PRIVATE) {
|
|
||||||
Curl_conncache_destroy(easy->easy_handle->state.conn_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Point now to this multi's connection cache */
|
|
||||||
easy->easy_handle->state.conn_cache = multi->conn_cache;
|
easy->easy_handle->state.conn_cache = multi->conn_cache;
|
||||||
|
|
||||||
/* This adds the new entry at the 'end' of the doubly-linked circular
|
/* This adds the new entry at the 'end' of the doubly-linked circular
|
||||||
@ -666,18 +555,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
|
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
|
||||||
if(multi->num_easy == 1) {
|
/* stop using the multi handle's DNS cache */
|
||||||
if(easy_owns_conn) {
|
|
||||||
Curl_resolver_cancel(easy->easy_conn);
|
|
||||||
if(easy->easy_conn->dns_entry) {
|
|
||||||
Curl_resolv_unlock(easy->easy_handle, easy->easy_conn->dns_entry);
|
|
||||||
easy->easy_conn->dns_entry = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Curl_hostcache_destroy(easy->easy_handle);
|
|
||||||
multi->hostcache = NULL;
|
|
||||||
}
|
|
||||||
/* clear out the usage of the shared DNS cache */
|
|
||||||
easy->easy_handle->dns.hostcache = NULL;
|
easy->easy_handle->dns.hostcache = NULL;
|
||||||
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
|
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
|
||||||
}
|
}
|
||||||
@ -700,12 +578,9 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
|||||||
Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
|
Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(easy->easy_handle->state.conn_cache->type == CONNCACHE_MULTI) {
|
/* as this was using a shared connection cache we clear the pointer
|
||||||
/* if this was using the shared connection cache we clear the pointer
|
to that since we're not part of that multi handle anymore */
|
||||||
to that since we're not part of that handle anymore */
|
easy->easy_handle->state.conn_cache = NULL;
|
||||||
easy->easy_handle->state.conn_cache = NULL;
|
|
||||||
easy->easy_handle->state.lastconnect = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* change state without using multistate(), only to make singlesocket() do
|
/* change state without using multistate(), only to make singlesocket() do
|
||||||
what we want */
|
what we want */
|
||||||
@ -1025,7 +900,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
bool connected;
|
bool connected;
|
||||||
bool async;
|
bool async;
|
||||||
bool protocol_connect = FALSE;
|
bool protocol_connect = FALSE;
|
||||||
bool dophase_done;
|
bool dophase_done = FALSE;
|
||||||
bool done = FALSE;
|
bool done = FALSE;
|
||||||
CURLMcode result = CURLM_OK;
|
CURLMcode result = CURLM_OK;
|
||||||
struct SingleRequest *k;
|
struct SingleRequest *k;
|
||||||
@ -1120,8 +995,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
/* after init, go CONNECT */
|
/* after init, go CONNECT */
|
||||||
multistate(easy, CURLM_STATE_CONNECT);
|
multistate(easy, CURLM_STATE_CONNECT);
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
|
||||||
data->state.used_interface = Curl_if_multi;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1577,9 +1450,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
if(!ret)
|
if(!ret)
|
||||||
retry = (newurl)?TRUE:FALSE;
|
retry = (newurl)?TRUE:FALSE;
|
||||||
|
|
||||||
if(retry)
|
if(retry) {
|
||||||
/* if we are to retry, set the result to OK */
|
/* if we are to retry, set the result to OK and consider the
|
||||||
|
request as done */
|
||||||
easy->result = CURLE_OK;
|
easy->result = CURLE_OK;
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(easy->result) {
|
if(easy->result) {
|
||||||
@ -1897,6 +1773,9 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
|||||||
/* Close all the connections in the connection cache */
|
/* Close all the connections in the connection cache */
|
||||||
close_all_connections(multi);
|
close_all_connections(multi);
|
||||||
|
|
||||||
|
multi->closure_handle->dns.hostcache = multi->hostcache;
|
||||||
|
Curl_hostcache_clean(multi->closure_handle);
|
||||||
|
|
||||||
Curl_close(multi->closure_handle);
|
Curl_close(multi->closure_handle);
|
||||||
multi->closure_handle = NULL;
|
multi->closure_handle = NULL;
|
||||||
|
|
||||||
|
134
lib/multihandle.h
Normal file
134
lib/multihandle.h
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#ifndef HEADER_CURL_MULTIHANDLE_H
|
||||||
|
#define HEADER_CURL_MULTIHANDLE_H
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2013, 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 http://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.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
struct Curl_message {
|
||||||
|
/* the 'CURLMsg' is the part that is visible to the external user */
|
||||||
|
struct CURLMsg extmsg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NOTE: if you add a state here, add the name to the statename[] array as
|
||||||
|
well!
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
CURLM_STATE_INIT, /* 0 - start in this state */
|
||||||
|
CURLM_STATE_CONNECT, /* 1 - resolve/connect has been sent off */
|
||||||
|
CURLM_STATE_WAITRESOLVE, /* 2 - awaiting the resolve to finalize */
|
||||||
|
CURLM_STATE_WAITCONNECT, /* 3 - awaiting the connect to finalize */
|
||||||
|
CURLM_STATE_WAITPROXYCONNECT, /* 4 - awaiting proxy CONNECT to finalize */
|
||||||
|
CURLM_STATE_PROTOCONNECT, /* 5 - completing the protocol-specific connect
|
||||||
|
phase */
|
||||||
|
CURLM_STATE_WAITDO, /* 6 - wait for our turn to send the request */
|
||||||
|
CURLM_STATE_DO, /* 7 - start send off the request (part 1) */
|
||||||
|
CURLM_STATE_DOING, /* 8 - sending off the request (part 1) */
|
||||||
|
CURLM_STATE_DO_MORE, /* 9 - send off the request (part 2) */
|
||||||
|
CURLM_STATE_DO_DONE, /* 10 - done sending off request */
|
||||||
|
CURLM_STATE_WAITPERFORM, /* 11 - wait for our turn to read the response */
|
||||||
|
CURLM_STATE_PERFORM, /* 12 - transfer data */
|
||||||
|
CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */
|
||||||
|
CURLM_STATE_DONE, /* 14 - post data transfer operation */
|
||||||
|
CURLM_STATE_COMPLETED, /* 15 - operation complete */
|
||||||
|
CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */
|
||||||
|
CURLM_STATE_LAST /* 17 - not a true state, never use this */
|
||||||
|
} CURLMstate;
|
||||||
|
|
||||||
|
/* we support N sockets per easy handle. Set the corresponding bit to what
|
||||||
|
action we should wait for */
|
||||||
|
#define MAX_SOCKSPEREASYHANDLE 5
|
||||||
|
#define GETSOCK_READABLE (0x00ff)
|
||||||
|
#define GETSOCK_WRITABLE (0xff00)
|
||||||
|
|
||||||
|
struct Curl_one_easy {
|
||||||
|
/* first, two fields for the linked list of these */
|
||||||
|
struct Curl_one_easy *next;
|
||||||
|
struct Curl_one_easy *prev;
|
||||||
|
|
||||||
|
struct SessionHandle *easy_handle; /* the easy handle for this unit */
|
||||||
|
struct connectdata *easy_conn; /* the "unit's" connection */
|
||||||
|
|
||||||
|
CURLMstate state; /* the handle's state */
|
||||||
|
CURLcode result; /* previous result */
|
||||||
|
|
||||||
|
struct Curl_message msg; /* A single posted message. */
|
||||||
|
|
||||||
|
/* Array with the plain socket numbers this handle takes care of, in no
|
||||||
|
particular order. Note that all sockets are added to the sockhash, where
|
||||||
|
the state etc are also kept. This array is mostly used to detect when a
|
||||||
|
socket is to be removed from the hash. See singlesocket(). */
|
||||||
|
curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
|
||||||
|
int numsocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This is the struct known as CURLM on the outside */
|
||||||
|
struct Curl_multi {
|
||||||
|
/* First a simple identifier to easier detect if a user mix up
|
||||||
|
this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
|
||||||
|
long type;
|
||||||
|
|
||||||
|
/* We have a doubly-linked circular list with easy handles */
|
||||||
|
struct Curl_one_easy easy;
|
||||||
|
|
||||||
|
int num_easy; /* amount of entries in the linked list above. */
|
||||||
|
int num_alive; /* amount of easy handles that are added but have not yet
|
||||||
|
reached COMPLETE state */
|
||||||
|
|
||||||
|
struct curl_llist *msglist; /* a list of messages from completed transfers */
|
||||||
|
|
||||||
|
/* callback function and user data pointer for the *socket() API */
|
||||||
|
curl_socket_callback socket_cb;
|
||||||
|
void *socket_userp;
|
||||||
|
|
||||||
|
/* Hostname cache */
|
||||||
|
struct curl_hash *hostcache;
|
||||||
|
|
||||||
|
/* timetree points to the splay-tree of time nodes to figure out expire
|
||||||
|
times of all currently set timers */
|
||||||
|
struct Curl_tree *timetree;
|
||||||
|
|
||||||
|
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
|
||||||
|
the pluralis form, there can be more than one easy handle waiting on the
|
||||||
|
same actual socket) */
|
||||||
|
struct curl_hash *sockhash;
|
||||||
|
|
||||||
|
/* Whether pipelining is enabled for this multi handle */
|
||||||
|
bool pipelining_enabled;
|
||||||
|
|
||||||
|
/* Shared connection cache (bundles)*/
|
||||||
|
struct conncache *conn_cache;
|
||||||
|
|
||||||
|
/* This handle will be used for closing the cached connections in
|
||||||
|
curl_multi_cleanup() */
|
||||||
|
struct SessionHandle *closure_handle;
|
||||||
|
|
||||||
|
long maxconnects; /* if >0, a fixed limit of the maximum number of entries
|
||||||
|
we're allowed to grow the connection cache to */
|
||||||
|
|
||||||
|
/* timer callback and user data pointer for the *socket() API */
|
||||||
|
curl_multi_timer_callback timer_cb;
|
||||||
|
void *timer_userp;
|
||||||
|
struct timeval timer_lastcall; /* the fixed time for the timeout for the
|
||||||
|
previous callback */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* HEADER_CURL_MULTIHANDLE_H */
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
|
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
|
||||||
* Copyright (C) 2011 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2011 - 2013, 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
|
||||||
@ -192,6 +192,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
|
|||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
int rc, proto = LDAP_VERSION3;
|
int rc, proto = LDAP_VERSION3;
|
||||||
char hosturl[1024], *ptr;
|
char hosturl[1024], *ptr;
|
||||||
|
(void)done;
|
||||||
|
|
||||||
strcpy(hosturl, "ldap");
|
strcpy(hosturl, "ldap");
|
||||||
ptr = hosturl+4;
|
ptr = hosturl+4;
|
||||||
@ -212,23 +213,12 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
|
|||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
if(conn->handler->flags & PROTOPT_SSL) {
|
if(conn->handler->flags & PROTOPT_SSL) {
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
if(data->state.used_interface == Curl_if_easy) {
|
res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
|
||||||
res = Curl_ssl_connect(conn, FIRSTSOCKET);
|
if(res)
|
||||||
if(res)
|
return res;
|
||||||
return res;
|
|
||||||
li->ssldone = TRUE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
|
|
||||||
if(res)
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_easy)
|
|
||||||
return ldap_connecting(conn, done);
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,10 +252,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_easy)
|
tvp = &tv;
|
||||||
tvp = NULL; /* let ldap_result block indefinitely */
|
|
||||||
else
|
|
||||||
tvp = &tv;
|
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if(!li->didbind) {
|
if(!li->didbind) {
|
||||||
|
30
lib/pop3.c
30
lib/pop3.c
@ -570,17 +570,8 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
|
|||||||
result = pop3_state_capa(conn);
|
result = pop3_state_capa(conn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(data->state.used_interface == Curl_if_multi) {
|
state(conn, POP3_UPGRADETLS);
|
||||||
state(conn, POP3_UPGRADETLS);
|
result = pop3_state_upgrade_tls(conn);
|
||||||
result = pop3_state_upgrade_tls(conn);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
|
||||||
if(CURLE_OK == result) {
|
|
||||||
pop3_to_pop3s(conn);
|
|
||||||
result = pop3_state_capa(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1301,7 +1292,6 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
|
|||||||
{
|
{
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
struct pingpong *pp = &pop3c->pp;
|
struct pingpong *pp = &pop3c->pp;
|
||||||
|
|
||||||
*done = FALSE; /* default to not done yet */
|
*done = FALSE; /* default to not done yet */
|
||||||
@ -1336,13 +1326,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
|
|||||||
/* Start off waiting for the server greeting response */
|
/* Start off waiting for the server greeting response */
|
||||||
state(conn, POP3_SERVERGREET);
|
state(conn, POP3_SERVERGREET);
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_multi)
|
result = pop3_multi_statemach(conn, done);
|
||||||
result = pop3_multi_statemach(conn, done);
|
|
||||||
else {
|
|
||||||
result = pop3_easy_statemach(conn);
|
|
||||||
if(!result)
|
|
||||||
*done = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1418,12 +1402,8 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* Run the state-machine */
|
/* Run the state-machine */
|
||||||
if(conn->data->state.used_interface == Curl_if_multi)
|
result = pop3_multi_statemach(conn, dophase_done);
|
||||||
result = pop3_multi_statemach(conn, dophase_done);
|
|
||||||
else {
|
|
||||||
result = pop3_easy_statemach(conn);
|
|
||||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
|
||||||
}
|
|
||||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||||
|
|
||||||
if(*dophase_done)
|
if(*dophase_done)
|
||||||
|
41
lib/smtp.c
41
lib/smtp.c
@ -493,17 +493,8 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
|
|||||||
result = smtp_authenticate(conn);
|
result = smtp_authenticate(conn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(data->state.used_interface == Curl_if_multi) {
|
state(conn, SMTP_UPGRADETLS);
|
||||||
state(conn, SMTP_UPGRADETLS);
|
return smtp_state_upgrade_tls(conn);
|
||||||
result = smtp_state_upgrade_tls(conn);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
|
||||||
if(CURLE_OK == result) {
|
|
||||||
smtp_to_smtps(conn);
|
|
||||||
result = smtp_state_ehlo(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1300,7 +1291,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
|
|||||||
{
|
{
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
struct pingpong *pp = &smtpc->pp;
|
struct pingpong *pp = &smtpc->pp;
|
||||||
const char *path = conn->data->state.path;
|
const char *path = conn->data->state.path;
|
||||||
char localhost[HOSTNAME_MAX + 1];
|
char localhost[HOSTNAME_MAX + 1];
|
||||||
@ -1323,15 +1313,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
|
|||||||
pp->endofresp = smtp_endofresp;
|
pp->endofresp = smtp_endofresp;
|
||||||
pp->conn = conn;
|
pp->conn = conn;
|
||||||
|
|
||||||
if((conn->handler->protocol & CURLPROTO_SMTPS) &&
|
|
||||||
data->state.used_interface != Curl_if_multi) {
|
|
||||||
/* SMTPS is simply smtp with SSL for the control channel */
|
|
||||||
/* so perform the SSL initialization for this socket */
|
|
||||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise the response reader stuff */
|
/* Initialise the response reader stuff */
|
||||||
Curl_pp_init(pp);
|
Curl_pp_init(pp);
|
||||||
|
|
||||||
@ -1357,13 +1338,7 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
|
|||||||
/* Start off waiting for the server greeting response */
|
/* Start off waiting for the server greeting response */
|
||||||
state(conn, SMTP_SERVERGREET);
|
state(conn, SMTP_SERVERGREET);
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_multi)
|
result = smtp_multi_statemach(conn, done);
|
||||||
result = smtp_multi_statemach(conn, done);
|
|
||||||
else {
|
|
||||||
result = smtp_easy_statemach(conn);
|
|
||||||
if(!result)
|
|
||||||
*done = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1470,13 +1445,9 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
|||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* Run the state-machine */
|
/* run the state-machine */
|
||||||
if(conn->data->state.used_interface == Curl_if_multi)
|
result = smtp_multi_statemach(conn, dophase_done);
|
||||||
result = smtp_multi_statemach(conn, dophase_done);
|
|
||||||
else {
|
|
||||||
result = smtp_easy_statemach(conn);
|
|
||||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
|
||||||
}
|
|
||||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||||
|
|
||||||
if(*dophase_done)
|
if(*dophase_done)
|
||||||
|
28
lib/ssh.c
28
lib/ssh.c
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -2793,13 +2793,7 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
|
|||||||
|
|
||||||
state(conn, SSH_INIT);
|
state(conn, SSH_INIT);
|
||||||
|
|
||||||
if(data->state.used_interface == Curl_if_multi)
|
result = ssh_multi_statemach(conn, done);
|
||||||
result = ssh_multi_statemach(conn, done);
|
|
||||||
else {
|
|
||||||
result = ssh_easy_statemach(conn, TRUE);
|
|
||||||
if(!result)
|
|
||||||
*done = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2828,13 +2822,8 @@ 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 */
|
||||||
if(conn->data->state.used_interface == Curl_if_multi) {
|
result = ssh_multi_statemach(conn, dophase_done);
|
||||||
result = ssh_multi_statemach(conn, dophase_done);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = ssh_easy_statemach(conn, FALSE);
|
|
||||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
|
||||||
}
|
|
||||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||||
|
|
||||||
if(*dophase_done) {
|
if(*dophase_done) {
|
||||||
@ -3037,13 +3026,8 @@ 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 */
|
||||||
if(conn->data->state.used_interface == Curl_if_multi) {
|
result = ssh_multi_statemach(conn, dophase_done);
|
||||||
result = ssh_multi_statemach(conn, dophase_done);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = ssh_easy_statemach(conn, FALSE);
|
|
||||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
|
||||||
}
|
|
||||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||||
|
|
||||||
if(*dophase_done) {
|
if(*dophase_done) {
|
||||||
|
12
lib/ssluse.c
12
lib/ssluse.c
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -1520,16 +1520,6 @@ ossl_connect_step1(struct connectdata *conn,
|
|||||||
|
|
||||||
SSL_CTX_set_options(connssl->ctx, ctx_options);
|
SSL_CTX_set_options(connssl->ctx, ctx_options);
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* Not sure it's needed to tell SSL_connect() that socket is
|
|
||||||
* non-blocking. It doesn't seem to care, but just return with
|
|
||||||
* SSL_ERROR_WANT_x.
|
|
||||||
*/
|
|
||||||
if(data->state.used_interface == Curl_if_multi)
|
|
||||||
SSL_CTX_ctrl(connssl->ctx, BIO_C_SET_NBIO, 1, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
|
if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
|
||||||
if(!cert_stuff(conn,
|
if(!cert_stuff(conn,
|
||||||
connssl->ctx,
|
connssl->ctx,
|
||||||
|
132
lib/tftp.c
132
lib/tftp.c
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -1185,129 +1185,6 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
|
|||||||
return (long)(state->max_time - current);
|
return (long)(state->max_time - current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************
|
|
||||||
*
|
|
||||||
* tftp_easy_statemach
|
|
||||||
*
|
|
||||||
* Handle easy request until completion
|
|
||||||
*
|
|
||||||
**********************************************************/
|
|
||||||
static CURLcode tftp_easy_statemach(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
int check_time = 0;
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
|
|
||||||
curl_socket_t fd_read;
|
|
||||||
long timeout_ms;
|
|
||||||
struct SingleRequest *k = &data->req;
|
|
||||||
struct timeval transaction_start = Curl_tvnow();
|
|
||||||
|
|
||||||
k->start = transaction_start;
|
|
||||||
k->now = transaction_start;
|
|
||||||
|
|
||||||
/* Run the TFTP State Machine */
|
|
||||||
for(; (state->state != TFTP_STATE_FIN) && (result == CURLE_OK); ) {
|
|
||||||
|
|
||||||
timeout_ms = state->retry_time * 1000;
|
|
||||||
|
|
||||||
if(data->set.upload) {
|
|
||||||
if(data->set.max_send_speed &&
|
|
||||||
(data->progress.ulspeed > data->set.max_send_speed)) {
|
|
||||||
fd_read = CURL_SOCKET_BAD;
|
|
||||||
timeout_ms = Curl_sleep_time(data->set.max_send_speed,
|
|
||||||
data->progress.ulspeed, state->blksize);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fd_read = state->sockfd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(data->set.max_recv_speed &&
|
|
||||||
(data->progress.dlspeed > data->set.max_recv_speed)) {
|
|
||||||
fd_read = CURL_SOCKET_BAD;
|
|
||||||
timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
|
|
||||||
data->progress.dlspeed, state->blksize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fd_read = state->sockfd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data->set.timeout) {
|
|
||||||
timeout_ms = data->set.timeout - Curl_tvdiff(k->now, k->start);
|
|
||||||
if(timeout_ms > state->retry_time * 1000)
|
|
||||||
timeout_ms = state->retry_time * 1000;
|
|
||||||
else if(timeout_ms < 0)
|
|
||||||
timeout_ms = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Wait until ready to read or timeout occurs */
|
|
||||||
rc = Curl_socket_ready(fd_read, CURL_SOCKET_BAD, timeout_ms);
|
|
||||||
|
|
||||||
k->now = Curl_tvnow();
|
|
||||||
|
|
||||||
/* Force a progress callback if it's been too long */
|
|
||||||
if(Curl_tvdiff(k->now, k->start) >= data->set.timeout) {
|
|
||||||
if(Curl_pgrsUpdate(conn)) {
|
|
||||||
tftp_state_machine(state, TFTP_EVENT_ERROR);
|
|
||||||
return CURLE_ABORTED_BY_CALLBACK;
|
|
||||||
}
|
|
||||||
k->start = k->now;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rc == -1) {
|
|
||||||
/* bail out */
|
|
||||||
int error = SOCKERRNO;
|
|
||||||
failf(data, "%s", Curl_strerror(conn, error));
|
|
||||||
state->event = TFTP_EVENT_ERROR;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
if(rc==0) {
|
|
||||||
/* A timeout occurred, but our timeout is variable, so maybe
|
|
||||||
just continue? */
|
|
||||||
long rtms = state->retry_time * 1000;
|
|
||||||
if(Curl_tvdiff(k->now, transaction_start) > rtms) {
|
|
||||||
state->event = TFTP_EVENT_TIMEOUT;
|
|
||||||
/* Force a look at transfer timeouts */
|
|
||||||
check_time = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
continue; /* skip state machine */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = tftp_receive_packet(conn);
|
|
||||||
if(result == CURLE_OK)
|
|
||||||
transaction_start = Curl_tvnow();
|
|
||||||
|
|
||||||
if(k->bytecountp)
|
|
||||||
*k->bytecountp = k->bytecount; /* read count */
|
|
||||||
if(k->writebytecountp)
|
|
||||||
*k->writebytecountp = k->writebytecount; /* write count */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(check_time) {
|
|
||||||
tftp_state_timeout(conn, NULL);
|
|
||||||
check_time = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result)
|
|
||||||
return(result);
|
|
||||||
|
|
||||||
result = tftp_state_machine(state, state->event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tell curl we're done */
|
|
||||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************
|
/**********************************************************
|
||||||
*
|
*
|
||||||
* tftp_multi_statemach
|
* tftp_multi_statemach
|
||||||
@ -1404,12 +1281,7 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
|
|||||||
if(state->state == TFTP_STATE_FIN || result != CURLE_OK)
|
if(state->state == TFTP_STATE_FIN || result != CURLE_OK)
|
||||||
return(result);
|
return(result);
|
||||||
|
|
||||||
if(conn->data->state.used_interface == Curl_if_multi)
|
tftp_multi_statemach(conn, dophase_done);
|
||||||
tftp_multi_statemach(conn, dophase_done);
|
|
||||||
else {
|
|
||||||
result = tftp_easy_statemach(conn);
|
|
||||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*dophase_done)
|
if(*dophase_done)
|
||||||
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -2068,8 +2068,6 @@ static CURLcode Curl_do_perform(struct SessionHandle *data)
|
|||||||
char *newurl = NULL; /* possibly a new URL to follow to! */
|
char *newurl = NULL; /* possibly a new URL to follow to! */
|
||||||
followtype follow = FOLLOW_NONE;
|
followtype follow = FOLLOW_NONE;
|
||||||
|
|
||||||
data->state.used_interface = Curl_if_easy;
|
|
||||||
|
|
||||||
res = Curl_pretransfer(data);
|
res = Curl_pretransfer(data);
|
||||||
if(res)
|
if(res)
|
||||||
return res;
|
return res;
|
||||||
|
98
lib/url.c
98
lib/url.c
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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,7 +131,6 @@ int curl_win32_idn_to_ascii(const char *in, char **out);
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/* Local static prototypes */
|
/* Local static prototypes */
|
||||||
static bool ConnectionKillOne(struct SessionHandle *data);
|
|
||||||
static void conn_free(struct connectdata *conn);
|
static void conn_free(struct connectdata *conn);
|
||||||
static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
|
static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
|
||||||
static CURLcode do_init(struct connectdata *conn);
|
static CURLcode do_init(struct connectdata *conn);
|
||||||
@ -255,15 +254,6 @@ static const struct Curl_handler Curl_handler_dummy = {
|
|||||||
PROTOPT_NONE /* flags */
|
PROTOPT_NONE /* flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void close_connections(struct SessionHandle *data)
|
|
||||||
{
|
|
||||||
/* Loop through all open connections and kill them one by one */
|
|
||||||
bool killed;
|
|
||||||
do {
|
|
||||||
killed = ConnectionKillOne(data);
|
|
||||||
} while(killed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Curl_freeset(struct SessionHandle * data)
|
void Curl_freeset(struct SessionHandle * data)
|
||||||
{
|
{
|
||||||
/* Free all dynamic strings stored in the data->set substructure. */
|
/* Free all dynamic strings stored in the data->set substructure. */
|
||||||
@ -386,6 +376,11 @@ CURLcode Curl_close(struct SessionHandle *data)
|
|||||||
and detach this handle from there. */
|
and detach this handle from there. */
|
||||||
curl_multi_remove_handle(data->multi, data);
|
curl_multi_remove_handle(data->multi, data);
|
||||||
|
|
||||||
|
if(data->multi_easy)
|
||||||
|
/* when curl_easy_perform() is used, it creates its own multi handle to
|
||||||
|
use and this is the one */
|
||||||
|
curl_multi_cleanup(data->multi_easy);
|
||||||
|
|
||||||
/* Destroy the timeout list that is held in the easy handle. It is
|
/* Destroy the timeout list that is held in the easy handle. It is
|
||||||
/normally/ done by curl_multi_remove_handle() but this is "just in
|
/normally/ done by curl_multi_remove_handle() but this is "just in
|
||||||
case" */
|
case" */
|
||||||
@ -398,19 +393,6 @@ CURLcode Curl_close(struct SessionHandle *data)
|
|||||||
the multi handle, since that function uses the magic
|
the multi handle, since that function uses the magic
|
||||||
field! */
|
field! */
|
||||||
|
|
||||||
if(data->state.conn_cache) {
|
|
||||||
if(data->state.conn_cache->type == CONNCACHE_PRIVATE) {
|
|
||||||
/* close all connections still alive that are in the private connection
|
|
||||||
cache, as we no longer have the pointer left to the shared one. */
|
|
||||||
close_connections(data);
|
|
||||||
Curl_conncache_destroy(data->state.conn_cache);
|
|
||||||
data->state.conn_cache = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data->dns.hostcachetype == HCACHE_PRIVATE)
|
|
||||||
Curl_hostcache_destroy(data);
|
|
||||||
|
|
||||||
if(data->state.rangestringalloc)
|
if(data->state.rangestringalloc)
|
||||||
free(data->state.range);
|
free(data->state.range);
|
||||||
|
|
||||||
@ -2000,10 +1982,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
data->share->dirty++;
|
data->share->dirty++;
|
||||||
|
|
||||||
if(data->share->hostcache) {
|
if(data->share->hostcache) {
|
||||||
/* use shared host cache, first free the private one if any */
|
/* use shared host cache */
|
||||||
if(data->dns.hostcachetype == HCACHE_PRIVATE)
|
|
||||||
Curl_hostcache_destroy(data);
|
|
||||||
|
|
||||||
data->dns.hostcache = data->share->hostcache;
|
data->dns.hostcache = data->share->hostcache;
|
||||||
data->dns.hostcachetype = HCACHE_SHARED;
|
data->dns.hostcachetype = HCACHE_SHARED;
|
||||||
}
|
}
|
||||||
@ -2982,69 +2961,6 @@ ConnectionExists(struct SessionHandle *data,
|
|||||||
return FALSE; /* no matching connecting exists */
|
return FALSE; /* no matching connecting exists */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This function kills and removes an existing connection in the connection
|
|
||||||
* cache. The connection that has been unused for the longest time.
|
|
||||||
*
|
|
||||||
* Returns FALSE if it can't find any unused connection to kill.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
ConnectionKillOne(struct SessionHandle *data)
|
|
||||||
{
|
|
||||||
struct conncache *bc = data->state.conn_cache;
|
|
||||||
struct curl_hash_iterator iter;
|
|
||||||
struct curl_llist_element *curr;
|
|
||||||
struct curl_hash_element *he;
|
|
||||||
long highscore=-1;
|
|
||||||
long score;
|
|
||||||
struct timeval now;
|
|
||||||
struct connectdata *conn_candidate = NULL;
|
|
||||||
struct connectbundle *bundle;
|
|
||||||
|
|
||||||
now = Curl_tvnow();
|
|
||||||
|
|
||||||
Curl_hash_start_iterate(bc->hash, &iter);
|
|
||||||
|
|
||||||
he = Curl_hash_next_element(&iter);
|
|
||||||
while(he) {
|
|
||||||
struct connectdata *conn;
|
|
||||||
|
|
||||||
bundle = he->ptr;
|
|
||||||
|
|
||||||
curr = bundle->conn_list->head;
|
|
||||||
while(curr) {
|
|
||||||
conn = curr->ptr;
|
|
||||||
|
|
||||||
if(!conn->inuse) {
|
|
||||||
/* Set higher score for the age passed since the connection was used */
|
|
||||||
score = Curl_tvdiff(now, conn->now);
|
|
||||||
|
|
||||||
if(score > highscore) {
|
|
||||||
highscore = score;
|
|
||||||
conn_candidate = conn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
curr = curr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
he = Curl_hash_next_element(&iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(conn_candidate) {
|
|
||||||
/* Set the connection's owner correctly */
|
|
||||||
conn_candidate->data = data;
|
|
||||||
|
|
||||||
bundle = conn_candidate->bundle;
|
|
||||||
|
|
||||||
/* the winner gets the honour of being disconnected */
|
|
||||||
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this connection can now be marked 'idle' */
|
/* this connection can now be marked 'idle' */
|
||||||
static void
|
static void
|
||||||
ConnectionDone(struct connectdata *conn)
|
ConnectionDone(struct connectdata *conn)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -1147,15 +1147,15 @@ struct auth {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct UrlState {
|
struct UrlState {
|
||||||
enum {
|
|
||||||
Curl_if_none,
|
|
||||||
Curl_if_easy,
|
|
||||||
Curl_if_multi
|
|
||||||
} used_interface;
|
|
||||||
|
|
||||||
/* Points to the connection cache */
|
/* Points to the connection cache */
|
||||||
struct conncache *conn_cache;
|
struct conncache *conn_cache;
|
||||||
|
|
||||||
|
/* when curl_easy_perform() is called, the multi handle is "owned" by
|
||||||
|
the easy handle so curl_easy_cleanup() on such an easy handle will
|
||||||
|
also close the multi handle! */
|
||||||
|
bool multi_owned_by_easy;
|
||||||
|
|
||||||
/* buffers to store authentication data in, as parsed from input options */
|
/* buffers to store authentication data in, as parsed from input options */
|
||||||
struct timeval keeps_speed; /* for the progress meter really */
|
struct timeval keeps_speed; /* for the progress meter really */
|
||||||
|
|
||||||
@ -1588,7 +1588,6 @@ struct Names {
|
|||||||
struct curl_hash *hostcache;
|
struct curl_hash *hostcache;
|
||||||
enum {
|
enum {
|
||||||
HCACHE_NONE, /* not pointing to anything */
|
HCACHE_NONE, /* not pointing to anything */
|
||||||
HCACHE_PRIVATE, /* points to our own */
|
|
||||||
HCACHE_GLOBAL, /* points to the (shrug) global one */
|
HCACHE_GLOBAL, /* points to the (shrug) global one */
|
||||||
HCACHE_MULTI, /* points to a shared one in the multi handle */
|
HCACHE_MULTI, /* points to a shared one in the multi handle */
|
||||||
HCACHE_SHARED /* points to a shared one in a shared object */
|
HCACHE_SHARED /* points to a shared one in a shared object */
|
||||||
@ -1608,7 +1607,11 @@ struct Names {
|
|||||||
struct SessionHandle {
|
struct SessionHandle {
|
||||||
struct Names dns;
|
struct Names dns;
|
||||||
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
|
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
|
||||||
struct to which this "belongs" */
|
struct to which this "belongs" when used by
|
||||||
|
the multi interface */
|
||||||
|
struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle
|
||||||
|
struct to which this "belongs" when used
|
||||||
|
by the easy interface */
|
||||||
struct Curl_one_easy *multi_pos; /* if non-NULL, points to its position
|
struct Curl_one_easy *multi_pos; /* if non-NULL, points to its position
|
||||||
in multi controlling structure to assist
|
in multi controlling structure to assist
|
||||||
in removal. */
|
in removal. */
|
||||||
|
@ -27,7 +27,7 @@ EXTRA_DIST = ftpserver.pl httpserver.pl secureserver.pl runtests.pl getpart.pm \
|
|||||||
FILEFORMAT README stunnel.pem memanalyze.pl testcurl.pl valgrind.pm ftp.pm \
|
FILEFORMAT README stunnel.pem memanalyze.pl testcurl.pl valgrind.pm ftp.pm \
|
||||||
sshserver.pl sshhelp.pm testcurl.1 runtests.1 $(HTMLPAGES) $(PDFPAGES) \
|
sshserver.pl sshhelp.pm testcurl.1 runtests.1 $(HTMLPAGES) $(PDFPAGES) \
|
||||||
serverhelp.pm tftpserver.pl rtspserver.pl directories.pm symbol-scan.pl \
|
serverhelp.pm tftpserver.pl rtspserver.pl directories.pm symbol-scan.pl \
|
||||||
CMakeLists.txt mem-include-scan.pl
|
CMakeLists.txt mem-include-scan.pl valgrind.supp
|
||||||
|
|
||||||
# we have two variables here to make sure DIST_SUBDIRS won't get 'unit'
|
# we have two variables here to make sure DIST_SUBDIRS won't get 'unit'
|
||||||
# added twice as then targets such as 'distclean' misbehave and try to
|
# added twice as then targets such as 'distclean' misbehave and try to
|
||||||
|
@ -36,6 +36,11 @@ FTP PORT download, no data conn and no transient negative reply
|
|||||||
<strippart>
|
<strippart>
|
||||||
s/^EPRT \|1\|(.*)/EPRT \|1\|/
|
s/^EPRT \|1\|(.*)/EPRT \|1\|/
|
||||||
</strippart>
|
</strippart>
|
||||||
|
|
||||||
|
# This test doesn't send a QUIT because the main state machine in multi.c
|
||||||
|
# triggers the timeout and sets the CURLE_OPERATION_TIMEDOUT error (28) for
|
||||||
|
# which the FTP disconect code generically has to assume could mean the
|
||||||
|
# control the connection and thus it cannot send any command.
|
||||||
<protocol>
|
<protocol>
|
||||||
USER anonymous
|
USER anonymous
|
||||||
PASS ftp@example.com
|
PASS ftp@example.com
|
||||||
@ -44,10 +49,9 @@ EPRT |1|
|
|||||||
TYPE I
|
TYPE I
|
||||||
SIZE 1208
|
SIZE 1208
|
||||||
RETR 1208
|
RETR 1208
|
||||||
QUIT
|
|
||||||
</protocol>
|
</protocol>
|
||||||
<errorcode>
|
<errorcode>
|
||||||
12
|
28
|
||||||
</errorcode>
|
</errorcode>
|
||||||
</verify>
|
</verify>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
@ -54,6 +54,8 @@ fooo
|
|||||||
mooo
|
mooo
|
||||||
</file1>
|
</file1>
|
||||||
|
|
||||||
|
# The final "221 bye bye baby" response to QUIT will not be recorded
|
||||||
|
# since that is not considered part of this particular transfer!
|
||||||
<file2 name="log/heads1349">
|
<file2 name="log/heads1349">
|
||||||
220- _ _ ____ _
|
220- _ _ ____ _
|
||||||
220- ___| | | | _ \| |
|
220- ___| | | | _ \| |
|
||||||
@ -69,7 +71,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1349 () (10 bytes).
|
150 Binary data connection for 1349 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -54,6 +54,8 @@ fooo
|
|||||||
mooo
|
mooo
|
||||||
</file1>
|
</file1>
|
||||||
|
|
||||||
|
# The final "221 bye bye baby" response to QUIT will not be recorded
|
||||||
|
# since that is not considered part of this particular transfer!
|
||||||
<file2 name="log/stdout1350">
|
<file2 name="log/stdout1350">
|
||||||
220- _ _ ____ _
|
220- _ _ ____ _
|
||||||
220- ___| | | | _ \| |
|
220- ___| | | | _ \| |
|
||||||
@ -69,7 +71,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1350 () (10 bytes).
|
150 Binary data connection for 1350 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -55,6 +55,8 @@ fooo
|
|||||||
mooo
|
mooo
|
||||||
</file1>
|
</file1>
|
||||||
|
|
||||||
|
# The final "221 bye bye baby" response to QUIT will not be recorded
|
||||||
|
# since that is not considered part of this particular transfer!
|
||||||
<file2 name="log/heads1351">
|
<file2 name="log/heads1351">
|
||||||
220- _ _ ____ _
|
220- _ _ ____ _
|
||||||
220- ___| | | | _ \| |
|
220- ___| | | | _ \| |
|
||||||
@ -70,7 +72,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1351 () (10 bytes).
|
150 Binary data connection for 1351 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -55,6 +55,8 @@ fooo
|
|||||||
mooo
|
mooo
|
||||||
</file1>
|
</file1>
|
||||||
|
|
||||||
|
# The final "221 bye bye baby" response to QUIT will not be recorded
|
||||||
|
# since that is not considered part of this particular transfer!
|
||||||
<file2 name="log/stdout1352">
|
<file2 name="log/stdout1352">
|
||||||
220- _ _ ____ _
|
220- _ _ ____ _
|
||||||
220- ___| | | | _ \| |
|
220- ___| | | | _ \| |
|
||||||
@ -70,7 +72,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1352 () (10 bytes).
|
150 Binary data connection for 1352 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -54,6 +54,8 @@ fooo
|
|||||||
mooo
|
mooo
|
||||||
</file1>
|
</file1>
|
||||||
|
|
||||||
|
# The final "221 bye bye baby" response to QUIT will not be recorded
|
||||||
|
# since that is not considered part of this particular transfer!
|
||||||
<file2 name="log/heads1353">
|
<file2 name="log/heads1353">
|
||||||
220- _ _ ____ _
|
220- _ _ ____ _
|
||||||
220- ___| | | | _ \| |
|
220- ___| | | | _ \| |
|
||||||
@ -69,7 +71,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1353 () (10 bytes).
|
150 Binary data connection for 1353 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -69,7 +69,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1354 () (10 bytes).
|
150 Binary data connection for 1354 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -87,7 +87,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1357 () (214 bytes).
|
150 Binary data connection for 1357 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -87,7 +87,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1358 () (214 bytes).
|
150 Binary data connection for 1358 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -88,7 +88,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1359 () (214 bytes).
|
150 Binary data connection for 1359 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -88,7 +88,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1360 () (214 bytes).
|
150 Binary data connection for 1360 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -87,7 +87,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1361 () (214 bytes).
|
150 Binary data connection for 1361 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -87,7 +87,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1362 () (214 bytes).
|
150 Binary data connection for 1362 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -64,7 +64,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1379 () (10 bytes).
|
150 Binary data connection for 1379 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -64,7 +64,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1380 () (10 bytes).
|
150 Binary data connection for 1380 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -65,7 +65,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1381 () (10 bytes).
|
150 Binary data connection for 1381 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -65,7 +65,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1382 () (10 bytes).
|
150 Binary data connection for 1382 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -64,7 +64,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1383 () (10 bytes).
|
150 Binary data connection for 1383 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -64,7 +64,6 @@ mooo
|
|||||||
213 10
|
213 10
|
||||||
150 Binary data connection for 1384 () (10 bytes).
|
150 Binary data connection for 1384 () (10 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -79,7 +79,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1387 () (214 bytes).
|
150 Binary data connection for 1387 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -79,7 +79,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1388 () (214 bytes).
|
150 Binary data connection for 1388 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -80,7 +80,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1389 () (214 bytes).
|
150 Binary data connection for 1389 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -80,7 +80,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1390 () (214 bytes).
|
150 Binary data connection for 1390 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -79,7 +79,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1391 () (214 bytes).
|
150 Binary data connection for 1391 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -79,7 +79,6 @@ MOOOO
|
|||||||
213 214
|
213 214
|
||||||
150 Binary data connection for 1392 () (214 bytes).
|
150 Binary data connection for 1392 () (214 bytes).
|
||||||
226 File transfer complete
|
226 File transfer complete
|
||||||
221 bye bye baby
|
|
||||||
</file2>
|
</file2>
|
||||||
<stripfile2>
|
<stripfile2>
|
||||||
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
|
||||||
|
@ -12,7 +12,7 @@ LIST
|
|||||||
# Server-side
|
# Server-side
|
||||||
<reply>
|
<reply>
|
||||||
<servercmd>
|
<servercmd>
|
||||||
REPLY LIST +OK 1407 100
|
REPLY LIST +OK 1407 100\r\n.
|
||||||
</servercmd>
|
</servercmd>
|
||||||
</reply>
|
</reply>
|
||||||
|
|
||||||
|
@ -101,66 +101,60 @@ run 1: set cookie 1, 2 and 3
|
|||||||
lock: dns [Pigs in space]: 14
|
lock: dns [Pigs in space]: 14
|
||||||
unlock: dns [Pigs in space]: 15
|
unlock: dns [Pigs in space]: 15
|
||||||
CLEANUP
|
CLEANUP
|
||||||
lock: dns [Pigs in space]: 16
|
lock: cookie [Pigs in space]: 16
|
||||||
unlock: dns [Pigs in space]: 17
|
unlock: cookie [Pigs in space]: 17
|
||||||
lock: cookie [Pigs in space]: 18
|
lock: share [Pigs in space]: 18
|
||||||
unlock: cookie [Pigs in space]: 19
|
unlock: share [Pigs in space]: 19
|
||||||
lock: share [Pigs in space]: 20
|
|
||||||
unlock: share [Pigs in space]: 21
|
|
||||||
*** run 2
|
*** run 2
|
||||||
CURLOPT_SHARE
|
CURLOPT_SHARE
|
||||||
lock: share [Pigs in space]: 22
|
lock: share [Pigs in space]: 20
|
||||||
unlock: share [Pigs in space]: 23
|
unlock: share [Pigs in space]: 21
|
||||||
PERFORM
|
PERFORM
|
||||||
lock: dns [Pigs in space]: 24
|
lock: dns [Pigs in space]: 22
|
||||||
unlock: dns [Pigs in space]: 25
|
unlock: dns [Pigs in space]: 23
|
||||||
|
lock: cookie [Pigs in space]: 24
|
||||||
|
unlock: cookie [Pigs in space]: 25
|
||||||
lock: cookie [Pigs in space]: 26
|
lock: cookie [Pigs in space]: 26
|
||||||
unlock: cookie [Pigs in space]: 27
|
unlock: cookie [Pigs in space]: 27
|
||||||
lock: cookie [Pigs in space]: 28
|
lock: cookie [Pigs in space]: 28
|
||||||
unlock: cookie [Pigs in space]: 29
|
unlock: cookie [Pigs in space]: 29
|
||||||
lock: cookie [Pigs in space]: 30
|
|
||||||
unlock: cookie [Pigs in space]: 31
|
|
||||||
run 2: set cookie 4 and 5
|
run 2: set cookie 4 and 5
|
||||||
lock: dns [Pigs in space]: 32
|
lock: dns [Pigs in space]: 30
|
||||||
unlock: dns [Pigs in space]: 33
|
unlock: dns [Pigs in space]: 31
|
||||||
CLEANUP
|
CLEANUP
|
||||||
lock: dns [Pigs in space]: 34
|
lock: cookie [Pigs in space]: 32
|
||||||
unlock: dns [Pigs in space]: 35
|
unlock: cookie [Pigs in space]: 33
|
||||||
lock: cookie [Pigs in space]: 36
|
lock: share [Pigs in space]: 34
|
||||||
unlock: cookie [Pigs in space]: 37
|
unlock: share [Pigs in space]: 35
|
||||||
lock: share [Pigs in space]: 38
|
|
||||||
unlock: share [Pigs in space]: 39
|
|
||||||
*** run 3
|
*** run 3
|
||||||
CURLOPT_SHARE
|
CURLOPT_SHARE
|
||||||
lock: share [Pigs in space]: 40
|
lock: share [Pigs in space]: 36
|
||||||
unlock: share [Pigs in space]: 41
|
unlock: share [Pigs in space]: 37
|
||||||
CURLOPT_COOKIEJAR
|
CURLOPT_COOKIEJAR
|
||||||
PERFORM
|
PERFORM
|
||||||
lock: dns [Pigs in space]: 42
|
lock: dns [Pigs in space]: 38
|
||||||
unlock: dns [Pigs in space]: 43
|
unlock: dns [Pigs in space]: 39
|
||||||
|
lock: cookie [Pigs in space]: 40
|
||||||
|
unlock: cookie [Pigs in space]: 41
|
||||||
|
lock: cookie [Pigs in space]: 42
|
||||||
|
unlock: cookie [Pigs in space]: 43
|
||||||
lock: cookie [Pigs in space]: 44
|
lock: cookie [Pigs in space]: 44
|
||||||
unlock: cookie [Pigs in space]: 45
|
unlock: cookie [Pigs in space]: 45
|
||||||
lock: cookie [Pigs in space]: 46
|
|
||||||
unlock: cookie [Pigs in space]: 47
|
|
||||||
lock: cookie [Pigs in space]: 48
|
|
||||||
unlock: cookie [Pigs in space]: 49
|
|
||||||
run 3: overwrite cookie 1 and 4
|
run 3: overwrite cookie 1 and 4
|
||||||
lock: dns [Pigs in space]: 50
|
lock: dns [Pigs in space]: 46
|
||||||
unlock: dns [Pigs in space]: 51
|
unlock: dns [Pigs in space]: 47
|
||||||
try SHARE_CLEANUP...
|
try SHARE_CLEANUP...
|
||||||
lock: share [Pigs in space]: 52
|
lock: share [Pigs in space]: 48
|
||||||
unlock: share [Pigs in space]: 53
|
unlock: share [Pigs in space]: 49
|
||||||
SHARE_CLEANUP failed, correct
|
SHARE_CLEANUP failed, correct
|
||||||
CLEANUP
|
CLEANUP
|
||||||
lock: dns [Pigs in space]: 54
|
lock: cookie [Pigs in space]: 50
|
||||||
unlock: dns [Pigs in space]: 55
|
unlock: cookie [Pigs in space]: 51
|
||||||
lock: cookie [Pigs in space]: 56
|
lock: share [Pigs in space]: 52
|
||||||
unlock: cookie [Pigs in space]: 57
|
unlock: share [Pigs in space]: 53
|
||||||
lock: share [Pigs in space]: 58
|
|
||||||
unlock: share [Pigs in space]: 59
|
|
||||||
SHARE_CLEANUP
|
SHARE_CLEANUP
|
||||||
lock: share [Pigs in space]: 60
|
lock: share [Pigs in space]: 54
|
||||||
unlock: share [Pigs in space]: 61
|
unlock: share [Pigs in space]: 55
|
||||||
GLOBAL_CLEANUP
|
GLOBAL_CLEANUP
|
||||||
</stdout>
|
</stdout>
|
||||||
<stderr>
|
<stderr>
|
||||||
|
@ -10,7 +10,8 @@ LIST
|
|||||||
# Server-side
|
# Server-side
|
||||||
<reply>
|
<reply>
|
||||||
<servercmd>
|
<servercmd>
|
||||||
REPLY LIST +OK 808 100
|
# include the '.\r\n' 3-byte trailer to end the transfer poperly!
|
||||||
|
REPLY LIST +OK 808 100\r\n.
|
||||||
</servercmd>
|
</servercmd>
|
||||||
</reply>
|
</reply>
|
||||||
|
|
||||||
|
@ -34,11 +34,13 @@ pop3://%HOSTIP:%POP3PORT/813 -u user:wrong
|
|||||||
<errorcode>
|
<errorcode>
|
||||||
67
|
67
|
||||||
</errorcode>
|
</errorcode>
|
||||||
|
#
|
||||||
|
# The multi interface considers a broken "DO" request as a prematurely broken
|
||||||
|
# transfer and such a connection will not get a "QUIT"
|
||||||
<protocol>
|
<protocol>
|
||||||
CAPA
|
CAPA
|
||||||
USER user
|
USER user
|
||||||
PASS wrong
|
PASS wrong
|
||||||
QUIT
|
|
||||||
</protocol>
|
</protocol>
|
||||||
</verify>
|
</verify>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, 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
|
||||||
@ -41,7 +41,7 @@
|
|||||||
#error "this test requires FD_SETSIZE"
|
#error "this test requires FD_SETSIZE"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SAFETY_MARGIN (10)
|
#define SAFETY_MARGIN (11)
|
||||||
|
|
||||||
#if defined(WIN32) || defined(_WIN32) || defined(MSDOS)
|
#if defined(WIN32) || defined(_WIN32) || defined(MSDOS)
|
||||||
#define DEV_NULL "NUL"
|
#define DEV_NULL "NUL"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# | (__| |_| | _ <| |___
|
# | (__| |_| | _ <| |___
|
||||||
# \___|\___/|_| \_\_____|
|
# \___|\___/|_| \_\_____|
|
||||||
#
|
#
|
||||||
# Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
# Copyright (C) 1998 - 2013, 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
|
||||||
@ -3084,6 +3084,7 @@ sub singletest {
|
|||||||
my $valgrindcmd = "$valgrind ";
|
my $valgrindcmd = "$valgrind ";
|
||||||
$valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
|
$valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
|
||||||
$valgrindcmd .= "--leak-check=yes ";
|
$valgrindcmd .= "--leak-check=yes ";
|
||||||
|
$valgrindcmd .= "--suppressions=valgrind.supp ";
|
||||||
$valgrindcmd .= "--num-callers=16 ";
|
$valgrindcmd .= "--num-callers=16 ";
|
||||||
$valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
|
$valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
|
||||||
$CMDLINE = "$valgrindcmd $CMDLINE";
|
$CMDLINE = "$valgrindcmd $CMDLINE";
|
||||||
|
16
tests/valgrind.supp
Normal file
16
tests/valgrind.supp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
libidn-idna_to_ascii-error
|
||||||
|
Memcheck:Addr4
|
||||||
|
fun:idna_to_ascii_4z
|
||||||
|
fun:idna_to_ascii_8z
|
||||||
|
fun:idna_to_ascii_lz
|
||||||
|
fun:fix_hostname
|
||||||
|
fun:resolve_server
|
||||||
|
fun:create_conn
|
||||||
|
fun:Curl_connect
|
||||||
|
fun:multi_runsingle
|
||||||
|
fun:curl_multi_perform
|
||||||
|
fun:curl_easy_perform
|
||||||
|
fun:operate
|
||||||
|
fun:main
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user