Lines Matching +full:- +full:- +full:timeout +full:- +full:first +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
196 * tftp_set_timeouts -
200 * packet is received, then use user-provided transfer timeouts
206 time_t maxtime, timeout; in tftp_set_timeouts() local
208 bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; in tftp_set_timeouts()
210 /* Compute drop-dead time */ in tftp_set_timeouts()
211 timeout_ms = Curl_timeleft(state->data, NULL, start); in tftp_set_timeouts()
214 /* time-out, bail out, go home */ in tftp_set_timeouts()
215 failf(state->data, "Connection time-out"); in tftp_set_timeouts()
224 /* Set per-block timeout to total */ in tftp_set_timeouts()
225 timeout = maxtime; in tftp_set_timeouts()
228 state->retry_max = (int)timeout/5; in tftp_set_timeouts()
231 if(state->retry_max<3) in tftp_set_timeouts()
232 state->retry_max = 3; in tftp_set_timeouts()
234 if(state->retry_max>50) in tftp_set_timeouts()
235 state->retry_max = 50; in tftp_set_timeouts()
237 /* Compute the re-ACK interval to suit the timeout */ in tftp_set_timeouts()
238 state->retry_time = (int)(timeout/state->retry_max); in tftp_set_timeouts()
239 if(state->retry_time<1) in tftp_set_timeouts()
240 state->retry_time = 1; in tftp_set_timeouts()
242 infof(state->data, in tftp_set_timeouts()
245 (int)state->state, timeout_ms, state->retry_time, state->retry_max); in tftp_set_timeouts()
248 time(&state->rx_time); in tftp_set_timeouts()
263 packet->data[0] = (unsigned char)(num >> 8); in setpacketevent()
264 packet->data[1] = (unsigned char)(num & 0xff); in setpacketevent()
270 packet->data[2] = (unsigned char)(num >> 8); in setpacketblock()
271 packet->data[3] = (unsigned char)(num & 0xff); in setpacketblock()
276 return (unsigned short)((packet->data[0] << 8) | packet->data[1]); in getrpacketevent()
281 return (unsigned short)((packet->data[2] << 8) | packet->data[3]); in getrpacketblock()
287 return end ? (size_t) (end - string) : maxlen; in tftp_strnlen()
302 loc += tftp_strnlen(buf + loc, len-loc); in tftp_option_get()
316 struct Curl_easy *data = state->data; in tftp_parse_option_ack()
319 state->blksize = TFTP_BLKSIZE_DEFAULT; in tftp_parse_option_ack()
324 tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); in tftp_parse_option_ack()
351 else if(blksize > state->requested_blksize) { in tftp_parse_option_ack()
360 state->blksize = (int)blksize; in tftp_parse_option_ack()
362 state->blksize, "requested", state->requested_blksize); in tftp_parse_option_ack()
372 if(!data->state.upload) { in tftp_parse_option_ack()
374 failf(data, "invalid tsize -:%s:- value in OACK packet", value); in tftp_parse_option_ack()
388 if(( strlen(option) + *csize + 1) > (size_t)state->blksize) in tftp_option_add()
400 struct Curl_easy *data = state->data; in tftp_connect_for_tx()
404 state->state = TFTP_STATE_TX; in tftp_connect_for_tx()
416 struct Curl_easy *data = state->data; in tftp_connect_for_rx()
420 state->state = TFTP_STATE_RX; in tftp_connect_for_rx()
434 struct Curl_easy *data = state->data; in tftp_send_first()
437 /* Set ascii mode if -B flag was used */ in tftp_send_first()
438 if(data->state.prefer_ascii) in tftp_send_first()
443 case TFTP_EVENT_INIT: /* Send the first packet out */ in tftp_send_first()
444 case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */ in tftp_send_first()
446 state->retries++; in tftp_send_first()
447 if(state->retries>state->retry_max) { in tftp_send_first()
448 state->error = TFTP_ERR_NORESPONSE; in tftp_send_first()
449 state->state = TFTP_STATE_FIN; in tftp_send_first()
453 if(data->state.upload) { in tftp_send_first()
455 setpacketevent(&state->spacket, TFTP_EVENT_WRQ); in tftp_send_first()
456 if(data->state.infilesize != -1) in tftp_send_first()
457 Curl_pgrsSetUploadSize(data, data->state.infilesize); in tftp_send_first()
461 setpacketevent(&state->spacket, TFTP_EVENT_RRQ); in tftp_send_first()
464 file name so we skip the always-present first letter of the path in tftp_send_first()
466 result = Curl_urldecode(&state->data->state.up.path[1], 0, in tftp_send_first()
471 if(strlen(filename) > (state->blksize - strlen(mode) - 4)) { in tftp_send_first()
477 msnprintf((char *)state->spacket.data + 2, in tftp_send_first()
478 state->blksize, in tftp_send_first()
483 if(!data->set.tftp_no_options) { in tftp_send_first()
486 if(data->state.upload && (data->state.infilesize != -1)) in tftp_send_first()
488 data->state.infilesize); in tftp_send_first()
493 (char *)state->spacket.data + sbytes, in tftp_send_first()
497 (char *)state->spacket.data + sbytes, buf); in tftp_send_first()
500 msnprintf(buf, sizeof(buf), "%d", state->requested_blksize); in tftp_send_first()
503 (char *)state->spacket.data + sbytes, in tftp_send_first()
507 (char *)state->spacket.data + sbytes, buf); in tftp_send_first()
509 /* add timeout option */ in tftp_send_first()
510 msnprintf(buf, sizeof(buf), "%d", state->retry_time); in tftp_send_first()
513 (char *)state->spacket.data + sbytes, in tftp_send_first()
517 (char *)state->spacket.data + sbytes, buf); in tftp_send_first()
528 senddata = sendto(state->sockfd, (void *)state->spacket.data, in tftp_send_first()
530 &data->conn->remote_addr->sa_addr, in tftp_send_first()
531 data->conn->remote_addr->addrlen); in tftp_send_first()
540 if(data->state.upload) { in tftp_send_first()
557 state->state = TFTP_STATE_FIN; in tftp_send_first()
561 failf(state->data, "tftp_send_first: internal error"); in tftp_send_first()
584 struct Curl_easy *data = state->data; in tftp_rx()
591 rblock = getrpacketblock(&state->rpacket); in tftp_rx()
592 if(NEXT_BLOCKNUM(state->block) == rblock) { in tftp_rx()
594 state->retries = 0; in tftp_rx()
596 else if(state->block == rblock) { in tftp_rx()
605 rblock, NEXT_BLOCKNUM(state->block)); in tftp_rx()
610 state->block = (unsigned short)rblock; in tftp_rx()
611 setpacketevent(&state->spacket, TFTP_EVENT_ACK); in tftp_rx()
612 setpacketblock(&state->spacket, state->block); in tftp_rx()
613 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
615 (struct sockaddr *)&state->remote_addr, in tftp_rx()
616 state->remote_addrlen); in tftp_rx()
623 if(state->rbytes < (ssize_t)state->blksize + 4) { in tftp_rx()
624 state->state = TFTP_STATE_FIN; in tftp_rx()
627 state->state = TFTP_STATE_RX; in tftp_rx()
629 time(&state->rx_time); in tftp_rx()
634 state->block = 0; in tftp_rx()
635 state->retries = 0; in tftp_rx()
636 setpacketevent(&state->spacket, TFTP_EVENT_ACK); in tftp_rx()
637 setpacketblock(&state->spacket, state->block); in tftp_rx()
638 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
640 (struct sockaddr *)&state->remote_addr, in tftp_rx()
641 state->remote_addrlen); in tftp_rx()
648 state->state = TFTP_STATE_RX; in tftp_rx()
649 time(&state->rx_time); in tftp_rx()
654 state->retries++; in tftp_rx()
656 "Timeout waiting for block %d ACK. Retries = %d", in tftp_rx()
657 NEXT_BLOCKNUM(state->block), state->retries); in tftp_rx()
658 if(state->retries > state->retry_max) { in tftp_rx()
659 state->error = TFTP_ERR_TIMEOUT; in tftp_rx()
660 state->state = TFTP_STATE_FIN; in tftp_rx()
664 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
666 (struct sockaddr *)&state->remote_addr, in tftp_rx()
667 state->remote_addrlen); in tftp_rx()
676 setpacketevent(&state->spacket, TFTP_EVENT_ERROR); in tftp_rx()
677 setpacketblock(&state->spacket, state->block); in tftp_rx()
678 (void)sendto(state->sockfd, (void *)state->spacket.data, in tftp_rx()
680 (struct sockaddr *)&state->remote_addr, in tftp_rx()
681 state->remote_addrlen); in tftp_rx()
684 state->state = TFTP_STATE_FIN; in tftp_rx()
704 struct Curl_easy *data = state->data; in tftp_tx()
707 struct SingleRequest *k = &data->req; in tftp_tx()
719 int rblock = getrpacketblock(&state->rpacket); in tftp_tx()
721 if(rblock != state->block && in tftp_tx()
722 /* There's a bug in tftpd-hpa that causes it to send us an ack for in tftp_tx()
725 * https://www.syslinux.org/archives/2010-September/015612.html in tftp_tx()
727 !(state->block == 0 && rblock == 65535)) { in tftp_tx()
730 rblock, state->block); in tftp_tx()
731 state->retries++; in tftp_tx()
733 if(state->retries>state->retry_max) { in tftp_tx()
735 state->block); in tftp_tx()
739 /* Re-send the data packet */ in tftp_tx()
740 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_tx()
741 4 + state->sbytes, SEND_4TH_ARG, in tftp_tx()
742 (struct sockaddr *)&state->remote_addr, in tftp_tx()
743 state->remote_addrlen); in tftp_tx()
756 time(&state->rx_time); in tftp_tx()
757 state->block++; in tftp_tx()
760 state->block = 1; /* first data block is 1 when using OACK */ in tftp_tx()
762 state->retries = 0; in tftp_tx()
763 setpacketevent(&state->spacket, TFTP_EVENT_DATA); in tftp_tx()
764 setpacketblock(&state->spacket, state->block); in tftp_tx()
765 if(state->block > 1 && state->sbytes < state->blksize) { in tftp_tx()
766 state->state = TFTP_STATE_FIN; in tftp_tx()
774 state->sbytes = 0; in tftp_tx()
775 bufptr = (char *)state->spacket.data + 4; in tftp_tx()
777 result = Curl_client_read(data, bufptr, state->blksize - state->sbytes, in tftp_tx()
781 state->sbytes += (int)cb; in tftp_tx()
783 } while(state->sbytes < state->blksize && cb); in tftp_tx()
785 sbytes = sendto(state->sockfd, (void *) state->spacket.data, in tftp_tx()
786 4 + state->sbytes, SEND_4TH_ARG, in tftp_tx()
787 (struct sockaddr *)&state->remote_addr, in tftp_tx()
788 state->remote_addrlen); in tftp_tx()
795 k->writebytecount += state->sbytes; in tftp_tx()
796 Curl_pgrsSetUploadCounter(data, k->writebytecount); in tftp_tx()
800 /* Increment the retry counter and log the timeout */ in tftp_tx()
801 state->retries++; in tftp_tx()
802 infof(data, "Timeout waiting for block %d ACK. " in tftp_tx()
803 " Retries = %d", NEXT_BLOCKNUM(state->block), state->retries); in tftp_tx()
805 if(state->retries > state->retry_max) { in tftp_tx()
806 state->error = TFTP_ERR_TIMEOUT; in tftp_tx()
807 state->state = TFTP_STATE_FIN; in tftp_tx()
810 /* Re-send the data packet */ in tftp_tx()
811 sbytes = sendto(state->sockfd, (void *)state->spacket.data, in tftp_tx()
812 4 + state->sbytes, SEND_4TH_ARG, in tftp_tx()
813 (struct sockaddr *)&state->remote_addr, in tftp_tx()
814 state->remote_addrlen); in tftp_tx()
820 /* since this was a re-send, we remain at the still byte position */ in tftp_tx()
821 Curl_pgrsSetUploadCounter(data, k->writebytecount); in tftp_tx()
826 state->state = TFTP_STATE_FIN; in tftp_tx()
827 setpacketevent(&state->spacket, TFTP_EVENT_ERROR); in tftp_tx()
828 setpacketblock(&state->spacket, state->block); in tftp_tx()
829 (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, in tftp_tx()
830 (struct sockaddr *)&state->remote_addr, in tftp_tx()
831 state->remote_addrlen); in tftp_tx()
834 state->state = TFTP_STATE_FIN; in tftp_tx()
908 struct Curl_easy *data = state->data; in tftp_state_machine()
910 switch(state->state) { in tftp_state_machine()
927 DEBUGF(infof(data, "STATE: %d", state->state)); in tftp_state_machine()
946 struct tftp_state_data *state = conn->proto.tftpc; in tftp_disconnect()
952 Curl_safefree(state->rpacket.data); in tftp_disconnect()
953 Curl_safefree(state->spacket.data); in tftp_disconnect()
972 struct connectdata *conn = data->conn; in tftp_connect()
976 state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data)); in tftp_connect()
981 if(data->set.tftp_blksize) in tftp_connect()
983 blksize = (int)data->set.tftp_blksize; in tftp_connect()
990 if(!state->rpacket.data) { in tftp_connect()
991 state->rpacket.data = calloc(1, need_blksize + 2 + 2); in tftp_connect()
993 if(!state->rpacket.data) in tftp_connect()
997 if(!state->spacket.data) { in tftp_connect()
998 state->spacket.data = calloc(1, need_blksize + 2 + 2); in tftp_connect()
1000 if(!state->spacket.data) in tftp_connect()
1008 state->data = data; in tftp_connect()
1009 state->sockfd = conn->sock[FIRSTSOCKET]; in tftp_connect()
1010 state->state = TFTP_STATE_START; in tftp_connect()
1011 state->error = TFTP_ERR_NONE; in tftp_connect()
1012 state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */ in tftp_connect()
1013 state->requested_blksize = blksize; in tftp_connect()
1015 ((struct sockaddr *)&state->local_addr)->sa_family = in tftp_connect()
1016 (CURL_SA_FAMILY_T)(conn->remote_addr->family); in tftp_connect()
1020 if(!conn->bits.bound) { in tftp_connect()
1028 * when running IPv4-only. in tftp_connect()
1034 int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, in tftp_connect()
1035 conn->remote_addr->addrlen); in tftp_connect()
1042 conn->bits.bound = TRUE; in tftp_connect()
1063 struct connectdata *conn = data->conn; in tftp_done()
1064 struct tftp_state_data *state = conn->proto.tftpc; in tftp_done()
1074 result = tftp_translate_code(state->error); in tftp_done()
1090 socks[0] = conn->sock[FIRSTSOCKET]; in tftp_getsock()
1106 struct connectdata *conn = data->conn; in tftp_receive_packet()
1107 struct tftp_state_data *state = conn->proto.tftpc; in tftp_receive_packet()
1111 state->rbytes = (int)recvfrom(state->sockfd, in tftp_receive_packet()
1112 (void *)state->rpacket.data, in tftp_receive_packet()
1113 state->blksize + 4, in tftp_receive_packet()
1117 if(state->remote_addrlen == 0) { in tftp_receive_packet()
1118 memcpy(&state->remote_addr, &fromaddr, fromlen); in tftp_receive_packet()
1119 state->remote_addrlen = fromlen; in tftp_receive_packet()
1123 if(state->rbytes < 4) { in tftp_receive_packet()
1125 /* Not a timeout, but how best to handle it? */ in tftp_receive_packet()
1126 state->event = TFTP_EVENT_TIMEOUT; in tftp_receive_packet()
1130 unsigned short event = getrpacketevent(&state->rpacket); in tftp_receive_packet()
1131 state->event = (tftp_event_t)event; in tftp_receive_packet()
1133 switch(state->event) { in tftp_receive_packet()
1136 if(state->rbytes > 4 && in tftp_receive_packet()
1137 (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { in tftp_receive_packet()
1139 (char *)state->rpacket.data + 4, in tftp_receive_packet()
1140 state->rbytes-4); in tftp_receive_packet()
1149 unsigned short error = getrpacketblock(&state->rpacket); in tftp_receive_packet()
1150 char *str = (char *)state->rpacket.data + 4; in tftp_receive_packet()
1151 size_t strn = state->rbytes - 4; in tftp_receive_packet()
1152 state->error = (tftp_error_t)error; in tftp_receive_packet()
1161 (const char *)state->rpacket.data + 2, in tftp_receive_packet()
1162 state->rbytes-2); in tftp_receive_packet()
1193 struct connectdata *conn = data->conn; in tftp_state_timeout()
1194 struct tftp_state_data *state = conn->proto.tftpc; in tftp_state_timeout()
1200 timeout_ms = Curl_timeleft(state->data, NULL, in tftp_state_timeout()
1201 (state->state == TFTP_STATE_START)); in tftp_state_timeout()
1203 state->error = TFTP_ERR_TIMEOUT; in tftp_state_timeout()
1204 state->state = TFTP_STATE_FIN; in tftp_state_timeout()
1208 if(current > state->rx_time + state->retry_time) { in tftp_state_timeout()
1211 time(&state->rx_time); /* update even though we received nothing */ in tftp_state_timeout()
1228 struct connectdata *conn = data->conn; in tftp_multi_statemach()
1229 struct tftp_state_data *state = conn->proto.tftpc; in tftp_multi_statemach()
1235 failf(data, "TFTP response timeout"); in tftp_multi_statemach()
1242 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; in tftp_multi_statemach()
1245 Curl_xfer_setup(data, -1, -1, FALSE, -1); in tftp_multi_statemach()
1249 int rc = SOCKET_READABLE(state->sockfd, 0); in tftp_multi_statemach()
1251 if(rc == -1) { in tftp_multi_statemach()
1256 state->event = TFTP_EVENT_ERROR; in tftp_multi_statemach()
1262 result = tftp_state_machine(state, state->event); in tftp_multi_statemach()
1265 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; in tftp_multi_statemach()
1268 Curl_xfer_setup(data, -1, -1, FALSE, -1); in tftp_multi_statemach()
1313 struct connectdata *conn = data->conn; in tftp_perform()
1314 struct tftp_state_data *state = conn->proto.tftpc; in tftp_perform()
1320 if((state->state == TFTP_STATE_FIN) || result) in tftp_perform()
1346 struct connectdata *conn = data->conn; in tftp_do()
1350 if(!conn->proto.tftpc) { in tftp_do()
1356 state = conn->proto.tftpc; in tftp_do()
1366 result = tftp_translate_code(state->error); in tftp_do()
1376 conn->transport = TRNSPRT_UDP; in tftp_setup_connection()
1380 type = strstr(data->state.up.path, ";mode="); in tftp_setup_connection()
1383 type = strstr(conn->host.rawalloc, ";mode="); in tftp_setup_connection()
1393 data->state.prefer_ascii = TRUE; in tftp_setup_connection()
1400 data->state.prefer_ascii = FALSE; in tftp_setup_connection()