tftp: use connections meta hash

Use connection meta hash for state struct instead of union pointer at
connectdata.

Closes #17235
This commit is contained in:
Stefan Eissing 2025-04-30 11:08:02 +02:00 committed by Daniel Stenberg
parent d57bdbf830
commit 378aa011e6
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
2 changed files with 47 additions and 62 deletions

View file

@ -121,7 +121,10 @@ struct tftp_packet {
unsigned char *data;
};
struct tftp_state_data {
/* meta key for storing protocol meta at connection */
#define CURL_META_TFTP_CONN "meta:proto:tftp:conn"
struct tftp_conn {
tftp_state_t state;
tftp_mode_t mode;
tftp_error_t error;
@ -146,12 +149,9 @@ struct tftp_state_data {
/* Forward declarations */
static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_rx(struct tftp_conn *state, tftp_event_t event);
static CURLcode tftp_tx(struct tftp_conn *state, tftp_event_t event);
static CURLcode tftp_connect(struct Curl_easy *data, bool *done);
static CURLcode tftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection);
static CURLcode tftp_do(struct Curl_easy *data, bool *done);
static CURLcode tftp_done(struct Curl_easy *data,
CURLcode, bool premature);
@ -181,7 +181,7 @@ const struct Curl_handler Curl_handler_tftp = {
tftp_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
tftp_disconnect, /* disconnect */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
@ -203,7 +203,7 @@ const struct Curl_handler Curl_handler_tftp = {
*
*
**********************************************************/
static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
static CURLcode tftp_set_timeouts(struct tftp_conn *state)
{
time_t maxtime, timeout;
timediff_t timeout_ms;
@ -310,7 +310,7 @@ static const char *tftp_option_get(const char *buf, size_t len,
return &buf[loc];
}
static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
static CURLcode tftp_parse_option_ack(struct tftp_conn *state,
const char *ptr, int len)
{
const char *tmp = ptr;
@ -379,7 +379,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
return CURLE_OK;
}
static CURLcode tftp_option_add(struct tftp_state_data *state, size_t *csize,
static CURLcode tftp_option_add(struct tftp_conn *state, size_t *csize,
char *buf, const char *option)
{
if(( strlen(option) + *csize + 1) > (size_t)state->blksize)
@ -389,7 +389,7 @@ static CURLcode tftp_option_add(struct tftp_state_data *state, size_t *csize,
return CURLE_OK;
}
static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
static CURLcode tftp_connect_for_tx(struct tftp_conn *state,
tftp_event_t event)
{
CURLcode result;
@ -405,7 +405,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
return tftp_tx(state, event);
}
static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
static CURLcode tftp_connect_for_rx(struct tftp_conn *state,
tftp_event_t event)
{
CURLcode result;
@ -421,7 +421,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
return tftp_rx(state, event);
}
static CURLcode tftp_send_first(struct tftp_state_data *state,
static CURLcode tftp_send_first(struct tftp_conn *state,
tftp_event_t event)
{
size_t sbytes;
@ -576,8 +576,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
* Event handler for the RX state
*
**********************************************************/
static CURLcode tftp_rx(struct tftp_state_data *state,
tftp_event_t event)
static CURLcode tftp_rx(struct tftp_conn *state, tftp_event_t event)
{
ssize_t sbytes;
int rblock;
@ -699,7 +698,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
* Event handler for the TX state
*
**********************************************************/
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
static CURLcode tftp_tx(struct tftp_conn *state, tftp_event_t event)
{
struct Curl_easy *data = state->data;
ssize_t sbytes;
@ -901,7 +900,7 @@ static CURLcode tftp_translate_code(tftp_error_t error)
* The tftp state machine event dispatcher
*
**********************************************************/
static CURLcode tftp_state_machine(struct tftp_state_data *state,
static CURLcode tftp_state_machine(struct tftp_conn *state,
tftp_event_t event)
{
CURLcode result = CURLE_OK;
@ -933,28 +932,14 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
return result;
}
/**********************************************************
*
* tftp_disconnect
*
* The disconnect callback
*
**********************************************************/
static CURLcode tftp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
static void tftp_conn_dtor(void *key, size_t klen, void *entry)
{
struct tftp_state_data *state = conn->proto.tftpc;
(void) data;
(void) dead_connection;
/* done, free dynamically allocated pkt buffers */
if(state) {
Curl_safefree(state->rpacket.data);
Curl_safefree(state->spacket.data);
free(state);
}
return CURLE_OK;
struct tftp_conn *state = entry;
(void)key;
(void)klen;
Curl_safefree(state->rpacket.data);
Curl_safefree(state->spacket.data);
free(state);
}
/**********************************************************
@ -966,15 +951,16 @@ static CURLcode tftp_disconnect(struct Curl_easy *data,
**********************************************************/
static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
{
struct tftp_state_data *state;
struct tftp_conn *state;
int blksize;
int need_blksize;
struct connectdata *conn = data->conn;
blksize = TFTP_BLKSIZE_DEFAULT;
state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data));
if(!state)
state = calloc(1, sizeof(*state));
if(!state ||
Curl_conn_meta_set(conn, CURL_META_TFTP_CONN, state, tftp_conn_dtor))
return CURLE_OUT_OF_MEMORY;
/* alloc pkt buffers based on specified blksize */
@ -1061,7 +1047,7 @@ static CURLcode tftp_done(struct Curl_easy *data, CURLcode status,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
(void)status; /* unused */
(void)premature; /* not used */
@ -1098,12 +1084,11 @@ static int tftp_getsock(struct Curl_easy *data,
* Called once select fires and data is ready on the socket
*
**********************************************************/
static CURLcode tftp_receive_packet(struct Curl_easy *data)
static CURLcode tftp_receive_packet(struct Curl_easy *data,
struct tftp_conn *state)
{
curl_socklen_t fromlen;
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
/* Receive the packet */
fromlen = sizeof(state->remote_addr);
@ -1182,12 +1167,10 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
* Check if timeouts have been reached
*
**********************************************************/
static timediff_t tftp_state_timeout(struct Curl_easy *data,
static timediff_t tftp_state_timeout(struct tftp_conn *state,
tftp_event_t *event)
{
time_t current;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
timediff_t timeout_ms;
if(event)
@ -1222,11 +1205,14 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
tftp_event_t event;
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
timediff_t timeout_ms = tftp_state_timeout(data, &event);
struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
timediff_t timeout_ms;
*done = FALSE;
if(!state)
return CURLE_FAILED_INIT;
timeout_ms = tftp_state_timeout(state, &event);
if(timeout_ms < 0) {
failf(data, "TFTP response timeout");
return CURLE_OPERATION_TIMEDOUT;
@ -1252,7 +1238,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
state->event = TFTP_EVENT_ERROR;
}
else if(rc) {
result = tftp_receive_packet(data);
result = tftp_receive_packet(data, state);
if(result)
return result;
result = tftp_state_machine(state, state->event);
@ -1307,9 +1293,11 @@ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
*dophase_done = FALSE;
if(!state)
return CURLE_FAILED_INIT;
result = tftp_state_machine(state, TFTP_EVENT_INIT);
@ -1337,21 +1325,21 @@ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
static CURLcode tftp_do(struct Curl_easy *data, bool *done)
{
struct tftp_state_data *state;
CURLcode result;
struct connectdata *conn = data->conn;
struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
CURLcode result;
*done = FALSE;
if(!conn->proto.tftpc) {
if(!state) {
result = tftp_connect(data, done);
if(result)
return result;
}
state = conn->proto.tftpc;
if(!state)
return CURLE_TFTP_ILLEGAL;
state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
if(!state)
return CURLE_TFTP_ILLEGAL;
}
result = tftp_perform(data, done);

View file

@ -870,9 +870,6 @@ struct connectdata {
#ifdef USE_SSH
struct ssh_conn sshc;
#endif
#ifndef CURL_DISABLE_TFTP
struct tftp_state_data *tftpc;
#endif
#ifndef CURL_DISABLE_IMAP
struct imap_conn imapc;
#endif