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;
/* 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);
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 */
*
*
**********************************************************/
-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;
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;
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)
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;
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;
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;
* 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;
* 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;
* 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;
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);
}
/**********************************************************
**********************************************************/
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 */
{
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 */
* 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);
* 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)
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;
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);
{
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);
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);