1 /*- 2 * Copyright (c) 1985, 1993 The 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 5.1 (Berkeley) 05/11/93"; 10 #endif /* not lint */ 11 12 #ifdef sgi 13 #ident "$Revision: 1.6 $" 14 #endif 15 16 #include "globals.h" 17 18 struct tsp *answer; 19 20 extern u_short sequence; 21 22 void 23 xmit(type, seq, addr) 24 int type; 25 u_int seq; 26 struct sockaddr_in *addr; 27 { 28 static struct tsp msg; 29 30 msg.tsp_type = type; 31 msg.tsp_seq = seq; 32 msg.tsp_vers = TSPVERSION; 33 (void)strcpy(msg.tsp_name, hostname); 34 bytenetorder(&msg); 35 if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 36 (struct sockaddr*)addr, sizeof(struct sockaddr)) < 0) { 37 trace_sendto_err(addr->sin_addr); 38 } 39 } 40 41 42 /* 43 * Acksend implements reliable datagram transmission by using sequence 44 * numbers and retransmission when necessary. 45 * If `name' is ANYADDR, this routine implements reliable broadcast. 46 * 47 * Because this function calls readmsg(), none of its args may be in 48 * a message provided by readmsg(). 49 */ 50 struct tsp * 51 acksend(message, addr, name, ack, net, bad) 52 struct tsp *message; /* this message */ 53 struct sockaddr_in *addr; /* to here */ 54 char *name; 55 int ack; /* look for this ack */ 56 struct netinfo *net; /* receive from this network */ 57 int bad; /* 1=losing patience */ 58 { 59 struct timeval twait; 60 int count; 61 long msec; 62 63 message->tsp_vers = TSPVERSION; 64 message->tsp_seq = sequence; 65 if (trace) { 66 fprintf(fd, "acksend: to %s: ", 67 (name == ANYADDR ? "broadcast" : name)); 68 print(message, addr); 69 } 70 bytenetorder(message); 71 72 msec = 200; 73 count = bad ? 1 : 5; /* 5 packets in 6.4 seconds */ 74 answer = 0; 75 do { 76 if (!answer) { 77 /* do not go crazy transmitting just because the 78 * other guy cannot keep our sequence numbers 79 * straight. 80 */ 81 if (sendto(sock, (char *)message, sizeof(struct tsp), 82 0, (struct sockaddr*)addr, 83 sizeof(struct sockaddr)) < 0) { 84 trace_sendto_err(addr->sin_addr); 85 break; 86 } 87 } 88 89 mstotvround(&twait, msec); 90 answer = readmsg(ack, name, &twait, net); 91 if (answer != 0) { 92 if (answer->tsp_seq != sequence) { 93 if (trace) 94 fprintf(fd,"acksend: seq # %u!=%u\n", 95 answer->tsp_seq, sequence); 96 continue; 97 } 98 break; 99 } 100 101 msec *= 2; 102 } while (--count > 0); 103 sequence++; 104 105 return(answer); 106 } 107