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:
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
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* 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
|
||||
@@ -1404,12 +1281,7 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
|
||||
if(state->state == TFTP_STATE_FIN || result != CURLE_OK)
|
||||
return(result);
|
||||
|
||||
if(conn->data->state.used_interface == Curl_if_multi)
|
||||
tftp_multi_statemach(conn, dophase_done);
|
||||
else {
|
||||
result = tftp_easy_statemach(conn);
|
||||
*dophase_done = TRUE; /* with the easy interface we are done here */
|
||||
}
|
||||
tftp_multi_statemach(conn, dophase_done);
|
||||
|
||||
if(*dophase_done)
|
||||
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
||||
|
||||
Reference in New Issue
Block a user