xref: /netbsd/usr.sbin/timed/timed/acksend.c (revision bf9ec67e)
1 /*	$NetBSD: acksend.c,v 1.6 2001/09/02 00:13:05 reinoud Exp $	*/
2 
3 /*-
4  * Copyright (c) 1985, 1993 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)acksend.c	8.1 (Berkeley) 6/6/93";
40 #else
41 __RCSID("$NetBSD: acksend.c,v 1.6 2001/09/02 00:13:05 reinoud Exp $");
42 #endif
43 #endif /* not lint */
44 
45 #include "globals.h"
46 
47 
48 struct tsp *answer;
49 
50 extern u_short sequence;
51 
52 void
53 xmit(int type,
54      u_short seq,
55      struct sockaddr_in *addr)
56 {
57 	static struct tsp msg;
58 
59 	msg.tsp_type = type;
60 	msg.tsp_seq = seq;
61 	msg.tsp_vers = TSPVERSION;
62 	(void)strcpy(msg.tsp_name, hostname);
63 	bytenetorder(&msg);
64 	if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
65 		   (struct sockaddr*)addr, sizeof(struct sockaddr)) < 0) {
66 		trace_sendto_err(addr->sin_addr);
67 	}
68 }
69 
70 
71 /*
72  * Acksend implements reliable datagram transmission by using sequence
73  * numbers and retransmission when necessary.
74  * If `name' is ANYADDR, this routine implements reliable broadcast.
75  *
76  * Because this function calls readmsg(), none of its args may be in
77  *	a message provided by readmsg().
78  */
79 struct tsp *
80 acksend(struct tsp *message,		/* this message */
81 	struct sockaddr_in *addr, char *name,	/* to here */
82 	int ack,			/* look for this ack */
83 	struct netinfo *net,		/* receive from this network */
84 	int bad)			/* 1=losing patience */
85 {
86 	struct timeval twait;
87 	int count;
88 	long msec;
89 
90 	message->tsp_vers = TSPVERSION;
91 	message->tsp_seq = sequence;
92 	if (trace) {
93 		fprintf(fd, "acksend: to %s: ",
94 			(name == ANYADDR ? "broadcast" : name));
95 		print(message, addr);
96 	}
97 	bytenetorder(message);
98 
99 	msec = 200;
100 	count = bad ? 1 : 5;	/* 5 packets in 6.4 seconds */
101 	answer = 0;
102 	do {
103 		if (!answer) {
104 			/* do not go crazy transmitting just because the
105 			 * other guy cannot keep our sequence numbers
106 			 * straight.
107 			 */
108 			if (sendto(sock, (char *)message, sizeof(struct tsp),
109 				   0, (struct sockaddr*)addr,
110 				   sizeof(struct sockaddr)) < 0) {
111 				trace_sendto_err(addr->sin_addr);
112 				break;
113 			}
114 		}
115 
116 		mstotvround(&twait, msec);
117 		answer  = readmsg(ack, name, &twait, net);
118 		if (answer != 0) {
119 			if (answer->tsp_seq != sequence) {
120 				if (trace)
121 					fprintf(fd,"acksend: seq # %u!=%u\n",
122 						answer->tsp_seq, sequence);
123 				continue;
124 			}
125 			break;
126 		}
127 
128 		msec *= 2;
129 	} while (--count > 0);
130 	sequence++;
131 
132 	return(answer);
133 }
134