1 /*-
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)acksend.c 8.1 (Berkeley) 06/06/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
xmit(type,seq,addr)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 *
acksend(message,addr,name,ack,net,bad)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