5
5
* | (__| |_| | _ <| |___
6
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
8
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
10
10
* This software is licensed as described in the file COPYING, which
11
11
* you should have received as part of this distribution. The terms
110
103
/* Local API functions */
111
static void state(struct connectdata *conn,
105
static void _state(struct connectdata *conn,
107
#define state(x,y) _state(x,y)
109
static void _state(struct connectdata *conn,
112
#define state(x,y) _state(x,y,__LINE__)
113
115
static CURLcode ftp_sendquote(struct connectdata *conn,
114
116
struct curl_slist *quote);
115
117
static CURLcode ftp_quit(struct connectdata *conn);
418
422
* connection for a negative response regarding a failure in connecting
421
static CURLcode ReceivedServerConnect(struct connectdata* conn, bool* received)
425
static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
423
427
struct SessionHandle *data = conn->data;
424
428
curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
522
526
/* FTP download: */
523
527
Curl_setup_transfer(conn, SECONDARYSOCKET,
524
conn->proto.ftpc.retr_size_saved, FALSE,
525
ftp->bytecountp, -1, NULL); /* no upload here */
528
conn->proto.ftpc.retr_size_saved, FALSE,
529
ftp->bytecountp, -1, NULL); /* no upload here */
528
532
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
536
540
* AllowServerConnect()
538
* When we've issue the PORT command, we have told the server to connect
539
* to us. This function
540
* - will sit and wait here until the server has connected for easy interface
541
* - will check whether data connection is established if so it is accepted
542
* for multi interface
542
* When we've issue the PORT command, we have told the server to connect to
543
* us. This function checks whether data connection is established if so it is
545
547
static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
547
549
struct SessionHandle *data = conn->data;
550
551
CURLcode ret = CURLE_OK;
552
553
*connected = FALSE;
555
556
/* Save the time we start accepting server connect */
556
557
Curl_pgrsTime(data, TIMER_STARTACCEPT);
559
timeout_ms = ftp_timeleft_accept(data);
561
/* if a timeout was already reached, bail out */
562
failf(data, "Accept timeout occurred while waiting server connect");
563
return CURLE_FTP_ACCEPT_TIMEOUT;
566
/* see if the connection request is already here */
567
ret = ReceivedServerConnect(conn, connected);
572
ret = AcceptServerConnect(conn);
576
ret = InitiateTransfer(conn);
580
break; /* connection is accepted, break the loop */
583
if(data->state.used_interface == Curl_if_easy) {
585
if(timeout_ms < interval_ms)
586
interval_ms = timeout_ms;
588
/* sleep for 1 second and then continue */
589
Curl_socket_ready(CURL_SOCKET_BAD, CURL_SOCKET_BAD, interval_ms);
592
/* Add timeout to multi handle and break out of the loop */
593
if(ret == CURLE_OK && *connected == FALSE) {
594
if(data->set.accepttimeout > 0)
595
Curl_expire(data, data->set.accepttimeout);
597
Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
600
break; /* connection was not accepted immediately */
559
timeout_ms = ftp_timeleft_accept(data);
561
/* if a timeout was already reached, bail out */
562
failf(data, "Accept timeout occurred while waiting server connect");
563
return CURLE_FTP_ACCEPT_TIMEOUT;
566
/* see if the connection request is already here */
567
ret = ReceivedServerConnect(conn, connected);
572
ret = AcceptServerConnect(conn);
576
ret = InitiateTransfer(conn);
581
/* Add timeout to multi handle and break out of the loop */
582
if(ret == CURLE_OK && *connected == FALSE) {
583
if(data->set.accepttimeout > 0)
584
Curl_expire(data, data->set.accepttimeout);
586
Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
632
617
size_t *size) /* size of the response */
634
619
struct connectdata *conn = pp->conn;
620
struct SessionHandle *data = conn->data;
635
621
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
636
struct SessionHandle *data = conn->data;
637
622
char * const buf = data->state.buffer;
639
624
CURLcode result = CURLE_OK;
663
648
/* store the latest code for later retrieval */
664
conn->data->info.httpcode=code;
649
data->info.httpcode=code;
670
655
/* 421 means "Service not available, closing control connection." and FTP
671
656
* servers use it to signal that idle session timeout has been exceeded.
672
* If we ignored the response, it could end up hanging in some cases. */
657
* If we ignored the response, it could end up hanging in some cases.
659
* This response code can come at any point so having it treated
660
* generically is a good idea.
662
infof(data, "We got a 421 - timeout!\n");
663
state(conn, FTP_STOP);
673
664
return CURLE_OPERATION_TIMEDOUT;
789
781
/* This is the ONLY way to change FTP state! */
790
static void state(struct connectdata *conn,
782
static void _state(struct connectdata *conn,
793
789
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
794
790
/* for debug purposes */
833
829
struct ftp_conn *ftpc = &conn->proto.ftpc;
834
830
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
835
831
if(ftpc->state != newstate)
836
infof(conn->data, "FTP %p state change from %s to %s\n",
837
ftpc, names[ftpc->state], names[newstate]);
832
infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
833
ftpc, lineno, names[ftpc->state], names[newstate]);
839
835
ftpc->state = newstate;
1792
/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
1794
static CURLcode ftp_epsv_disable(struct connectdata *conn)
1796
CURLcode result = CURLE_OK;
1797
infof(conn->data, "got positive EPSV response, but can't connect. "
1798
"Disabling EPSV\n");
1799
/* disable it for next transfer */
1800
conn->bits.ftp_use_epsv = FALSE;
1801
conn->data->state.errorbuf = FALSE; /* allow error message to get
1803
PPSENDF(&conn->proto.ftpc.pp, "PASV", NULL);
1804
conn->proto.ftpc.count1++;
1805
/* remain in the FTP_PASV state */
1796
1809
static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
1976
1993
Curl_resolv_unlock(data, addr); /* we're done using this address */
1978
if(result && ftpc->count1 == 0 && ftpcode == 229) {
1979
infof(data, "got positive EPSV response, but can't connect. "
1980
"Disabling EPSV\n");
1981
/* disable it for next transfer */
1982
conn->bits.ftp_use_epsv = FALSE;
1983
data->state.errorbuf = FALSE; /* allow error message to get rewritten */
1984
PPSENDF(&ftpc->pp, "PASV", NULL);
1986
/* remain in the FTP_PASV state */
1996
if(ftpc->count1 == 0 && ftpcode == 229)
1997
return ftp_epsv_disable(conn);
1993
2002
conn->bits.tcpconnect[SECONDARYSOCKET] = connected;
2071
if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
2072
/* the CONNECT procedure is not complete, the tunnel is not yet up */
2073
state(conn, FTP_STOP); /* this phase is completed */
2074
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
2060
2080
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
2082
conn->bits.do_more = TRUE;
2062
2083
state(conn, FTP_STOP); /* this phase is completed */
2411
2434
if(!connected) {
2412
2435
struct ftp_conn *ftpc = &conn->proto.ftpc;
2413
2436
infof(data, "Data conn was not available immediately\n");
2414
/* as there's not necessarily an immediate action on the control
2415
connection now, we halt the state machine */
2416
state(conn, FTP_STOP);
2417
2437
ftpc->wait_data_conn = TRUE;
3227
3246
state(conn, FTP_WAIT220);
3229
if(data->state.used_interface == Curl_if_multi)
3230
result = ftp_multi_statemach(conn, done);
3232
result = ftp_easy_statemach(conn);
3248
result = ftp_multi_statemach(conn, done);
3663
3676
/* the ftp struct is inited in ftp_connect() */
3664
3677
struct FTP *ftp = data->state.proto.ftp;
3666
3681
/* if the second connection isn't done yet, wait for it */
3667
3682
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
3683
if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
3684
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
3685
aren't used so we blank their arguments. TODO: make this nicer */
3686
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
3668
3691
result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
3670
3693
/* Ready to do more? */
3702
/* already in a state so skip the intial commands.
3703
They are only done to kickstart the do_more state */
3704
result = ftp_multi_statemach(conn, complete);
3706
/* if we got an error or if we don't wait for a data connection return
3708
if(result || (ftpc->wait_data_conn != TRUE))
3711
if(ftpc->wait_data_conn)
3712
/* if we reach the end of the FTP state machine here, *complete will be
3713
TRUE but so is ftpc->wait_data_conn, which says we need to wait for
3714
the data connection and therefore we're not actually complete */
3678
3718
if(ftp->transfer <= FTPTRANSFER_INFO) {
3679
3719
/* a transfer is about to take place, or if not a file name was given
3680
3720
so we'll do a SIZE on it later and then we need the right TYPE first */
3782
3825
/* run the state-machine */
3783
if(conn->data->state.used_interface == Curl_if_multi)
3784
result = ftp_multi_statemach(conn, dophase_done);
3786
result = ftp_easy_statemach(conn);
3787
*dophase_done = TRUE; /* with the easy interface we are done here */
3826
result = ftp_multi_statemach(conn, dophase_done);
3789
3828
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
3791
3830
if(*dophase_done)
3792
DEBUGF(infof(conn->data, "DO phase is complete\n"));
3831
DEBUGF(infof(conn->data, "DO phase is complete1\n"));
4402
4441
static CURLcode ftp_dophase_done(struct connectdata *conn,
4403
4442
bool connected)
4405
CURLcode result = CURLE_OK;
4406
4444
struct FTP *ftp = conn->data->state.proto.ftp;
4407
4445
struct ftp_conn *ftpc = &conn->proto.ftpc;
4409
4447
if(connected) {
4410
4448
bool completed;
4411
result = ftp_do_more(conn, &completed);
4449
CURLcode result = ftp_do_more(conn, &completed);
4414
if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) {
4415
/* Failure detected, close the second socket if it was created already */
4416
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
4417
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
4452
if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
4453
/* close the second socket if it was created already */
4454
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
4455
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
4421
4461
if(ftp->transfer != FTPTRANSFER_BODY)