1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)acksend.c 2.8 (Berkeley) 03/02/91"; 10 #endif /* not lint */ 11 12 #include "globals.h" 13 #include <protocols/timed.h> 14 15 #define RECEIVED 0 16 #define LOST 1 17 #define SECFORACK 1 /* seconds */ 18 #define USECFORACK 0 /* microseconds */ 19 #define MAXCOUNT 5 20 21 struct tsp *answer; 22 23 /* 24 * Acksend implements reliable datagram transmission by using sequence 25 * numbers and retransmission when necessary. 26 * `name' is the name of the destination 27 * `addr' is the address to send to 28 * If `name' is ANYADDR, this routine implements reliable broadcast. 29 */ 30 31 struct tsp *acksend(message, addr, name, ack, net) 32 struct tsp *message; 33 struct sockaddr_in *addr; 34 char *name; 35 int ack; 36 struct netinfo *net; 37 { 38 int count; 39 int flag; 40 extern u_short sequence; 41 struct timeval tout; 42 struct tsp *readmsg(); 43 44 count = 0; 45 46 message->tsp_vers = TSPVERSION; 47 message->tsp_seq = sequence; 48 if (trace) { 49 fprintf(fd, "acksend: "); 50 if (name == ANYADDR) 51 fprintf(fd, "broadcast: "); 52 else 53 fprintf(fd, "%s: ", name); 54 print(message, addr); 55 } 56 bytenetorder(message); 57 do { 58 if (sendto(sock, (char *)message, sizeof(struct tsp), 0, 59 (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0) { 60 syslog(LOG_ERR, "acksend: sendto: %m"); 61 exit(1); 62 } 63 tout.tv_sec = SECFORACK; 64 tout.tv_usec = USECFORACK; 65 answer = readmsg(ack, name, &tout, net); 66 if (answer != NULL) { 67 if (answer->tsp_seq != sequence) { 68 if (trace) 69 fprintf(fd, "acksend: seq # %d != %d\n", 70 answer->tsp_seq, sequence); 71 continue; 72 } 73 flag = RECEIVED; 74 } else { 75 flag = LOST; 76 if (++count == MAXCOUNT) { 77 break; 78 } 79 } 80 } while (flag != RECEIVED); 81 sequence++; 82 return(answer); 83 } 84