Added BoringSSL - replacement for OpenSSL, updated libcurl to use boringssl
This commit is contained in:
@@ -5,11 +5,11 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2015, 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.
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
@@ -20,30 +20,16 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_TFTP
|
||||
/* -- WIN32 approved -- */
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
@@ -58,8 +44,6 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
#include "urldata.h"
|
||||
#include <curl/curl.h>
|
||||
#include "transfer.h"
|
||||
@@ -72,14 +56,12 @@
|
||||
#include "multiif.h"
|
||||
#include "url.h"
|
||||
#include "rawstr.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#include "curl_memory.h"
|
||||
#include "speedcheck.h"
|
||||
#include "curl_printf.h"
|
||||
#include "select.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/* RFC2348 allows the block size to be negotiated */
|
||||
@@ -163,10 +145,11 @@ typedef struct tftp_state_data {
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
|
||||
static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
|
||||
static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event);
|
||||
static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event);
|
||||
static CURLcode tftp_connect(struct connectdata *conn, bool *done);
|
||||
static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection);
|
||||
static CURLcode tftp_disconnect(struct connectdata *conn,
|
||||
bool dead_connection);
|
||||
static CURLcode tftp_do(struct connectdata *conn, bool *done);
|
||||
static CURLcode tftp_done(struct connectdata *conn,
|
||||
CURLcode, bool premature);
|
||||
@@ -193,10 +176,13 @@ const struct Curl_handler Curl_handler_tftp = {
|
||||
tftp_doing, /* doing */
|
||||
tftp_getsock, /* proto_getsock */
|
||||
tftp_getsock, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
ZERO_NULL, /* perform_getsock */
|
||||
tftp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
PORT_TFTP, /* defport */
|
||||
PROT_TFTP /* protocol */
|
||||
CURLPROTO_TFTP, /* protocol */
|
||||
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
|
||||
};
|
||||
|
||||
/**********************************************************
|
||||
@@ -213,12 +199,12 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
|
||||
{
|
||||
time_t maxtime, timeout;
|
||||
long timeout_ms;
|
||||
bool start = (bool)(state->state == TFTP_STATE_START);
|
||||
bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
|
||||
|
||||
time(&state->start_time);
|
||||
|
||||
/* Compute drop-dead time */
|
||||
timeout_ms = Curl_timeleft(state->conn, NULL, start);
|
||||
timeout_ms = Curl_timeleft(state->conn->data, NULL, start);
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* time-out, bail out, go home */
|
||||
@@ -232,7 +218,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
|
||||
state->max_time = state->start_time+maxtime;
|
||||
|
||||
/* Set per-block timeout to total */
|
||||
timeout = maxtime ;
|
||||
timeout = maxtime;
|
||||
|
||||
/* Average restart after 5 seconds */
|
||||
state->retry_max = (int)timeout/5;
|
||||
@@ -255,11 +241,11 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
|
||||
|
||||
state->max_time = state->start_time+maxtime;
|
||||
|
||||
/* Set per-block timeout to 10% of total */
|
||||
timeout = maxtime/10 ;
|
||||
/* Set per-block timeout to total */
|
||||
timeout = maxtime;
|
||||
|
||||
/* Average reposting an ACK after 15 seconds */
|
||||
state->retry_max = (int)timeout/15;
|
||||
/* Average reposting an ACK after 5 seconds */
|
||||
state->retry_max = (int)timeout/5;
|
||||
}
|
||||
/* But bound the total number */
|
||||
if(state->retry_max<3)
|
||||
@@ -329,14 +315,14 @@ static const char *tftp_option_get(const char *buf, size_t len,
|
||||
loc = Curl_strnlen( buf, len );
|
||||
loc++; /* NULL term */
|
||||
|
||||
if (loc >= len)
|
||||
if(loc >= len)
|
||||
return NULL;
|
||||
*option = buf;
|
||||
|
||||
loc += Curl_strnlen( buf+loc, len-loc );
|
||||
loc++; /* NULL term */
|
||||
|
||||
if (loc > len)
|
||||
if(loc > len)
|
||||
return NULL;
|
||||
*value = &buf[strlen(*option) + 1];
|
||||
|
||||
@@ -352,7 +338,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
/* if OACK doesn't contain blksize option, the default (512) must be used */
|
||||
state->blksize = TFTP_BLKSIZE_DEFAULT;
|
||||
|
||||
while (tmp < ptr + len) {
|
||||
while(tmp < ptr + len) {
|
||||
const char *option, *value;
|
||||
|
||||
tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value);
|
||||
@@ -382,7 +368,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
TFTP_BLKSIZE_MIN);
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
else if (blksize > state->requested_blksize) {
|
||||
else if(blksize > state->requested_blksize) {
|
||||
/* could realloc pkt buffers here, but the spec doesn't call out
|
||||
* support for the server requesting a bigger blksize than the client
|
||||
* requests */
|
||||
@@ -403,7 +389,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
|
||||
/* tsize should be ignored on upload: Who cares about the size of the
|
||||
remote file? */
|
||||
if (!data->set.upload) {
|
||||
if(!data->set.upload) {
|
||||
if(!tsize) {
|
||||
failf(data, "invalid tsize -:%s:- value in OACK packet", value);
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
@@ -419,41 +405,41 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
|
||||
char *buf, const char *option)
|
||||
{
|
||||
if( ( strlen(option) + csize + 1 ) > (size_t)state->blksize )
|
||||
if(( strlen(option) + csize + 1 ) > (size_t)state->blksize)
|
||||
return 0;
|
||||
strcpy(buf, option);
|
||||
return( strlen(option) + 1 );
|
||||
return strlen(option) + 1;
|
||||
}
|
||||
|
||||
static CURLcode tftp_connect_for_tx(tftp_state_data_t *state,
|
||||
tftp_event_t event)
|
||||
{
|
||||
CURLcode res;
|
||||
CURLcode result;
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
|
||||
infof(data, "%s\n", "Connected for transmit");
|
||||
#endif
|
||||
state->state = TFTP_STATE_TX;
|
||||
res = tftp_set_timeouts(state);
|
||||
if(res != CURLE_OK)
|
||||
return(res);
|
||||
result = tftp_set_timeouts(state);
|
||||
if(result)
|
||||
return result;
|
||||
return tftp_tx(state, event);
|
||||
}
|
||||
|
||||
static CURLcode tftp_connect_for_rx(tftp_state_data_t *state,
|
||||
tftp_event_t event)
|
||||
{
|
||||
CURLcode res;
|
||||
CURLcode result;
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
|
||||
infof(data, "%s\n", "Connected for receive");
|
||||
#endif
|
||||
state->state = TFTP_STATE_RX;
|
||||
res = tftp_set_timeouts(state);
|
||||
if(res != CURLE_OK)
|
||||
return(res);
|
||||
result = tftp_set_timeouts(state);
|
||||
if(result)
|
||||
return result;
|
||||
return tftp_rx(state, event);
|
||||
}
|
||||
|
||||
@@ -465,7 +451,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
char *filename;
|
||||
char buf[64];
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
CURLcode res = CURLE_OK;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* Set ascii mode if -B flag was used */
|
||||
if(data->set.prefer_ascii)
|
||||
@@ -480,7 +466,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
if(state->retries>state->retry_max) {
|
||||
state->error = TFTP_ERR_NORESPONSE;
|
||||
state->state = TFTP_STATE_FIN;
|
||||
return res;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(data->set.upload) {
|
||||
@@ -488,8 +474,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
|
||||
state->conn->data->req.upload_fromhere =
|
||||
(char *)state->spacket.data+4;
|
||||
if(data->set.infilesize != -1)
|
||||
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||
if(data->state.infilesize != -1)
|
||||
Curl_pgrsSetUploadSize(data, data->state.infilesize);
|
||||
}
|
||||
else {
|
||||
/* If we are downloading, send an RRQ */
|
||||
@@ -508,32 +494,36 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
"%s%c%s%c", filename, '\0', mode, '\0');
|
||||
sbytes = 4 + strlen(filename) + strlen(mode);
|
||||
|
||||
/* add tsize option */
|
||||
if(data->set.upload && (data->set.infilesize != -1))
|
||||
snprintf( buf, sizeof(buf), "%" FORMAT_OFF_T, data->set.infilesize );
|
||||
else
|
||||
strcpy(buf, "0"); /* the destination is large enough */
|
||||
/* optional addition of TFTP options */
|
||||
if(!data->set.tftp_no_options) {
|
||||
/* add tsize option */
|
||||
if(data->set.upload && (data->state.infilesize != -1))
|
||||
snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
|
||||
data->state.infilesize);
|
||||
else
|
||||
strcpy(buf, "0"); /* the destination is large enough */
|
||||
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_TSIZE);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf);
|
||||
/* add blksize option */
|
||||
snprintf( buf, sizeof(buf), "%d", state->requested_blksize );
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_BLKSIZE);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_TSIZE);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf);
|
||||
/* add blksize option */
|
||||
snprintf(buf, sizeof(buf), "%d", state->requested_blksize);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_BLKSIZE);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
|
||||
/* add timeout option */
|
||||
snprintf( buf, sizeof(buf), "%d", state->retry_time);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_INTERVAL);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
/* add timeout option */
|
||||
snprintf(buf, sizeof(buf), "%d", state->retry_time);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_INTERVAL);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
}
|
||||
|
||||
/* the typecase for the 3rd argument is mostly for systems that do
|
||||
not have a size_t argument, like older unixes that want an 'int' */
|
||||
@@ -544,24 +534,24 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
if(senddata != (ssize_t)sbytes) {
|
||||
failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
|
||||
}
|
||||
Curl_safefree(filename);
|
||||
free(filename);
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_OACK:
|
||||
if(data->set.upload) {
|
||||
res = tftp_connect_for_tx(state, event);
|
||||
result = tftp_connect_for_tx(state, event);
|
||||
}
|
||||
else {
|
||||
res = tftp_connect_for_rx(state, event);
|
||||
result = tftp_connect_for_rx(state, event);
|
||||
}
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_ACK: /* Connected for transmit */
|
||||
res = tftp_connect_for_tx(state, event);
|
||||
result = tftp_connect_for_tx(state, event);
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_DATA: /* Connected for receive */
|
||||
res = tftp_connect_for_rx(state, event);
|
||||
result = tftp_connect_for_rx(state, event);
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_ERROR:
|
||||
@@ -572,7 +562,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
failf(state->conn->data, "tftp_send_first: internal error");
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
|
||||
@@ -597,21 +588,25 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||
case TFTP_EVENT_DATA:
|
||||
/* Is this the block we expect? */
|
||||
rblock = getrpacketblock(&state->rpacket);
|
||||
if(NEXT_BLOCKNUM(state->block) != rblock) {
|
||||
/* No, log it, up the retry count and fail if over the limit */
|
||||
if(NEXT_BLOCKNUM(state->block) == rblock) {
|
||||
/* This is the expected block. Reset counters and ACK it. */
|
||||
state->retries = 0;
|
||||
}
|
||||
else if(state->block == rblock) {
|
||||
/* This is the last recently received block again. Log it and ACK it
|
||||
again. */
|
||||
infof(data, "Received last DATA packet block %d again.\n", rblock);
|
||||
}
|
||||
else {
|
||||
/* totally unexpected, just log it */
|
||||
infof(data,
|
||||
"Received unexpected DATA packet block %d\n", rblock);
|
||||
state->retries++;
|
||||
if(state->retries > state->retry_max) {
|
||||
failf(data, "tftp_rx: giving up waiting for block %d",
|
||||
NEXT_BLOCKNUM(state->block));
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
"Received unexpected DATA packet block %d, expecting block %d\n",
|
||||
rblock, NEXT_BLOCKNUM(state->block));
|
||||
break;
|
||||
}
|
||||
/* This is the expected block. Reset counters and ACK it. */
|
||||
|
||||
/* ACK this block. */
|
||||
state->block = (unsigned short)rblock;
|
||||
state->retries = 0;
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_ACK);
|
||||
setpacketblock(&state->spacket, state->block);
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
@@ -624,7 +619,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||
}
|
||||
|
||||
/* Check if completed (That is, a less than full packet is received) */
|
||||
if(state->rbytes < (ssize_t)state->blksize+4){
|
||||
if(state->rbytes < (ssize_t)state->blksize+4) {
|
||||
state->state = TFTP_STATE_FIN;
|
||||
}
|
||||
else {
|
||||
@@ -708,14 +703,14 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
ssize_t sbytes;
|
||||
int rblock;
|
||||
CURLcode res = CURLE_OK;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SingleRequest *k = &data->req;
|
||||
|
||||
switch(event) {
|
||||
|
||||
case TFTP_EVENT_ACK:
|
||||
case TFTP_EVENT_OACK:
|
||||
if (event == TFTP_EVENT_ACK) {
|
||||
if(event == TFTP_EVENT_ACK) {
|
||||
/* Ack the packet */
|
||||
rblock = getrpacketblock(&state->rpacket);
|
||||
|
||||
@@ -734,21 +729,22 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
if(state->retries>state->retry_max) {
|
||||
failf(data, "tftp_tx: giving up waiting for block %d ack",
|
||||
state->block);
|
||||
res = CURLE_SEND_ERROR;
|
||||
result = CURLE_SEND_ERROR;
|
||||
}
|
||||
else {
|
||||
/* Re-send the data packet */
|
||||
sbytes = sendto(state->sockfd, (void *)&state->spacket.data,
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
4+state->sbytes, SEND_4TH_ARG,
|
||||
(struct sockaddr *)&state->remote_addr,
|
||||
state->remote_addrlen);
|
||||
/* Check all sbytes were sent */
|
||||
if(sbytes<0) {
|
||||
failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
|
||||
res = CURLE_SEND_ERROR;
|
||||
result = CURLE_SEND_ERROR;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
return result;
|
||||
}
|
||||
/* This is the expected packet. Reset the counters and send the next
|
||||
block */
|
||||
@@ -765,11 +761,13 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
state->state = TFTP_STATE_FIN;
|
||||
return CURLE_OK;
|
||||
}
|
||||
res = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes);
|
||||
if(res)
|
||||
return res;
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
4+state->sbytes, SEND_4TH_ARG,
|
||||
|
||||
result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
sbytes = sendto(state->sockfd, (void *) state->spacket.data,
|
||||
4 + state->sbytes, SEND_4TH_ARG,
|
||||
(struct sockaddr *)&state->remote_addr,
|
||||
state->remote_addrlen);
|
||||
/* Check all sbytes were sent */
|
||||
@@ -825,7 +823,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
@@ -837,48 +835,47 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
**********************************************************/
|
||||
static CURLcode tftp_translate_code(tftp_error_t error)
|
||||
{
|
||||
CURLcode code = CURLE_OK;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(error != TFTP_ERR_NONE) {
|
||||
switch(error) {
|
||||
case TFTP_ERR_NOTFOUND:
|
||||
code = CURLE_TFTP_NOTFOUND;
|
||||
result = CURLE_TFTP_NOTFOUND;
|
||||
break;
|
||||
case TFTP_ERR_PERM:
|
||||
code = CURLE_TFTP_PERM;
|
||||
result = CURLE_TFTP_PERM;
|
||||
break;
|
||||
case TFTP_ERR_DISKFULL:
|
||||
code = CURLE_REMOTE_DISK_FULL;
|
||||
result = CURLE_REMOTE_DISK_FULL;
|
||||
break;
|
||||
case TFTP_ERR_UNDEF:
|
||||
case TFTP_ERR_ILLEGAL:
|
||||
code = CURLE_TFTP_ILLEGAL;
|
||||
result = CURLE_TFTP_ILLEGAL;
|
||||
break;
|
||||
case TFTP_ERR_UNKNOWNID:
|
||||
code = CURLE_TFTP_UNKNOWNID;
|
||||
result = CURLE_TFTP_UNKNOWNID;
|
||||
break;
|
||||
case TFTP_ERR_EXISTS:
|
||||
code = CURLE_REMOTE_FILE_EXISTS;
|
||||
result = CURLE_REMOTE_FILE_EXISTS;
|
||||
break;
|
||||
case TFTP_ERR_NOSUCHUSER:
|
||||
code = CURLE_TFTP_NOSUCHUSER;
|
||||
result = CURLE_TFTP_NOSUCHUSER;
|
||||
break;
|
||||
case TFTP_ERR_TIMEOUT:
|
||||
code = CURLE_OPERATION_TIMEDOUT;
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
break;
|
||||
case TFTP_ERR_NORESPONSE:
|
||||
code = CURLE_COULDNT_CONNECT;
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
break;
|
||||
default:
|
||||
code= CURLE_ABORTED_BY_CALLBACK;
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
code = CURLE_OK;
|
||||
}
|
||||
else
|
||||
result = CURLE_OK;
|
||||
|
||||
return(code);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
@@ -891,20 +888,21 @@ static CURLcode tftp_translate_code(tftp_error_t error)
|
||||
static CURLcode tftp_state_machine(tftp_state_data_t *state,
|
||||
tftp_event_t event)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
|
||||
switch(state->state) {
|
||||
case TFTP_STATE_START:
|
||||
DEBUGF(infof(data, "TFTP_STATE_START\n"));
|
||||
res = tftp_send_first(state, event);
|
||||
result = tftp_send_first(state, event);
|
||||
break;
|
||||
case TFTP_STATE_RX:
|
||||
DEBUGF(infof(data, "TFTP_STATE_RX\n"));
|
||||
res = tftp_rx(state, event);
|
||||
result = tftp_rx(state, event);
|
||||
break;
|
||||
case TFTP_STATE_TX:
|
||||
DEBUGF(infof(data, "TFTP_STATE_TX\n"));
|
||||
res = tftp_tx(state, event);
|
||||
result = tftp_tx(state, event);
|
||||
break;
|
||||
case TFTP_STATE_FIN:
|
||||
infof(data, "%s\n", "TFTP finished");
|
||||
@@ -912,10 +910,11 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state,
|
||||
default:
|
||||
DEBUGF(infof(data, "STATE: %d\n", state->state));
|
||||
failf(data, "%s", "Internal state machine error");
|
||||
res = CURLE_TFTP_ILLEGAL;
|
||||
result = CURLE_TFTP_ILLEGAL;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
@@ -949,16 +948,11 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
**********************************************************/
|
||||
static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
CURLcode code;
|
||||
tftp_state_data_t *state;
|
||||
int blksize, rc;
|
||||
|
||||
blksize = TFTP_BLKSIZE_DEFAULT;
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
|
||||
if(!state)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@@ -984,9 +978,9 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
conn->bits.close = TRUE; /* we don't keep TFTP connections up bascially
|
||||
because there's none or very little gain for UDP
|
||||
*/
|
||||
/* we don't keep TFTP connections up basically because there's none or very
|
||||
* little gain for UDP */
|
||||
connclose(conn, "TFTP");
|
||||
|
||||
state->conn = conn;
|
||||
state->sockfd = state->conn->sock[FIRSTSOCKET];
|
||||
@@ -1027,8 +1021,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
Curl_pgrsStartNow(conn->data);
|
||||
|
||||
*done = TRUE;
|
||||
code = CURLE_OK;
|
||||
return(code);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
@@ -1041,18 +1035,20 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
|
||||
bool premature)
|
||||
{
|
||||
CURLcode code = CURLE_OK;
|
||||
CURLcode result = CURLE_OK;
|
||||
tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
|
||||
|
||||
(void)status; /* unused */
|
||||
(void)premature; /* not used */
|
||||
|
||||
Curl_pgrsDone(conn);
|
||||
if(Curl_pgrsDone(conn))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
|
||||
/* If we have encountered an error */
|
||||
code = tftp_translate_code(state->error);
|
||||
if(state)
|
||||
result = tftp_translate_code(state->error);
|
||||
|
||||
return code;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
@@ -1169,7 +1165,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
|
||||
time_t current;
|
||||
tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
|
||||
|
||||
if (event)
|
||||
if(event)
|
||||
*event = TFTP_EVENT_NONE;
|
||||
|
||||
time(¤t);
|
||||
@@ -1180,8 +1176,8 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
|
||||
state->state = TFTP_STATE_FIN;
|
||||
return 0;
|
||||
}
|
||||
else if (current > state->rx_time+state->retry_time) {
|
||||
if (event)
|
||||
else if(current > state->rx_time+state->retry_time) {
|
||||
if(event)
|
||||
*event = TFTP_EVENT_TIMEOUT;
|
||||
time(&state->rx_time); /* update even though we received nothing */
|
||||
}
|
||||
@@ -1192,130 +1188,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, (int)(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 occured, 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
|
||||
@@ -1338,11 +1210,11 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
|
||||
failf(data, "TFTP response timeout");
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
else if (event != TFTP_EVENT_NONE) {
|
||||
else if(event != TFTP_EVENT_NONE) {
|
||||
result = tftp_state_machine(state, event);
|
||||
if(result != CURLE_OK)
|
||||
return(result);
|
||||
*done = (bool)(state->state == TFTP_STATE_FIN);
|
||||
if(result)
|
||||
return result;
|
||||
*done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
|
||||
if(*done)
|
||||
/* Tell curl we're done */
|
||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||
@@ -1359,12 +1231,12 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
|
||||
}
|
||||
else if(rc != 0) {
|
||||
result = tftp_receive_packet(conn);
|
||||
if(result != CURLE_OK)
|
||||
return(result);
|
||||
if(result)
|
||||
return result;
|
||||
result = tftp_state_machine(state, state->event);
|
||||
if(result != CURLE_OK)
|
||||
return(result);
|
||||
*done = (bool)(state->state == TFTP_STATE_FIN);
|
||||
if(result)
|
||||
return result;
|
||||
*done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
|
||||
if(*done)
|
||||
/* Tell curl we're done */
|
||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||
@@ -1390,6 +1262,15 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
||||
}
|
||||
else if(!result) {
|
||||
/* The multi code doesn't have this logic for the DOING state so we
|
||||
provide it for TFTP since it may do the entire transfer in this
|
||||
state. */
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
else
|
||||
result = Curl_speedcheck(conn->data, Curl_tvnow());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1409,15 +1290,10 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
|
||||
|
||||
result = tftp_state_machine(state, TFTP_EVENT_INIT);
|
||||
|
||||
if(state->state == TFTP_STATE_FIN || result != CURLE_OK)
|
||||
return(result);
|
||||
if((state->state == TFTP_STATE_FIN) || result)
|
||||
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"));
|
||||
@@ -1438,35 +1314,30 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
|
||||
|
||||
static CURLcode tftp_do(struct connectdata *conn, bool *done)
|
||||
{
|
||||
tftp_state_data_t *state;
|
||||
CURLcode code;
|
||||
tftp_state_data_t *state;
|
||||
CURLcode result;
|
||||
|
||||
*done = FALSE;
|
||||
|
||||
/*
|
||||
Since connections can be re-used between SessionHandles, this might be a
|
||||
connection already existing but on a fresh SessionHandle struct so we must
|
||||
make sure we have a good 'struct TFTP' to play with. For new connections,
|
||||
the struct TFTP is allocated and setup in the tftp_connect() function.
|
||||
*/
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
if(!conn->proto.tftpc) {
|
||||
code = tftp_connect(conn, done);
|
||||
if(code)
|
||||
return code;
|
||||
result = tftp_connect(conn, done);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
state = (tftp_state_data_t *)conn->proto.tftpc;
|
||||
|
||||
code = tftp_perform(conn, done);
|
||||
state = (tftp_state_data_t *)conn->proto.tftpc;
|
||||
if(!state)
|
||||
return CURLE_BAD_CALLING_ORDER;
|
||||
|
||||
result = tftp_perform(conn, done);
|
||||
|
||||
/* If tftp_perform() returned an error, use that for return code. If it
|
||||
was OK, see if tftp_translate_code() has an error. */
|
||||
if (code == CURLE_OK)
|
||||
if(!result)
|
||||
/* If we have encountered an internal tftp error, translate it. */
|
||||
code = tftp_translate_code(state->error);
|
||||
result = tftp_translate_code(state->error);
|
||||
|
||||
return code;
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode tftp_setup_connection(struct connectdata * conn)
|
||||
|
||||
Reference in New Issue
Block a user