Gracefully handle ACKs from the future
This commit is contained in:
		
							parent
							
								
									020c0c67f2
								
							
						
					
					
						commit
						cac4275e60
					
				
					 1 changed files with 18 additions and 7 deletions
				
			
		
							
								
								
									
										21
									
								
								tftp.c
									
										
									
									
									
								
							
							
						
						
									
										21
									
								
								tftp.c
									
										
									
									
									
								
							| 
						 | 
					@ -222,9 +222,9 @@ inline void sock_perror(const char *msg)
 | 
				
			||||||
int tftp_put(struct nmrpd_args *args)
 | 
					int tftp_put(struct nmrpd_args *args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sockaddr_in addr;
 | 
						struct sockaddr_in addr;
 | 
				
			||||||
	uint16_t block, port;
 | 
						uint16_t block, ackblock, port;
 | 
				
			||||||
	ssize_t len, last_len;
 | 
						ssize_t len, last_len;
 | 
				
			||||||
	int fd, sock, ret, timeout;
 | 
						int fd, sock, ret, timeout, errors;
 | 
				
			||||||
	char rx[TFTP_PKT_SIZE], tx[TFTP_PKT_SIZE];
 | 
						char rx[TFTP_PKT_SIZE], tx[TFTP_PKT_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sock = -1;
 | 
						sock = -1;
 | 
				
			||||||
| 
						 | 
					@ -255,13 +255,16 @@ int tftp_put(struct nmrpd_args *args)
 | 
				
			||||||
	block = 0;
 | 
						block = 0;
 | 
				
			||||||
	last_len = -1;
 | 
						last_len = -1;
 | 
				
			||||||
	len = 0;
 | 
						len = 0;
 | 
				
			||||||
 | 
						errors = 0;
 | 
				
			||||||
	/* Not really, but this way the loop sends our WRQ before receiving */
 | 
						/* Not really, but this way the loop sends our WRQ before receiving */
 | 
				
			||||||
	timeout = 1;
 | 
						timeout = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pkt_mkwrq(tx, args->filename);
 | 
						pkt_mkwrq(tx, args->filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		if (timeout || (pkt_num(rx) == ACK && pkt_num(rx + 2) == block)) {
 | 
							ackblock = pkt_num(rx) == ACK ? pkt_num(rx + 2) : -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (timeout || ackblock == block) {
 | 
				
			||||||
			if (!timeout) {
 | 
								if (!timeout) {
 | 
				
			||||||
				++block;
 | 
									++block;
 | 
				
			||||||
				pkt_mknum(tx, DATA);
 | 
									pkt_mknum(tx, DATA);
 | 
				
			||||||
| 
						 | 
					@ -284,10 +287,18 @@ int tftp_put(struct nmrpd_args *args)
 | 
				
			||||||
			if (ret < 0) {
 | 
								if (ret < 0) {
 | 
				
			||||||
				goto cleanup;
 | 
									goto cleanup;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (pkt_num(rx) != ACK) {
 | 
							} else if (pkt_num(rx) != ACK || ackblock > block) {
 | 
				
			||||||
 | 
								if (verbosity) {
 | 
				
			||||||
				fprintf(stderr, "Expected ACK(%d), got ", block);
 | 
									fprintf(stderr, "Expected ACK(%d), got ", block);
 | 
				
			||||||
				pkt_print(rx, stderr);
 | 
									pkt_print(rx, stderr);
 | 
				
			||||||
			fprintf(stderr, "!\n");
 | 
									fprintf(stderr, ".\n");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (ackblock != -1 && ++errors > 5) {
 | 
				
			||||||
 | 
									fprintf(stderr, "Protocol error; bailing out.\n");
 | 
				
			||||||
 | 
									ret = -1;
 | 
				
			||||||
 | 
									goto cleanup;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = tftp_recvfrom(sock, rx, &port, args->rx_timeout);
 | 
							ret = tftp_recvfrom(sock, rx, &port, args->rx_timeout);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue