Lines Matching +full:- +full:- +full:timeout +full:- +full:retries
21 * SPDX-License-Identifier: curl
51 #include "cf-socket.h"
77 #define TFTP_OPTION_INTERVAL "timeout"
92 TFTP_EVENT_NONE = -1,
114 TFTP_ERR_NONE = -100,
130 int retries; member
195 * tftp_set_timeouts -
199 * packet is received, then use user-provided transfer timeouts
205 time_t maxtime, timeout; in tftp_set_timeouts() local
207 bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; in tftp_set_timeouts()
209 /* Compute drop-dead time */ in tftp_set_timeouts()
210 timeout_ms = Curl_timeleft(state->data, NULL, start); in tftp_set_timeouts()
213 /* time-out, bail out, go home */ in tftp_set_timeouts()
214 failf(state->data, "Connection time-out"); in tftp_set_timeouts()
223 /* Set per-block timeout to total */ in tftp_set_timeouts()
224 timeout = maxtime; in tftp_set_timeouts()
227 state->retry_max = (int)timeout/5; in tftp_set_timeouts()
230 if(state->retry_max<3) in tftp_set_timeouts()
231 state->retry_max = 3; in tftp_set_timeouts()
233 if(state->retry_max>50) in tftp_set_timeouts()
234 state->retry_max = 50; in tftp_set_timeouts()
236 /* Compute the re-ACK interval to suit the timeout */ in tftp_set_timeouts()
237 state->retry_time = (int)(timeout/state->retry_max); in tftp_set_timeouts()
238 if(state->retry_time<1) in tftp_set_timeouts()
239 state->retry_time = 1; in tftp_set_timeouts()
241 infof(state->data, in tftp_set_timeouts()
244 (int)state->state, timeout_ms, state->retry_time, state->retry_max); in tftp_set_timeouts()
247 time(&state->rx_time); in tftp_set_timeouts()
262 packet->data[0] = (unsigned char)(num >> 8); in setpacketevent()
263 packet->data[1] = (unsigned char)(num & 0xff); in setpacketevent()
269 packet->data[2] = (unsigned char)(num >> 8); in setpacketblock()
270 packet->data[3] = (unsigned char)(num & 0xff); in setpacketblock()
275 return (unsigned short)((packet->data[0] << 8) | packet->data[1]); in getrpacketevent()
280 return (unsigned short)((packet->data[2] << 8) | packet->data[3]); in getrpacketblock()
286 return end ? (size_t) (end - string) : maxlen; in tftp_strnlen()
301 loc += tftp_strnlen(buf + loc, len-loc); in tftp_option_get()
315 struct Curl_easy *data = state->data; in tftp_parse_option_ack()
318 state->blksize = TFTP_BLKSIZE_DEFAULT; in tftp_parse_option_ack()
323 tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); in tftp_parse_option_ack()
350 else if(blksize > state->requested_blksize) { in tftp_parse_option_ack()
359 state->blksize = (int)blksize; in tftp_parse_option_ack()
361 state->blksize, "requested", state->requested_blksize); in tftp_parse_option_ack()
371 if(!data->state.upload) { in tftp_parse_option_ack()
373 failf(data, "invalid tsize -:%s:- value in OACK packet", value); in tftp_parse_option_ack()
387 if(( strlen(option) + *csize + 1) > (size_t)state->blksize) in tftp_option_add()
399 struct Curl_easy *data = state->data; in tftp_connect_for_tx()
403 state->state = TFTP_STATE_TX; in tftp_connect_for_tx()
415 struct Curl_easy *data = state->data; in tftp_connect_for_rx()
419 state->state = TFTP_STATE_RX; in tftp_connect_for_rx()
433 struct Curl_easy *data = state->data; in tftp_send_first()
436 /* Set ascii mode if -B flag was used */ in tftp_send_first()
437 if(data->state.prefer_ascii) in tftp_send_first()
445 state->retries++; in tftp_send_first()
446 if(state->retries>state->retry_max) { in tftp_send_first()
447 state->error = TFTP_ERR_NORESPONSE; in tftp_send_first()
448 state->state = TFTP_STATE_FIN; in tftp_send_first()
452 if(data->state.upload) { in tftp_send_first()
454 setpacketevent(&state->spacket, TFTP_EVENT_WRQ); in tftp_send_first()
455 state->data->req.upload_fromhere = in tftp_send_first()
456 (char *)state->spacket.data + 4; in tftp_send_first()
457 if(data->state.infilesize != -1) in tftp_send_first()
458 Curl_pgrsSetUploadSize(data, data->state.infilesize); in tftp_send_first()
462 setpacketevent(&state->spacket, TFTP_EVENT_RRQ); in tftp_send_first()
465 file name so we skip the always-present first letter of the path in tftp_send_first()
467 result = Curl_urldecode(&state->data->state.up.path[1], 0, in tftp_send_first()
472 if(strlen(filename) > (state->blksize - strlen(mode) - 4)) { in tftp_send_first()
478 msnprintf((char *)state->spacket.data + 2, in tftp_send_first()
479 state->blksize, in tftp_send_first()
484 if(!data->set.tftp_no_options) { in tftp_send_first()
487 if(data->state.upload && (data->state.infilesize != -1)) in tftp_send_first()
489 data->state.infilesize); in tftp_send_first()
494 (char *)state->spacket.data + sbytes, in tftp_send_first()
498 (char *)state->spacket.data + sbytes, buf); in tftp_send_first()
501 msnprintf(buf, sizeof(buf), "%d", state->requested_blksize); in tftp_send_first()
504 (char *)state->spacket.data + sbytes, in tftp_send_first()
508 (char *)state->spacket.data + sbytes, buf); in tftp_send_first()
510 /* add timeout option */ in tftp_send_first()
511 msnprintf(buf, sizeof(buf), "%d", state->retry_time); in tftp_send_first()
514 (char *)state->spacket.data + sbytes, in tftp_send_first()
518 (char *)state->spacket.data + sbytes, buf); in tftp_send_first()
529 senddata = sendto(state->sockfd, (void *)state->spacket.data, in tftp_send_first()
531 &data->conn->remote_addr->sa_addr, in tftp_send_first()
532 data->conn->remote_addr->addrlen); in tftp_send_first()
541 if(data->state.upload) { in tftp_send_first()
558 state->state = TFTP_STATE_FIN; in tftp_send_first()
562 failf(state->data, "tftp_send_first: internal error"); in tftp_send_first()
585 struct Curl_easy *data = state->data; in tftp_rx()
592 rblock = getrpacketblock(&state->rpacket); in tftp_rx()
593 if(NEXT_BLOCKNUM(state->block) == rblock) { in tftp_rx()
595 state->retries = 0; in tftp_rx()
597 else if(state->block == rblock) { in tftp_rx()
606 rblock, NEXT_BLOCKNUM(state->block)); in tftp_rx()
611 state->block = (unsigned short)rblock; in tftp_rx()
612 setpacketevent(&state->spacket, TFTP_EVENT_ACK); in tftp_rx()
613 setpacketblock(&state->spacket, state->block); in tftp_rx()
614 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
616 (struct sockaddr *)&state->remote_addr, in tftp_rx()
617 state->remote_addrlen); in tftp_rx()
624 if(state->rbytes < (ssize_t)state->blksize + 4) { in tftp_rx()
625 state->state = TFTP_STATE_FIN; in tftp_rx()
628 state->state = TFTP_STATE_RX; in tftp_rx()
630 time(&state->rx_time); in tftp_rx()
635 state->block = 0; in tftp_rx()
636 state->retries = 0; in tftp_rx()
637 setpacketevent(&state->spacket, TFTP_EVENT_ACK); in tftp_rx()
638 setpacketblock(&state->spacket, state->block); in tftp_rx()
639 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
641 (struct sockaddr *)&state->remote_addr, in tftp_rx()
642 state->remote_addrlen); in tftp_rx()
649 state->state = TFTP_STATE_RX; in tftp_rx()
650 time(&state->rx_time); in tftp_rx()
655 state->retries++; in tftp_rx()
657 "Timeout waiting for block %d ACK. Retries = %d", in tftp_rx()
658 NEXT_BLOCKNUM(state->block), state->retries); in tftp_rx()
659 if(state->retries > state->retry_max) { in tftp_rx()
660 state->error = TFTP_ERR_TIMEOUT; in tftp_rx()
661 state->state = TFTP_STATE_FIN; in tftp_rx()
665 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
667 (struct sockaddr *)&state->remote_addr, in tftp_rx()
668 state->remote_addrlen); in tftp_rx()
677 setpacketevent(&state->spacket, TFTP_EVENT_ERROR); in tftp_rx()
678 setpacketblock(&state->spacket, state->block); in tftp_rx()
679 (void)sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
681 (struct sockaddr *)&state->remote_addr, in tftp_rx()
682 state->remote_addrlen); in tftp_rx()
685 state->state = TFTP_STATE_FIN; in tftp_rx()
705 struct Curl_easy *data = state->data; in tftp_tx()
708 struct SingleRequest *k = &data->req; in tftp_tx()
718 int rblock = getrpacketblock(&state->rpacket); in tftp_tx()
720 if(rblock != state->block && in tftp_tx()
721 /* There's a bug in tftpd-hpa that causes it to send us an ack for in tftp_tx()
724 * https://www.syslinux.org/archives/2010-September/015612.html in tftp_tx()
726 !(state->block == 0 && rblock == 65535)) { in tftp_tx()
729 rblock, state->block); in tftp_tx()
730 state->retries++; in tftp_tx()
732 if(state->retries>state->retry_max) { in tftp_tx()
734 state->block); in tftp_tx()
738 /* Re-send the data packet */ in tftp_tx()
739 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_tx()
740 4 + state->sbytes, SEND_4TH_ARG, in tftp_tx()
741 (struct sockaddr *)&state->remote_addr, in tftp_tx()
742 state->remote_addrlen); in tftp_tx()
755 time(&state->rx_time); in tftp_tx()
756 state->block++; in tftp_tx()
759 state->block = 1; /* first data block is 1 when using OACK */ in tftp_tx()
761 state->retries = 0; in tftp_tx()
762 setpacketevent(&state->spacket, TFTP_EVENT_DATA); in tftp_tx()
763 setpacketblock(&state->spacket, state->block); in tftp_tx()
764 if(state->block > 1 && state->sbytes < state->blksize) { in tftp_tx()
765 state->state = TFTP_STATE_FIN; in tftp_tx()
773 state->sbytes = 0; in tftp_tx()
774 state->data->req.upload_fromhere = (char *)state->spacket.data + 4; in tftp_tx()
776 result = Curl_fillreadbuffer(data, state->blksize - state->sbytes, &cb); in tftp_tx()
779 state->sbytes += (int)cb; in tftp_tx()
780 state->data->req.upload_fromhere += cb; in tftp_tx()
781 } while(state->sbytes < state->blksize && cb); in tftp_tx()
783 sbytes = sendto(state->sockfd, (void *) state->spacket.data, in tftp_tx()
784 4 + state->sbytes, SEND_4TH_ARG, in tftp_tx()
785 (struct sockaddr *)&state->remote_addr, in tftp_tx()
786 state->remote_addrlen); in tftp_tx()
793 k->writebytecount += state->sbytes; in tftp_tx()
794 Curl_pgrsSetUploadCounter(data, k->writebytecount); in tftp_tx()
798 /* Increment the retry counter and log the timeout */ in tftp_tx()
799 state->retries++; in tftp_tx()
800 infof(data, "Timeout waiting for block %d ACK. " in tftp_tx()
801 " Retries = %d", NEXT_BLOCKNUM(state->block), state->retries); in tftp_tx()
803 if(state->retries > state->retry_max) { in tftp_tx()
804 state->error = TFTP_ERR_TIMEOUT; in tftp_tx()
805 state->state = TFTP_STATE_FIN; in tftp_tx()
808 /* Re-send the data packet */ in tftp_tx()
809 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_tx()
810 4 + state->sbytes, SEND_4TH_ARG, in tftp_tx()
811 (struct sockaddr *)&state->remote_addr, in tftp_tx()
812 state->remote_addrlen); in tftp_tx()
818 /* since this was a re-send, we remain at the still byte position */ in tftp_tx()
819 Curl_pgrsSetUploadCounter(data, k->writebytecount); in tftp_tx()
824 state->state = TFTP_STATE_FIN; in tftp_tx()
825 setpacketevent(&state->spacket, TFTP_EVENT_ERROR); in tftp_tx()
826 setpacketblock(&state->spacket, state->block); in tftp_tx()
827 (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, in tftp_tx()
828 (struct sockaddr *)&state->remote_addr, in tftp_tx()
829 state->remote_addrlen); in tftp_tx()
832 state->state = TFTP_STATE_FIN; in tftp_tx()
906 struct Curl_easy *data = state->data; in tftp_state_machine()
908 switch(state->state) { in tftp_state_machine()
925 DEBUGF(infof(data, "STATE: %d", state->state)); in tftp_state_machine()
944 struct tftp_state_data *state = conn->proto.tftpc; in tftp_disconnect()
950 Curl_safefree(state->rpacket.data); in tftp_disconnect()
951 Curl_safefree(state->spacket.data); in tftp_disconnect()
970 struct connectdata *conn = data->conn; in tftp_connect()
974 state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data)); in tftp_connect()
979 if(data->set.tftp_blksize) in tftp_connect()
981 blksize = (int)data->set.tftp_blksize; in tftp_connect()
988 if(!state->rpacket.data) { in tftp_connect()
989 state->rpacket.data = calloc(1, need_blksize + 2 + 2); in tftp_connect()
991 if(!state->rpacket.data) in tftp_connect()
995 if(!state->spacket.data) { in tftp_connect()
996 state->spacket.data = calloc(1, need_blksize + 2 + 2); in tftp_connect()
998 if(!state->spacket.data) in tftp_connect()
1006 state->data = data; in tftp_connect()
1007 state->sockfd = conn->sock[FIRSTSOCKET]; in tftp_connect()
1008 state->state = TFTP_STATE_START; in tftp_connect()
1009 state->error = TFTP_ERR_NONE; in tftp_connect()
1010 state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */ in tftp_connect()
1011 state->requested_blksize = blksize; in tftp_connect()
1013 ((struct sockaddr *)&state->local_addr)->sa_family = in tftp_connect()
1014 (CURL_SA_FAMILY_T)(conn->remote_addr->family); in tftp_connect()
1018 if(!conn->bits.bound) { in tftp_connect()
1026 * when running IPv4-only. in tftp_connect()
1032 int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, in tftp_connect()
1033 conn->remote_addr->addrlen); in tftp_connect()
1040 conn->bits.bound = TRUE; in tftp_connect()
1061 struct connectdata *conn = data->conn; in tftp_done()
1062 struct tftp_state_data *state = conn->proto.tftpc; in tftp_done()
1072 result = tftp_translate_code(state->error); in tftp_done()
1088 socks[0] = conn->sock[FIRSTSOCKET]; in tftp_getsock()
1104 struct connectdata *conn = data->conn; in tftp_receive_packet()
1105 struct tftp_state_data *state = conn->proto.tftpc; in tftp_receive_packet()
1109 state->rbytes = (int)recvfrom(state->sockfd, in tftp_receive_packet()
1110 (void *)state->rpacket.data, in tftp_receive_packet()
1111 state->blksize + 4, in tftp_receive_packet()
1115 if(state->remote_addrlen == 0) { in tftp_receive_packet()
1116 memcpy(&state->remote_addr, &fromaddr, fromlen); in tftp_receive_packet()
1117 state->remote_addrlen = fromlen; in tftp_receive_packet()
1121 if(state->rbytes < 4) { in tftp_receive_packet()
1123 /* Not a timeout, but how best to handle it? */ in tftp_receive_packet()
1124 state->event = TFTP_EVENT_TIMEOUT; in tftp_receive_packet()
1128 unsigned short event = getrpacketevent(&state->rpacket); in tftp_receive_packet()
1129 state->event = (tftp_event_t)event; in tftp_receive_packet()
1131 switch(state->event) { in tftp_receive_packet()
1134 if(state->rbytes > 4 && in tftp_receive_packet()
1135 (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { in tftp_receive_packet()
1137 (char *)state->rpacket.data + 4, in tftp_receive_packet()
1138 state->rbytes-4); in tftp_receive_packet()
1147 unsigned short error = getrpacketblock(&state->rpacket); in tftp_receive_packet()
1148 char *str = (char *)state->rpacket.data + 4; in tftp_receive_packet()
1149 size_t strn = state->rbytes - 4; in tftp_receive_packet()
1150 state->error = (tftp_error_t)error; in tftp_receive_packet()
1159 (const char *)state->rpacket.data + 2, in tftp_receive_packet()
1160 state->rbytes-2); in tftp_receive_packet()
1191 struct connectdata *conn = data->conn; in tftp_state_timeout()
1192 struct tftp_state_data *state = conn->proto.tftpc; in tftp_state_timeout()
1198 timeout_ms = Curl_timeleft(state->data, NULL, in tftp_state_timeout()
1199 (state->state == TFTP_STATE_START)); in tftp_state_timeout()
1201 state->error = TFTP_ERR_TIMEOUT; in tftp_state_timeout()
1202 state->state = TFTP_STATE_FIN; in tftp_state_timeout()
1206 if(current > state->rx_time + state->retry_time) { in tftp_state_timeout()
1209 time(&state->rx_time); /* update even though we received nothing */ in tftp_state_timeout()
1226 struct connectdata *conn = data->conn; in tftp_multi_statemach()
1227 struct tftp_state_data *state = conn->proto.tftpc; in tftp_multi_statemach()
1233 failf(data, "TFTP response timeout"); in tftp_multi_statemach()
1240 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; in tftp_multi_statemach()
1243 Curl_setup_transfer(data, -1, -1, FALSE, -1); in tftp_multi_statemach()
1247 int rc = SOCKET_READABLE(state->sockfd, 0); in tftp_multi_statemach()
1249 if(rc == -1) { in tftp_multi_statemach()
1254 state->event = TFTP_EVENT_ERROR; in tftp_multi_statemach()
1260 result = tftp_state_machine(state, state->event); in tftp_multi_statemach()
1263 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; in tftp_multi_statemach()
1266 Curl_setup_transfer(data, -1, -1, FALSE, -1); in tftp_multi_statemach()
1311 struct connectdata *conn = data->conn; in tftp_perform()
1312 struct tftp_state_data *state = conn->proto.tftpc; in tftp_perform()
1318 if((state->state == TFTP_STATE_FIN) || result) in tftp_perform()
1344 struct connectdata *conn = data->conn; in tftp_do()
1348 if(!conn->proto.tftpc) { in tftp_do()
1354 state = conn->proto.tftpc; in tftp_do()
1364 result = tftp_translate_code(state->error); in tftp_do()
1374 conn->transport = TRNSPRT_UDP; in tftp_setup_connection()
1378 type = strstr(data->state.up.path, ";mode="); in tftp_setup_connection()
1381 type = strstr(conn->host.rawalloc, ";mode="); in tftp_setup_connection()
1391 data->state.prefer_ascii = TRUE; in tftp_setup_connection()
1398 data->state.prefer_ascii = FALSE; in tftp_setup_connection()