]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tftp: use connections meta hash
authorStefan Eissing <stefan@eissing.org>
Wed, 30 Apr 2025 09:08:02 +0000 (11:08 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 6 May 2025 07:05:27 +0000 (09:05 +0200)
Use connection meta hash for state struct instead of union pointer at
connectdata.

Closes #17235

lib/tftp.c
lib/urldata.h

index 2454e3e64f6fbe9a6419d17588e917b64f08bc07..24ce9af98368a52bc0ead5a04a7d889953a042c2 100644 (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);
 
index 8014f8412e84d85d9f9f25abc0872c549c0f7d76..39f57695fe6c47f03a098e06258f05e95b608a9e 100644 (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