mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 07:38:49 -05:00
FTP code turned into state machine. Not completely yet, but a good start.
The tag 'before_ftp_statemachine' was set just before this commit in case of future need.
This commit is contained in:
parent
120f17ce04
commit
6a2e21ec8c
@ -245,7 +245,9 @@ typedef enum {
|
||||
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
|
||||
CURLE_COULDNT_CONNECT, /* 7 */
|
||||
CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
|
||||
CURLE_FTP_ACCESS_DENIED, /* 9 */
|
||||
CURLE_FTP_ACCESS_DENIED, /* 9 a service was denied by the FTP server
|
||||
due to lack of access - when login fails
|
||||
this is not returned. */
|
||||
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 */
|
||||
CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
|
||||
CURLE_FTP_WEIRD_USER_REPLY, /* 12 */
|
||||
@ -305,6 +307,8 @@ typedef enum {
|
||||
CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
|
||||
that failed */
|
||||
CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
|
||||
CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
|
||||
accepted and we failed to login */
|
||||
CURL_LAST /* never use! */
|
||||
} CURLcode;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -85,7 +85,7 @@
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
CURLcode Curl_dict(struct connectdata *conn)
|
||||
CURLcode Curl_dict(struct connectdata *conn, bool *done)
|
||||
{
|
||||
char *word;
|
||||
char *ppath;
|
||||
@ -100,6 +100,8 @@ CURLcode Curl_dict(struct connectdata *conn)
|
||||
char *path = conn->path;
|
||||
curl_off_t *bytecount = &conn->bytecount;
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
|
||||
if(conn->bits.user_passwd) {
|
||||
/* AUTH is missing */
|
||||
}
|
||||
|
14
lib/dict.h
14
lib/dict.h
@ -2,18 +2,18 @@
|
||||
#define __DICT_H
|
||||
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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.
|
||||
@ -24,7 +24,7 @@
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
#ifndef CURL_DISABLE_DICT
|
||||
CURLcode Curl_dict(struct connectdata *conn);
|
||||
CURLcode Curl_dict(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_dict_done(struct connectdata *conn);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -266,7 +266,7 @@ static CURLcode file_upload(struct connectdata *conn)
|
||||
* opposed to sockets) we instead perform the whole do-operation in this
|
||||
* function.
|
||||
*/
|
||||
CURLcode Curl_file(struct connectdata *conn)
|
||||
CURLcode Curl_file(struct connectdata *conn, bool *done)
|
||||
{
|
||||
/* This implementation ignores the host name in conformance with
|
||||
RFC 1738. Only local files (reachable via the standard file system)
|
||||
@ -286,6 +286,8 @@ CURLcode Curl_file(struct connectdata *conn)
|
||||
int fd;
|
||||
struct timeval now = Curl_tvnow();
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
|
||||
Curl_readwrite_init(conn);
|
||||
Curl_initinfo(data);
|
||||
Curl_pgrsStartNow(data);
|
||||
|
14
lib/file.h
14
lib/file.h
@ -2,18 +2,18 @@
|
||||
#define __FILE_H
|
||||
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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.
|
||||
@ -24,7 +24,7 @@
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
#ifndef CURL_DISABLE_FILE
|
||||
CURLcode Curl_file(struct connectdata *);
|
||||
CURLcode Curl_file(struct connectdata *, bool *done);
|
||||
CURLcode Curl_file_done(struct connectdata *, CURLcode);
|
||||
CURLcode Curl_file_connect(struct connectdata *);
|
||||
#endif
|
||||
|
29
lib/ftp.h
29
lib/ftp.h
@ -1,18 +1,18 @@
|
||||
#ifndef __FTP_H
|
||||
#define __FTP_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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.
|
||||
@ -24,14 +24,21 @@
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
CURLcode Curl_ftp(struct connectdata *conn);
|
||||
CURLcode Curl_ftp(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode);
|
||||
CURLcode Curl_ftp_connect(struct connectdata *conn);
|
||||
CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
|
||||
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
|
||||
CURLcode Curl_nbftpsendf(struct connectdata *, const char *fmt, ...);
|
||||
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
|
||||
int *ftpcode);
|
||||
CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_ftp_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
CURLcode Curl_ftp_doing(struct connectdata *conn,
|
||||
bool *dophase_done);
|
||||
#endif /* CURL_DISABLE_FTP */
|
||||
#endif /* __FTP_H */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -99,7 +99,7 @@
|
||||
#ifdef CURLRES_ARES
|
||||
|
||||
/*
|
||||
* Curl_fdset() is called when someone from the outside world (using
|
||||
* Curl_resolv_fdset() is called when someone from the outside world (using
|
||||
* curl_multi_fdset()) wants to get our fd_set setup and we're talking with
|
||||
* ares. The caller must make sure that this function is only called when we
|
||||
* have a working ares channel.
|
||||
@ -107,10 +107,10 @@
|
||||
* Returns: CURLE_OK always!
|
||||
*/
|
||||
|
||||
CURLcode Curl_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
|
||||
{
|
||||
int max = ares_fds(conn->data->state.areschannel,
|
||||
|
@ -67,11 +67,6 @@
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||
#undef in_addr_t
|
||||
#define in_addr_t unsigned long
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "hostip.h"
|
||||
|
@ -67,11 +67,6 @@
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||
#undef in_addr_t
|
||||
#define in_addr_t unsigned long
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "hostip.h"
|
||||
|
10
lib/hostip.h
10
lib/hostip.h
@ -159,13 +159,13 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||
struct Curl_dns_entry **dnsentry);
|
||||
|
||||
/* Curl_fdset() is a generic function that exists in multiple versions
|
||||
/* Curl_resolv_fdset() is a generic function that exists in multiple versions
|
||||
depending on what name resolve technology we've built to use. The function
|
||||
is called from the curl_multi_fdset() function */
|
||||
CURLcode Curl_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
/* unlock a previously resolved dns entry */
|
||||
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns);
|
||||
|
||||
|
@ -67,11 +67,6 @@
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||
#undef in_addr_t
|
||||
#define in_addr_t unsigned long
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "hostip.h"
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -67,11 +67,6 @@
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||
#undef in_addr_t
|
||||
#define in_addr_t unsigned long
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "hostip.h"
|
||||
@ -133,10 +128,10 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
* It is present here to keep #ifdefs out from multi.c
|
||||
*/
|
||||
|
||||
CURLcode Curl_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
{
|
||||
(void)conn;
|
||||
(void)read_fd_set;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -155,7 +155,7 @@ struct thread_data {
|
||||
HANDLE thread_hnd;
|
||||
unsigned thread_id;
|
||||
DWORD thread_status;
|
||||
curl_socket_t dummy_sock; /* dummy for Curl_fdset() */
|
||||
curl_socket_t dummy_sock; /* dummy for Curl_resolv_fdset() */
|
||||
FILE *stderr_file;
|
||||
HANDLE mutex_waiting; /* marks that we are still waiting for a resolve */
|
||||
HANDLE event_resolved; /* marks that the thread obtained the information */
|
||||
@ -404,9 +404,9 @@ static bool init_resolve_thread (struct connectdata *conn,
|
||||
destroy_thread_data(&conn->async);
|
||||
return FALSE;
|
||||
}
|
||||
/* This socket is only to keep Curl_fdset() and select() happy; should never
|
||||
* become signalled for read/write since it's unbound but Windows needs
|
||||
* atleast 1 socket in select().
|
||||
/* This socket is only to keep Curl_resolv_fdset() and select() happy;
|
||||
* should never become signalled for read/write since it's unbound but
|
||||
* Windows needs atleast 1 socket in select().
|
||||
*/
|
||||
td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
return TRUE;
|
||||
@ -541,10 +541,10 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
{
|
||||
const struct thread_data *td =
|
||||
(const struct thread_data *) conn->async.os_specific;
|
||||
|
13
lib/http.c
13
lib/http.c
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -1222,7 +1222,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
||||
* Curl_http_connect() performs HTTP stuff to do at connect-time, called from
|
||||
* the generic Curl_connect().
|
||||
*/
|
||||
CURLcode Curl_http_connect(struct connectdata *conn)
|
||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
struct SessionHandle *data;
|
||||
CURLcode result;
|
||||
@ -1261,6 +1261,8 @@ CURLcode Curl_http_connect(struct connectdata *conn)
|
||||
data->state.first_host = strdup(conn->host.name);
|
||||
}
|
||||
|
||||
*done = TRUE;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -1328,7 +1330,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
* request is to be performed. This creates and sends a properly constructed
|
||||
* HTTP request.
|
||||
*/
|
||||
CURLcode Curl_http(struct connectdata *conn)
|
||||
CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
{
|
||||
struct SessionHandle *data=conn->data;
|
||||
char *buf = data->state.buffer; /* this is a short cut to the buffer */
|
||||
@ -1342,6 +1344,11 @@ CURLcode Curl_http(struct connectdata *conn)
|
||||
Curl_HttpReq httpreq = data->set.httpreq;
|
||||
char *addcookies = NULL;
|
||||
|
||||
/* Always consider the DO phase done after this function call, even if there
|
||||
may be parts of the request that is not yet sent, since we can deal with
|
||||
the rest of the request in the PERFORM phase. */
|
||||
*done = TRUE;
|
||||
|
||||
if(!conn->proto.http) {
|
||||
/* Only allocate this struct if we don't already have it! */
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -34,9 +34,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
||||
char *hostname, int remote_port);
|
||||
|
||||
/* protocol-specific functions set up to be called by the main engine */
|
||||
CURLcode Curl_http(struct connectdata *conn);
|
||||
CURLcode Curl_http(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_done(struct connectdata *, CURLcode);
|
||||
CURLcode Curl_http_connect(struct connectdata *conn);
|
||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
|
||||
|
||||
/* The following functions are defined in http_chunks.c */
|
||||
void Curl_httpchunk_init(struct connectdata *conn);
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -224,7 +224,7 @@ static void (*ldap_free_urldesc)(LDAPURLDesc *) = _ldap_free_urldesc;
|
||||
#endif
|
||||
|
||||
|
||||
CURLcode Curl_ldap(struct connectdata *conn)
|
||||
CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
{
|
||||
CURLcode status = CURLE_OK;
|
||||
int rc = 0;
|
||||
@ -256,6 +256,7 @@ CURLcode Curl_ldap(struct connectdata *conn)
|
||||
int num = 0;
|
||||
struct SessionHandle *data=conn->data;
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
infof(data, "LDAP local: %s\n", data->change.url);
|
||||
|
||||
if (!DynaOpen(&mod_name)) {
|
||||
|
14
lib/ldap.h
14
lib/ldap.h
@ -2,18 +2,18 @@
|
||||
#define __LDAP_H
|
||||
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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.
|
||||
@ -24,6 +24,6 @@
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
#ifndef CURL_DISABLE_LDAP
|
||||
CURLcode Curl_ldap(struct connectdata *conn);
|
||||
CURLcode Curl_ldap(struct connectdata *conn, bool *done);
|
||||
#endif
|
||||
#endif /* __LDAP_H */
|
||||
|
191
lib/multi.c
191
lib/multi.c
@ -45,6 +45,7 @@
|
||||
#include "memory.h"
|
||||
#include "easyif.h"
|
||||
#include "multiif.h"
|
||||
#include "sendf.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
@ -56,11 +57,14 @@ struct Curl_message {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CURLM_STATE_INIT,
|
||||
CURLM_STATE_INIT, /* start in this state */
|
||||
CURLM_STATE_CONNECT, /* resolve/connect has been sent off */
|
||||
CURLM_STATE_WAITRESOLVE, /* we're awaiting the resolve to finalize */
|
||||
CURLM_STATE_WAITCONNECT, /* we're awaiting the connect to finalize */
|
||||
CURLM_STATE_DO, /* send off the request (part 1) */
|
||||
CURLM_STATE_WAITRESOLVE, /* awaiting the resolve to finalize */
|
||||
CURLM_STATE_WAITCONNECT, /* awaiting the connect to finalize */
|
||||
CURLM_STATE_PROTOCONNECT, /* completing the protocol-specific connect
|
||||
phase */
|
||||
CURLM_STATE_DO, /* start send off the request (part 1) */
|
||||
CURLM_STATE_DOING, /* sending off the request (part 1) */
|
||||
CURLM_STATE_DO_MORE, /* send off the request (part 2) */
|
||||
CURLM_STATE_PERFORM, /* transfer data */
|
||||
CURLM_STATE_DONE, /* post data transfer operation */
|
||||
@ -111,6 +115,33 @@ struct Curl_multi {
|
||||
struct curl_hash *hostcache;
|
||||
};
|
||||
|
||||
/* always use this function to change state, to make debugging easier */
|
||||
static void multistate(struct Curl_one_easy *easy, CURLMstate state)
|
||||
{
|
||||
#ifdef CURLDEBUG
|
||||
const char *statename[]={
|
||||
"INIT",
|
||||
"CONNECT",
|
||||
"WAITRESOLVE",
|
||||
"WAITCONNECT",
|
||||
"PROTOCONNECT",
|
||||
"DO",
|
||||
"DOING",
|
||||
"DO_MORE",
|
||||
"PERFORM",
|
||||
"DONE",
|
||||
"COMPLETED",
|
||||
};
|
||||
CURLMstate oldstate = easy->state;
|
||||
#endif
|
||||
easy->state = state;
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
infof(easy->easy_handle,
|
||||
"STATE: %s => %s handle %p: \n",
|
||||
statename[oldstate], statename[easy->state], (char *)easy);
|
||||
#endif
|
||||
}
|
||||
|
||||
CURLM *curl_multi_init(void)
|
||||
{
|
||||
@ -158,7 +189,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
|
||||
/* set the easy handle */
|
||||
easy->easy_handle = easy_handle;
|
||||
easy->state = CURLM_STATE_INIT;
|
||||
multistate(easy, CURLM_STATE_INIT);
|
||||
|
||||
/* for multi interface connections, we share DNS cache automaticly */
|
||||
easy->easy_handle->hostcache = multi->hostcache;
|
||||
@ -258,7 +289,22 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
break;
|
||||
case CURLM_STATE_WAITRESOLVE:
|
||||
/* waiting for a resolve to complete */
|
||||
Curl_fdset(easy->easy_conn, read_fd_set, write_fd_set, &this_max_fd);
|
||||
Curl_resolv_fdset(easy->easy_conn, read_fd_set, write_fd_set,
|
||||
&this_max_fd);
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
break;
|
||||
|
||||
case CURLM_STATE_PROTOCONNECT:
|
||||
Curl_protocol_fdset(easy->easy_conn, read_fd_set, write_fd_set,
|
||||
&this_max_fd);
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
break;
|
||||
|
||||
case CURLM_STATE_DOING:
|
||||
Curl_doing_fdset(easy->easy_conn, read_fd_set, write_fd_set,
|
||||
&this_max_fd);
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
break;
|
||||
@ -318,6 +364,8 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
struct Curl_message *msg = NULL;
|
||||
bool connected;
|
||||
bool async;
|
||||
bool protocol_connect;
|
||||
bool dophase_done;
|
||||
|
||||
*running_handles = 0; /* bump this once for every living handle */
|
||||
|
||||
@ -326,10 +374,6 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy) {
|
||||
#if 0
|
||||
fprintf(stderr, "HANDLE %p: State: %x\n",
|
||||
(char *)easy, easy->state);
|
||||
#endif
|
||||
do {
|
||||
if (CURLM_STATE_WAITCONNECT <= easy->state &&
|
||||
easy->state <= CURLM_STATE_DO &&
|
||||
@ -344,13 +388,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
easy->easy_handle->change.url_changed = FALSE;
|
||||
easy->result = Curl_follow(easy->easy_handle, gotourl, FALSE);
|
||||
if(CURLE_OK == easy->result)
|
||||
easy->state = CURLM_STATE_CONNECT;
|
||||
multistate(easy, CURLM_STATE_CONNECT);
|
||||
else
|
||||
free(gotourl);
|
||||
}
|
||||
else {
|
||||
easy->result = CURLE_OUT_OF_MEMORY;
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
multistate(easy, CURLM_STATE_COMPLETED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -365,7 +409,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
|
||||
if(CURLE_OK == easy->result) {
|
||||
/* after init, go CONNECT */
|
||||
easy->state = CURLM_STATE_CONNECT;
|
||||
multistate(easy, CURLM_STATE_CONNECT);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
|
||||
easy->easy_handle->state.used_interface = Curl_if_multi;
|
||||
@ -376,16 +420,22 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
/* Connect. We get a connection identifier filled in. */
|
||||
Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
|
||||
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
|
||||
&async);
|
||||
&async, &protocol_connect);
|
||||
|
||||
if(CURLE_OK == easy->result) {
|
||||
if(async)
|
||||
/* We're now waiting for an asynchronous name lookup */
|
||||
easy->state = CURLM_STATE_WAITRESOLVE;
|
||||
multistate(easy, CURLM_STATE_WAITRESOLVE);
|
||||
else {
|
||||
/* after the connect has been sent off, go WAITCONNECT */
|
||||
easy->state = CURLM_STATE_WAITCONNECT;
|
||||
/* after the connect has been sent off, go WAITCONNECT unless the
|
||||
protocol connect is already done and we can go directly to
|
||||
DO! */
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
|
||||
if(protocol_connect)
|
||||
multistate(easy, CURLM_STATE_DO);
|
||||
else
|
||||
multistate(easy, CURLM_STATE_WAITCONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -401,14 +451,17 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
if(dns) {
|
||||
/* Perform the next step in the connection phase, and then move on
|
||||
to the WAITCONNECT state */
|
||||
easy->result = Curl_async_resolved(easy->easy_conn);
|
||||
easy->result = Curl_async_resolved(easy->easy_conn,
|
||||
&protocol_connect);
|
||||
|
||||
if(CURLE_OK != easy->result)
|
||||
/* if Curl_async_resolved() returns failure, the connection struct
|
||||
is already freed and gone */
|
||||
easy->easy_conn = NULL; /* no more connection */
|
||||
|
||||
easy->state = CURLM_STATE_WAITCONNECT;
|
||||
else {
|
||||
/* FIX: what if protocol_connect is TRUE here?! */
|
||||
multistate(easy, CURLM_STATE_WAITCONNECT);
|
||||
}
|
||||
}
|
||||
|
||||
if(CURLE_OK != easy->result) {
|
||||
@ -425,7 +478,8 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
easy->result = Curl_is_connected(easy->easy_conn, FIRSTSOCKET,
|
||||
&connected);
|
||||
if(connected)
|
||||
easy->result = Curl_protocol_connect(easy->easy_conn);
|
||||
easy->result = Curl_protocol_connect(easy->easy_conn,
|
||||
&protocol_connect);
|
||||
|
||||
if(CURLE_OK != easy->result) {
|
||||
/* failure detected */
|
||||
@ -435,29 +489,64 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
}
|
||||
|
||||
if(connected) {
|
||||
if(!protocol_connect) {
|
||||
/* We have a TCP connection, but 'protocol_connect' may be false
|
||||
and then we continue to 'STATE_PROTOCONNECT'. If protocol
|
||||
connect is TRUE, we move on to STATE_DO. */
|
||||
multistate(easy, CURLM_STATE_PROTOCONNECT);
|
||||
fprintf(stderr, "WAITCONNECT => PROTOCONNECT\n");
|
||||
}
|
||||
else {
|
||||
/* after the connect has completed, go DO */
|
||||
multistate(easy, CURLM_STATE_DO);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLM_STATE_PROTOCONNECT:
|
||||
/* protocol-specific connect phase */
|
||||
easy->result = Curl_protocol_connecting(easy->easy_conn,
|
||||
&protocol_connect);
|
||||
if(protocol_connect) {
|
||||
/* after the connect has completed, go DO */
|
||||
easy->state = CURLM_STATE_DO;
|
||||
multistate(easy, CURLM_STATE_DO);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
else if(easy->result) {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
Curl_disconnect(easy->easy_conn); /* close the connection */
|
||||
easy->easy_conn = NULL; /* no more connection */
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLM_STATE_DO:
|
||||
/* Do the fetch or put request */
|
||||
easy->result = Curl_do(&easy->easy_conn);
|
||||
/* Perform the protocol's DO action */
|
||||
easy->result = Curl_do(&easy->easy_conn, &dophase_done);
|
||||
|
||||
if(CURLE_OK == easy->result) {
|
||||
|
||||
/* after do, go PERFORM... or DO_MORE */
|
||||
if(easy->easy_conn->bits.do_more) {
|
||||
if(!dophase_done) {
|
||||
/* DO was not completed in one function call, we must continue
|
||||
DOING... */
|
||||
multistate(easy, CURLM_STATE_DOING);
|
||||
result = CURLM_OK;
|
||||
}
|
||||
|
||||
/* after DO, go PERFORM... or DO_MORE */
|
||||
else if(easy->easy_conn->bits.do_more) {
|
||||
/* we're supposed to do more, but we need to sit down, relax
|
||||
and wait a little while first */
|
||||
easy->state = CURLM_STATE_DO_MORE;
|
||||
multistate(easy, CURLM_STATE_DO_MORE);
|
||||
result = CURLM_OK;
|
||||
}
|
||||
else {
|
||||
/* we're done with the DO, now PERFORM */
|
||||
easy->result = Curl_readwrite_init(easy->easy_conn);
|
||||
if(CURLE_OK == easy->result) {
|
||||
easy->state = CURLM_STATE_PERFORM;
|
||||
multistate(easy, CURLM_STATE_PERFORM);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
}
|
||||
@ -471,10 +560,39 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLM_STATE_DOING:
|
||||
/* we continue DOING until the DO phase is complete */
|
||||
easy->result = Curl_protocol_doing(easy->easy_conn, &dophase_done);
|
||||
if(CURLE_OK == easy->result) {
|
||||
if(dophase_done) {
|
||||
/* after DO, go PERFORM... or DO_MORE */
|
||||
if(easy->easy_conn->bits.do_more) {
|
||||
/* we're supposed to do more, but we need to sit down, relax
|
||||
and wait a little while first */
|
||||
multistate(easy, CURLM_STATE_DO_MORE);
|
||||
result = CURLM_OK;
|
||||
}
|
||||
else {
|
||||
/* we're done with the DO, now PERFORM */
|
||||
easy->result = Curl_readwrite_init(easy->easy_conn);
|
||||
if(CURLE_OK == easy->result) {
|
||||
multistate(easy, CURLM_STATE_PERFORM);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
}
|
||||
} /* dophase_done */
|
||||
}
|
||||
else {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
Curl_disconnect(easy->easy_conn); /* close the connection */
|
||||
easy->easy_conn = NULL; /* no more connection */
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLM_STATE_DO_MORE:
|
||||
/*
|
||||
* First, check if we really are ready to do more.
|
||||
*/
|
||||
/* Ready to do more? */
|
||||
easy->result = Curl_is_connected(easy->easy_conn, SECONDARYSOCKET,
|
||||
&connected);
|
||||
if(connected) {
|
||||
@ -487,7 +605,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
easy->result = Curl_readwrite_init(easy->easy_conn);
|
||||
|
||||
if(CURLE_OK == easy->result) {
|
||||
easy->state = CURLM_STATE_PERFORM;
|
||||
multistate(easy, CURLM_STATE_PERFORM);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
}
|
||||
@ -532,7 +650,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
if(easy->result == CURLE_OK)
|
||||
easy->result = Curl_follow(easy->easy_handle, newurl, retry);
|
||||
if(CURLE_OK == easy->result) {
|
||||
easy->state = CURLM_STATE_CONNECT;
|
||||
multistate(easy, CURLM_STATE_CONNECT);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
else
|
||||
@ -542,7 +660,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
}
|
||||
else {
|
||||
/* after the transfer is done, go DONE */
|
||||
easy->state = CURLM_STATE_DONE;
|
||||
multistate(easy, CURLM_STATE_DONE);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
}
|
||||
@ -553,7 +671,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
|
||||
/* after we have DONE what we're supposed to do, go COMPLETED, and
|
||||
it doesn't matter what the Curl_done() returned! */
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
multistate(easy, CURLM_STATE_COMPLETED);
|
||||
break;
|
||||
|
||||
case CURLM_STATE_COMPLETED:
|
||||
@ -571,7 +689,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
/*
|
||||
* If an error was returned, and we aren't in completed state now,
|
||||
* then we go to completed and consider this transfer aborted. */
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
multistate(easy, CURLM_STATE_COMPLETED);
|
||||
}
|
||||
else
|
||||
/* this one still lives! */
|
||||
@ -600,7 +718,6 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
|
||||
multi->num_msgs++; /* increase message counter */
|
||||
}
|
||||
|
||||
easy = easy->next; /* operate on next handle */
|
||||
}
|
||||
|
||||
|
@ -27,5 +27,4 @@
|
||||
* Prototypes for library-wide functions provided by multi.c
|
||||
*/
|
||||
void Curl_multi_rmeasy(void *multi, CURL *data);
|
||||
|
||||
#endif /* __MULTIIF_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -1065,7 +1065,7 @@ CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_telnet(struct connectdata *conn)
|
||||
CURLcode Curl_telnet(struct connectdata *conn, bool *done)
|
||||
{
|
||||
CURLcode code;
|
||||
struct SessionHandle *data = conn->data;
|
||||
@ -1093,6 +1093,8 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
||||
char *buf = data->state.buffer;
|
||||
struct TELNET *tn;
|
||||
|
||||
*done = TRUE; /* uncontionally */
|
||||
|
||||
code = init_telnet(conn);
|
||||
if(code)
|
||||
return code;
|
||||
|
14
lib/telnet.h
14
lib/telnet.h
@ -2,18 +2,18 @@
|
||||
#define __TELNET_H
|
||||
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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.
|
||||
@ -24,7 +24,7 @@
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
#ifndef CURL_DISABLE_TELNET
|
||||
CURLcode Curl_telnet(struct connectdata *conn);
|
||||
CURLcode Curl_telnet(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -2027,9 +2027,11 @@ Curl_connect_host(struct SessionHandle *data,
|
||||
|
||||
do {
|
||||
bool async;
|
||||
bool protocol_done=TRUE; /* will be TRUE always since this is only used
|
||||
within the easy interface */
|
||||
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
||||
data->change.url_changed = FALSE;
|
||||
res = Curl_connect(data, conn, &async);
|
||||
res = Curl_connect(data, conn, &async, &protocol_done);
|
||||
|
||||
if((CURLE_OK == res) && async) {
|
||||
/* Now, if async is TRUE here, we need to wait for the name
|
||||
@ -2037,8 +2039,9 @@ Curl_connect_host(struct SessionHandle *data,
|
||||
res = Curl_wait_for_resolv(*conn, NULL);
|
||||
if(CURLE_OK == res)
|
||||
/* Resolved, continue with the connection */
|
||||
res = Curl_async_resolved(*conn);
|
||||
res = Curl_async_resolved(*conn, &protocol_done);
|
||||
else
|
||||
/* if we can't resolve, we kill this "connection" now */
|
||||
(void)Curl_disconnect(*conn);
|
||||
}
|
||||
if(res)
|
||||
@ -2126,8 +2129,8 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
||||
}
|
||||
|
||||
if(res == CURLE_OK) {
|
||||
|
||||
res = Curl_do(&conn);
|
||||
bool do_done;
|
||||
res = Curl_do(&conn, &do_done);
|
||||
|
||||
/* for non 3rd party transfer only */
|
||||
if(res == CURLE_OK && !data->set.source_url) {
|
||||
|
158
lib/url.c
158
lib/url.c
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -1989,41 +1989,117 @@ static void verboseconnect(struct connectdata *conn)
|
||||
conn->ip_addr_str, conn->port);
|
||||
}
|
||||
|
||||
CURLcode Curl_protocol_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
if(conn->curl_proto_fdset)
|
||||
res = conn->curl_proto_fdset(conn, read_fd_set, write_fd_set, max_fdp);
|
||||
return res;
|
||||
}
|
||||
|
||||
CURLcode Curl_doing_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
if(conn && conn->curl_doing_fdset)
|
||||
res = conn->curl_doing_fdset(conn, read_fd_set, write_fd_set, max_fdp);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are doing protocol-specific connecting and this is being called over and
|
||||
* over from the multi interface until the connection phase is done on
|
||||
* protocol layer.
|
||||
*/
|
||||
|
||||
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
|
||||
if(conn && conn->curl_connecting) {
|
||||
*done = FALSE;
|
||||
result = conn->curl_connecting(conn, done);
|
||||
}
|
||||
else
|
||||
*done = TRUE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are DOING this is being called over and over from the multi interface
|
||||
* until the DOING phase is done on protocol layer.
|
||||
*/
|
||||
|
||||
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
|
||||
if(conn && conn->curl_doing) {
|
||||
*done = FALSE;
|
||||
result = conn->curl_doing(conn, done);
|
||||
}
|
||||
else
|
||||
*done = TRUE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have discovered that the TCP connection has been successful, we can now
|
||||
* proceed with some action.
|
||||
*
|
||||
* If we're using the multi interface, this host address pointer is most
|
||||
* likely NULL at this point as we can't keep the resolved info around. This
|
||||
* may call for some reworking, like a reference counter in the struct or
|
||||
* something.
|
||||
*/
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn)
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *protocol_done)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode result=CURLE_OK;
|
||||
|
||||
if(conn->bits.tcpconnect)
|
||||
*protocol_done = FALSE;
|
||||
|
||||
if(conn->bits.tcpconnect && conn->bits.protoconnstart) {
|
||||
/* We already are connected, get back. This may happen when the connect
|
||||
worked fine in the first call, like when we connect to a local server
|
||||
or proxy. */
|
||||
or proxy. Note that we don't know if the protocol is actually done.
|
||||
|
||||
Unless this protocol doesn't have any protocol-connect callback, as
|
||||
then we know we're done. */
|
||||
if(!conn->curl_connecting)
|
||||
*protocol_done = TRUE;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
||||
if(!conn->bits.tcpconnect) {
|
||||
|
||||
if(data->set.verbose)
|
||||
verboseconnect(conn);
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
||||
|
||||
if(conn->curl_connect) {
|
||||
/* is there a protocol-specific connect() procedure? */
|
||||
if(data->set.verbose)
|
||||
verboseconnect(conn);
|
||||
}
|
||||
|
||||
/* set start time here for timeout purposes in the
|
||||
* connect procedure, it is later set again for the
|
||||
* progress meter purpose */
|
||||
conn->now = Curl_tvnow();
|
||||
if(!conn->bits.protoconnstart) {
|
||||
if(conn->curl_connect) {
|
||||
/* is there a protocol-specific connect() procedure? */
|
||||
|
||||
/* Call the protocol-specific connect function */
|
||||
result = conn->curl_connect(conn);
|
||||
/* Set start time here for timeout purposes in the connect procedure, it
|
||||
is later set again for the progress meter purpose */
|
||||
conn->now = Curl_tvnow();
|
||||
|
||||
/* Call the protocol-specific connect function */
|
||||
result = conn->curl_connect(conn, protocol_done);
|
||||
}
|
||||
else
|
||||
*protocol_done = TRUE;
|
||||
|
||||
/* it has started, possibly even completed but that knowledge isn't stored
|
||||
in this bit! */
|
||||
conn->bits.protoconnstart = TRUE;
|
||||
}
|
||||
|
||||
return result; /* pass back status */
|
||||
@ -2733,6 +2809,10 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
conn->curl_do_more = Curl_ftp_nextconnect;
|
||||
conn->curl_done = Curl_ftp_done;
|
||||
conn->curl_connect = Curl_ftp_connect;
|
||||
conn->curl_connecting = Curl_ftp_multi_statemach;
|
||||
conn->curl_doing = Curl_ftp_doing;
|
||||
conn->curl_proto_fdset = Curl_ftp_fdset;
|
||||
conn->curl_doing_fdset = Curl_ftp_fdset;
|
||||
conn->curl_disconnect = Curl_ftp_disconnect;
|
||||
}
|
||||
|
||||
@ -3385,17 +3465,21 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
*/
|
||||
|
||||
static CURLcode SetupConnection(struct connectdata *conn,
|
||||
struct Curl_dns_entry *hostaddr)
|
||||
struct Curl_dns_entry *hostaddr,
|
||||
bool *protocol_done)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode result=CURLE_OK;
|
||||
|
||||
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
|
||||
|
||||
if(conn->protocol & PROT_FILE)
|
||||
if(conn->protocol & PROT_FILE) {
|
||||
/* There's nothing in this function to setup if we're only doing
|
||||
a file:// transfer */
|
||||
*protocol_done = TRUE;
|
||||
return result;
|
||||
}
|
||||
*protocol_done = FALSE; /* default to not done */
|
||||
|
||||
/*************************************************************
|
||||
* Send user-agent to HTTP proxies even if the target protocol
|
||||
@ -3416,13 +3500,13 @@ static CURLcode SetupConnection(struct connectdata *conn,
|
||||
conn->headerbytecount = 0;
|
||||
|
||||
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
|
||||
bool connected;
|
||||
bool connected = FALSE;
|
||||
|
||||
/* Connect only if not already connected! */
|
||||
result = ConnectPlease(conn, hostaddr, &connected);
|
||||
|
||||
if(connected) {
|
||||
result = Curl_protocol_connect(conn);
|
||||
result = Curl_protocol_connect(conn, protocol_done);
|
||||
if(CURLE_OK == result)
|
||||
conn->bits.tcpconnect = TRUE;
|
||||
}
|
||||
@ -3436,6 +3520,7 @@ static CURLcode SetupConnection(struct connectdata *conn,
|
||||
else {
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
|
||||
conn->bits.tcpconnect = TRUE;
|
||||
*protocol_done = TRUE;
|
||||
if(data->set.verbose)
|
||||
verboseconnect(conn);
|
||||
}
|
||||
@ -3460,7 +3545,8 @@ static CURLcode SetupConnection(struct connectdata *conn,
|
||||
|
||||
CURLcode Curl_connect(struct SessionHandle *data,
|
||||
struct connectdata **in_connect,
|
||||
bool *asyncp)
|
||||
bool *asyncp,
|
||||
bool *protocol_done)
|
||||
{
|
||||
CURLcode code;
|
||||
struct Curl_dns_entry *dns;
|
||||
@ -3476,7 +3562,7 @@ CURLcode Curl_connect(struct SessionHandle *data,
|
||||
/* If an address is available it means that we already have the name
|
||||
resolved, OR it isn't async.
|
||||
If so => continue connecting from here */
|
||||
code = SetupConnection(*in_connect, dns);
|
||||
code = SetupConnection(*in_connect, dns, protocol_done);
|
||||
/* else
|
||||
response will be received and treated async wise */
|
||||
}
|
||||
@ -3494,12 +3580,16 @@ CURLcode Curl_connect(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
/* Call this function after Curl_connect() has returned async=TRUE and
|
||||
then a successful name resolve has been received */
|
||||
CURLcode Curl_async_resolved(struct connectdata *conn)
|
||||
then a successful name resolve has been received.
|
||||
|
||||
Note: this function disconnects and frees the conn data in case of
|
||||
resolve failure */
|
||||
CURLcode Curl_async_resolved(struct connectdata *conn,
|
||||
bool *protocol_done)
|
||||
{
|
||||
#if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME) || \
|
||||
defined(USE_THREADING_GETADDRINFO)
|
||||
CURLcode code = SetupConnection(conn, conn->async.dns);
|
||||
CURLcode code = SetupConnection(conn, conn->async.dns, protocol_done);
|
||||
|
||||
if(code)
|
||||
/* We're not allowed to return failure with memory left allocated
|
||||
@ -3573,7 +3663,7 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_do(struct connectdata **connp)
|
||||
CURLcode Curl_do(struct connectdata **connp, bool *done)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
struct connectdata *conn = *connp;
|
||||
@ -3583,7 +3673,7 @@ CURLcode Curl_do(struct connectdata **connp)
|
||||
|
||||
if(conn->curl_do) {
|
||||
/* generic protocol-specific function pointer set in curl_connect() */
|
||||
result = conn->curl_do(conn);
|
||||
result = conn->curl_do(conn, done);
|
||||
|
||||
/* This was formerly done in transfer.c, but we better do it here */
|
||||
|
||||
@ -3603,8 +3693,10 @@ CURLcode Curl_do(struct connectdata **connp)
|
||||
|
||||
if(CURLE_OK == result) {
|
||||
bool async;
|
||||
bool protocol_done = TRUE;
|
||||
|
||||
/* Now, redo the connect and get a new connection */
|
||||
result = Curl_connect(data, connp, &async);
|
||||
result = Curl_connect(data, connp, &async, &protocol_done);
|
||||
if(CURLE_OK == result) {
|
||||
/* We have connected or sent away a name resolve query fine */
|
||||
|
||||
@ -3617,13 +3709,13 @@ CURLcode Curl_do(struct connectdata **connp)
|
||||
return result;
|
||||
|
||||
/* Resolved, continue with the connection */
|
||||
result = Curl_async_resolved(conn);
|
||||
result = Curl_async_resolved(conn, &protocol_done);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ... finally back to actually retry the DO phase */
|
||||
result = conn->curl_do(conn);
|
||||
result = conn->curl_do(conn, done);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
lib/url.h
21
lib/url.h
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2005, 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
|
||||
@ -31,17 +31,28 @@ CURLcode Curl_open(struct SessionHandle **curl);
|
||||
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...);
|
||||
CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
|
||||
CURLcode Curl_connect(struct SessionHandle *, struct connectdata **,
|
||||
bool *async);
|
||||
CURLcode Curl_async_resolved(struct connectdata *conn);
|
||||
CURLcode Curl_do(struct connectdata **);
|
||||
bool *async, bool *protocol_connect);
|
||||
CURLcode Curl_async_resolved(struct connectdata *conn,
|
||||
bool *protocol_connect);
|
||||
CURLcode Curl_do(struct connectdata **, bool *done);
|
||||
CURLcode Curl_do_more(struct connectdata *);
|
||||
CURLcode Curl_done(struct connectdata **, CURLcode);
|
||||
CURLcode Curl_disconnect(struct connectdata *);
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn);
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
|
||||
bool Curl_ssl_config_matches(struct ssl_config_data* data,
|
||||
struct ssl_config_data* needle);
|
||||
bool Curl_clone_ssl_config(struct ssl_config_data* source,
|
||||
struct ssl_config_data* dest);
|
||||
void Curl_free_ssl_config(struct ssl_config_data* sslc);
|
||||
void Curl_safefree(void *ptr);
|
||||
CURLcode Curl_protocol_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
CURLcode Curl_doing_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
#endif
|
||||
|
@ -243,6 +243,42 @@ struct HTTP {
|
||||
/****************************************************************************
|
||||
* FTP unique setup
|
||||
***************************************************************************/
|
||||
typedef enum {
|
||||
FTP_STOP, /* do nothing state, stops the state machine */
|
||||
FTP_WAIT220, /* waiting for the inintial 220 response immediately after
|
||||
a connect */
|
||||
FTP_AUTH,
|
||||
FTP_USER,
|
||||
FTP_PASS,
|
||||
FTP_ACCT,
|
||||
FTP_PBSZ,
|
||||
FTP_PROT,
|
||||
FTP_PWD,
|
||||
FTP_QUOTE, /* waiting for a response to a command sent in a quote list */
|
||||
FTP_RETR_PREQUOTE,
|
||||
FTP_STOR_PREQUOTE,
|
||||
FTP_POSTQUOTE,
|
||||
FTP_CWD, /* change dir */
|
||||
FTP_MKD, /* if the dir didn't exist */
|
||||
FTP_MDTM, /* to figure out the datestamp */
|
||||
FTP_TYPE, /* to set type when doing a head-like request */
|
||||
FTP_LIST_TYPE, /* set type when about to do a dir list */
|
||||
FTP_RETR_TYPE, /* set type when about to RETR a file */
|
||||
FTP_STOR_TYPE, /* set type when about to STOR a file */
|
||||
FTP_SIZE, /* get the remote file's size for head-like request */
|
||||
FTP_RETR_SIZE, /* get the remote file's size for RETR */
|
||||
FTP_STOR_SIZE, /* get the size for (resumed) STOR */
|
||||
FTP_REST, /* when used to check if the server supports it in head-like */
|
||||
FTP_RETR_REST, /* when asking for "resume" in for RETR */
|
||||
FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */
|
||||
FTP_PASV, /* generic state for PASV and EPSV, check count1 */
|
||||
FTP_LIST, /* generic state for LIST, NLST or a custom list command */
|
||||
FTP_RETR,
|
||||
FTP_STOR, /* generic state for STOR and APPE */
|
||||
FTP_QUIT,
|
||||
FTP_LAST /* never used */
|
||||
} ftpstate;
|
||||
|
||||
struct FTP {
|
||||
curl_off_t *bytecountp;
|
||||
char *user; /* user name string */
|
||||
@ -271,6 +307,18 @@ struct FTP {
|
||||
bool cwddone; /* if it has been determined that the proper CWD combo
|
||||
already has been done */
|
||||
char *prevpath; /* conn->path from the previous transfer */
|
||||
size_t nread_resp; /* number of bytes currently read of a server response */
|
||||
int count1; /* general purpose counter for the state machine */
|
||||
int count2; /* general purpose counter for the state machine */
|
||||
int count3; /* general purpose counter for the state machine */
|
||||
char *sendthis; /* allocated pointer to a buffer that is to be sent to the
|
||||
ftp server */
|
||||
size_t sendleft; /* number of bytes left to send from the sendthis buffer */
|
||||
size_t sendsize; /* total size of the sendthis buffer */
|
||||
struct timeval response; /* set to Curl_tvnow() when a command has been sent
|
||||
off, used to time-out response reading */
|
||||
ftpstate state; /* always use ftp.c:state() to change state! */
|
||||
curl_off_t downloadsize;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -309,9 +357,12 @@ struct ConnectBits {
|
||||
bool forbidchunk; /* used only to explicitly forbid chunk-upload for
|
||||
specific upload buffers. See readmoredata() in
|
||||
http.c for details. */
|
||||
bool tcpconnect; /* the tcp stream (or simimlar) is connected, this
|
||||
is set the first time on the first connect function
|
||||
call */
|
||||
|
||||
bool tcpconnect; /* the TCP layer (or simimlar) is connected, this is set
|
||||
the first time on the first connect function call */
|
||||
bool protoconnstart;/* the protocol layer has STARTED its operation after
|
||||
the TCP layer connect */
|
||||
|
||||
bool retry; /* this connection is about to get closed and then
|
||||
re-attempted at another connection. */
|
||||
bool no_body; /* CURLOPT_NO_BODY (or similar) was set */
|
||||
@ -510,7 +561,7 @@ struct connectdata {
|
||||
|
||||
/* These two functions MUST be set by the curl_connect() function to be
|
||||
be protocol dependent */
|
||||
CURLcode (*curl_do)(struct connectdata *);
|
||||
CURLcode (*curl_do)(struct connectdata *, bool *done);
|
||||
CURLcode (*curl_done)(struct connectdata *, CURLcode);
|
||||
|
||||
/* If the curl_do() function is better made in two halves, this
|
||||
@ -521,8 +572,29 @@ struct connectdata {
|
||||
|
||||
/* This function *MAY* be set to a protocol-dependent function that is run
|
||||
* after the connect() and everything is done, as a step in the connection.
|
||||
* The 'done' pointer points to a bool that should be set to TRUE if the
|
||||
* function completes before return. If it doesn't complete, the caller
|
||||
* should call the curl_connecting() function until it is.
|
||||
*/
|
||||
CURLcode (*curl_connect)(struct connectdata *);
|
||||
CURLcode (*curl_connect)(struct connectdata *, bool *done);
|
||||
|
||||
/* See above. Currently only used for FTP. */
|
||||
CURLcode (*curl_connecting)(struct connectdata *, bool *done);
|
||||
CURLcode (*curl_doing)(struct connectdata *, bool *done);
|
||||
|
||||
/* Called from the multi interface during the PROTOCONNECT phase, and it
|
||||
should then return a proper fd set */
|
||||
CURLcode (*curl_proto_fdset)(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
|
||||
/* Called from the multi interface during the DOING phase, and it should
|
||||
then return a proper fd set */
|
||||
CURLcode (*curl_doing_fdset)(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
|
||||
/* This function *MAY* be set to a protocol-dependent function that is run
|
||||
* by the curl_disconnect(), as a step in the disconnection.
|
||||
|
@ -21,7 +21,6 @@
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
/* This is now designed to have its own local setup.h */
|
||||
#include "setup.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@ -3726,7 +3725,8 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
} /* if CURLE_OK */
|
||||
else if(CURLE_FTP_USER_PASSWORD_INCORRECT == res) {
|
||||
else if((CURLE_FTP_USER_PASSWORD_INCORRECT == res) ||
|
||||
(CURLE_LOGIN_DENIED == res)) {
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
|
||||
if(response/100 == 5)
|
||||
|
@ -21,7 +21,7 @@ REPLY USER 314 bluah you fewl!
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<errorcode>
|
||||
12
|
||||
67
|
||||
</errorcode>
|
||||
<protocol>
|
||||
USER anonymous
|
||||
|
@ -21,7 +21,7 @@ REPLY PASS 314 bluah you f00l!
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<errorcode>
|
||||
11
|
||||
67
|
||||
</errorcode>
|
||||
<protocol>
|
||||
USER anonymous
|
||||
|
@ -15,7 +15,7 @@ ftp
|
||||
FTP download with strict timeout and slow CWD
|
||||
</name>
|
||||
<command>
|
||||
ftp://%HOSTIP:%FTPPORT/path/to/file/126 -m 3
|
||||
ftp://%HOSTIP:%FTPPORT/path/to/file/190 -m 3
|
||||
</command>
|
||||
<file name="log/ftpserver.cmd">
|
||||
DELAY CWD 15
|
||||
@ -24,6 +24,7 @@ DELAY CWD 15
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
# 28 is CURLE_OPERATION_TIMEOUTED
|
||||
<errorcode>
|
||||
28
|
||||
</errorcode>
|
||||
|
@ -21,7 +21,7 @@ REPLY PASS 530 temporarily not available
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<errorcode>
|
||||
10
|
||||
67
|
||||
</errorcode>
|
||||
<protocol>
|
||||
USER anonymous
|
||||
|
@ -20,8 +20,9 @@ REPLY PASS 530 temporarily not available
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
# 67 is CURLE_LOGIN_DENIED
|
||||
<errorcode>
|
||||
10
|
||||
67
|
||||
</errorcode>
|
||||
<protocol>
|
||||
USER anonymous
|
||||
|
@ -9,7 +9,6 @@ int test(char *URL)
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user