1*25202Skarels /*
2*25202Skarels  $Log:	rdp_macros.h,v $
3*25202Skarels  * Revision 2.6  84/11/14  13:24:53  walsh
4*25202Skarels  * macro to go with monitoring outgoing packets on a debugged RDP connection.
5*25202Skarels  *
6*25202Skarels  * Revision 2.5  84/11/08  16:11:38  walsh
7*25202Skarels  * Added code to gather statistics on RDP traffic.  This makes the RDPCB
8*25202Skarels  * too big unles you make mbufs 512 bytes large.  RDP_CS should be turned off
9*25202Skarels  * unless you do.
10*25202Skarels  *
11*25202Skarels  * Revision 2.4  84/11/05  15:53:21  walsh
12*25202Skarels  * update_nulltimer() macro began to look inappropriate with recent
13*25202Skarels  * changes, so its been stripped out and put in-line.
14*25202Skarels  *
15*25202Skarels  * Revision 2.3  84/11/05  14:24:45  walsh
16*25202Skarels  * added comment.
17*25202Skarels  *
18*25202Skarels  * Revision 2.2  84/11/02  18:23:51  walsh
19*25202Skarels  * Protocol specifiers want NULL message to have own sequence number in
20*25202Skarels  * case of slow (t>NULL msg timeout) packets.  I don't see this as a problem,
21*25202Skarels  * and even if happened (dubious) would only delay discovery, but I
22*25202Skarels  * didn't win this one.  Initially not designed for this, but fixes are
23*25202Skarels  * in almost neatly.
24*25202Skarels  *
25*25202Skarels  * Revision 2.1  84/11/02  10:13:25  walsh
26*25202Skarels  * Fixed to include RCS comments in checked out source.
27*25202Skarels  *
28*25202Skarels  *
29*25202Skarels  * description:
30*25202Skarels  * Organized macros used by RDP and put most of them here.
31*25202Skarels  *
32*25202Skarels  * revision 1.3
33*25202Skarels  * date: 84/07/19 13:53:16;  author: walsh;  state: Exp;  lines added/del: 24/4
34*25202Skarels  * worked on retransmit took too long macro.  Should now advise
35*25202Skarels  * sockets sleeping in connect(2) and does trash child sockets
36*25202Skarels  * who cannot connect to their peers.
37*25202Skarels  *
38*25202Skarels  * revision 1.2
39*25202Skarels  * date: 84/07/19 10:53:06;  author: walsh;  state: Exp;  lines added/del: 8/5
40*25202Skarels  * Changed retransmit took too long timer to be advisory in nature.  It
41*25202Skarels  * reports error to user, but does not affect connection state.
42*25202Skarels  *
43*25202Skarels  * revision 1.1
44*25202Skarels  * date: 84/07/19 10:24:08;  author: walsh;  state: Exp;
45*25202Skarels  * Initial revision
46*25202Skarels  */
47*25202Skarels 
48*25202Skarels 
49*25202Skarels /********** Macros to hide (socket) level above **********/
50*25202Skarels 
51*25202Skarels /*
52*25202Skarels  * The user notifies the RDP of the maximum sized datagram he's willing to
53*25202Skarels  * receive by adjusting the socket receive buffering accordingly.
54*25202Skarels  */
55*25202Skarels #define pick_ourmaxlen(rdpcb) \
56*25202Skarels 	((rdpcb)->r_ourmaxlen = (rdpcb)->r_inpcb->inp_socket->so_rcv.sb_hiwat)
57*25202Skarels 
58*25202Skarels /*
59*25202Skarels  * Notify user of error condition via the socket
60*25202Skarels  */
61*25202Skarels #define set_error(rdpcb, error) (rdpcb)->r_inpcb->inp_socket->so_error = error;
62*25202Skarels 
63*25202Skarels /*
64*25202Skarels  * On packet reception, can we q a datagram on the socket for the user?
65*25202Skarels  * We only q one on the socket at a time.
66*25202Skarels  */
67*25202Skarels #define usr_rbuf_is_empty(rdpcb) \
68*25202Skarels 	((rdpcb)->r_inpcb->inp_socket->so_rcv.sb_cc == 0)
69*25202Skarels 
70*25202Skarels /*
71*25202Skarels  * All the datagrams are buffered by RDP.  RDP has reached its buffering
72*25202Skarels  * limit, so prevent the user from queueing more up until we get some
73*25202Skarels  * acknowledgements back from the other side.
74*25202Skarels  */
75*25202Skarels #define sendbufisfull(rdpcb) \
76*25202Skarels 	{ struct sockbuf *sosnd;				\
77*25202Skarels 	  sosnd = &(rdpcb)->r_inpcb->inp_socket->so_snd;	\
78*25202Skarels 	  sosnd->sb_cc = sosnd->sb_hiwat;			\
79*25202Skarels 	}
80*25202Skarels 
81*25202Skarels /*
82*25202Skarels  * Permit the user to q up more datagrams for sending.
83*25202Skarels  *
84*25202Skarels  * We only need to wake up a writer if he's blocked for
85*25202Skarels  * buffering space.  RDP allows at most 1 datagram in
86*25202Skarels  * the socket code, and no datagrams for transmission
87*25202Skarels  * are stored on the socket due to RDP's messing with
88*25202Skarels  * so_snd.sb_cc, so we are able to do the wakeup iff necessary
89*25202Skarels  */
90*25202Skarels #define sendbufhasspace(rdpcb) \
91*25202Skarels 	{ struct socket *so;			\
92*25202Skarels 	  so = (rdpcb)->r_inpcb->inp_socket;	\
93*25202Skarels 	  if (so->so_snd.sb_cc) {		\
94*25202Skarels 		  so->so_snd.sb_cc = 0;		\
95*25202Skarels 		  sowwakeup(so);		\
96*25202Skarels 	}}
97*25202Skarels 
98*25202Skarels #define wakeup_reader(rdpcb) sorwakeup((rdpcb)->r_inpcb->inp_socket)
99*25202Skarels #define wakeup_writer(rdpcb) sowwakeup((rdpcb)->r_inpcb->inp_socket)
100*25202Skarels 
101*25202Skarels /*
102*25202Skarels  * We can't send any new datagrams after we've been reset.
103*25202Skarels  */
104*25202Skarels #define user_cantsendmore(rdpcb) socantsendmore((rdpcb)->r_inpcb->inp_socket)
105*25202Skarels 
106*25202Skarels #define user_cantreadmore(rdpcb) socantrcvmore((rdpcb)->r_inpcb->inp_socket)
107*25202Skarels 
108*25202Skarels /*
109*25202Skarels  * The socket code prevents read(2) or write(2) until we're connected to
110*25202Skarels  * the other end.  Nor can a child socket be accept(2)ed until the connection
111*25202Skarels  * is established.
112*25202Skarels  */
113*25202Skarels #define rdpisconnected(rdpcb) soisconnected((rdpcb)->r_inpcb->inp_socket)
114*25202Skarels 
115*25202Skarels 
116*25202Skarels /********** Macros to save duplicating code fragments **********/
117*25202Skarels 
118*25202Skarels /*
119*25202Skarels  * set up re-transmission timer for packet we just sent.
120*25202Skarels  */
121*25202Skarels #define set_rxtimer(rdpcb, N) \
122*25202Skarels 	{ (rdpcb)->r_rxtimers[N] = (rdpcb)->r_rxmitime;		\
123*25202Skarels 	  (rdpcb)->r_timers[RDP_tRXMIT] = RDP_tvRXCHECK;	\
124*25202Skarels 	  if ((rdpcb)->r_rttlindex < 0) {			\
125*25202Skarels 		(rdpcb)->r_rttlindex = N;			\
126*25202Skarels 		(rdpcb)->r_timers[RDP_tRTTL] = (rdpcb)->r_rttl;	\
127*25202Skarels 	} }
128*25202Skarels 
129*25202Skarels /*
130*25202Skarels  * we received the other guy's SYN, and it was in packet seqnum
131*25202Skarels  */
132*25202Skarels #define got_syn(rdpcb, seqnum) \
133*25202Skarels 	{ (rdpcb)->r_synrcvd = TRUE;                \
134*25202Skarels 	  (rdpcb)->r_rcvq.rq_baseseq = (seqnum) +1; \
135*25202Skarels 	  (rdpcb)->r_irs = seqnum;                  \
136*25202Skarels 	}
137*25202Skarels 
138*25202Skarels /*
139*25202Skarels  * RFC 908 section 3.5 page 16 says to use twice the advertised buffering
140*25202Skarels  * This is a bad idea that is an attempt to make up for network latency
141*25202Skarels  * and to try to keep things pipelined.  We'll use only advertised buffering.
142*25202Skarels  * Approach:  Don't make trouble, other end must ask for it.  (by
143*25202Skarels  * advertising more than has)
144*25202Skarels  */
145*25202Skarels #define process_synopt(rdpcb, synopt) \
146*25202Skarels 	{ (rdpcb)->r_hisnbuf = MAX(1, MIN (ntohs((u_short)(synopt)->rh_nbuf), \
147*25202Skarels 					   RDP_MAXDGRAMS));	 \
148*25202Skarels 	  (rdpcb)->r_hismaxlen = ntohs((u_short)(synopt)->rh_maxlen);     \
149*25202Skarels 	  (rdpcb)->r_sequential = (rdpcb)->r_sequential ||       \
150*25202Skarels 		(ntohs((u_short)(synopt)->rh_options) & RDP_oSEQUENTIAL); \
151*25202Skarels 	  sbreserve(&((rdpcb)->r_inpcb->inp_socket->so_snd),     \
152*25202Skarels 		(rdpcb)->r_hismaxlen - HDRSLOP);		 \
153*25202Skarels 	}
154*25202Skarels 
155*25202Skarels /*
156*25202Skarels  * Advisory and does not close connection.  Allows user to pick up any
157*25202Skarels  * q'd received datagrams.  But, if there's no host-host communications
158*25202Skarels  * then these probably aren't useful.  The real reason for advisory nature
159*25202Skarels  * is that the user process knows best what to do, having contextual info.
160*25202Skarels  * ??? break this up into specific code in state timeout functions ???
161*25202Skarels  *
162*25202Skarels  * RTTL occurs for 1) normal user datagrams, and 2) NULL messages
163*25202Skarels  */
164*25202Skarels #define rttl(rdpcb) \
165*25202Skarels 	{ struct socket *rttlso;					\
166*25202Skarels 									\
167*25202Skarels 	rttlso = (rdpcb)->r_inpcb->inp_socket;				\
168*25202Skarels 	if (rttlso->so_state & SS_NOFDREF)				\
169*25202Skarels 		/*							\
170*25202Skarels 		 * was a child socket of a listen(2)er trying to	\
171*25202Skarels 		 * establish connection with other end.  RDP_sLSYNRCVD	\
172*25202Skarels 		 */							\
173*25202Skarels 		trash_pcbs(rdpcb);					\
174*25202Skarels 	else {								\
175*25202Skarels 		set_error(rdpcb, ETIMEDOUT);				\
176*25202Skarels 		/*							\
177*25202Skarels 		 * sleeping in connect(2) and not using NBIO.		\
178*25202Skarels 		 * RDP_sSYNSENT (syn not acked yet)			\
179*25202Skarels 		 */							\
180*25202Skarels 		wakeup((caddr_t) &rttlso->so_timeo);			\
181*25202Skarels 		/*							\
182*25202Skarels 		 * sleeping in write(2) waiting for buffer space	\
183*25202Skarels 		 * or sleeping in select(2).  RDP_sESTAB		\
184*25202Skarels 		 */							\
185*25202Skarels 		wakeup_writer(rdpcb);					\
186*25202Skarels 		/*							\
187*25202Skarels 		 * sleeping in read(2) for datagram from other side	\
188*25202Skarels 		 * and NULL msgs imply connection lost RDP_sESTAB	\
189*25202Skarels 		 */							\
190*25202Skarels 		wakeup_reader(rdpcb);					\
191*25202Skarels 		(rdpcb)->r_timers[RDP_tRTTL] = (rdpcb)->r_rttl;		\
192*25202Skarels 	}}
193*25202Skarels 
194*25202Skarels /*
195*25202Skarels  * Pass datagram to user.
196*25202Skarels  * On UNIX, mark end of datagram by setting m_act on last mbuf in chain.
197*25202Skarels  */
198*25202Skarels #define usr_rbuf_append(rdpcb, m) \
199*25202Skarels 	{ MBUF *x;						\
200*25202Skarels 	  for (x = (m); x->m_next; x = x->m_next)		\
201*25202Skarels 		;						\
202*25202Skarels 	  x->m_act = ((MBUF *) 1);				\
203*25202Skarels 	  sbappend(&(rdpcb)->r_inpcb->inp_socket->so_rcv, m);	\
204*25202Skarels 	}
205*25202Skarels 
206*25202Skarels /*
207*25202Skarels  * For in-line coding of the state transition function.
208*25202Skarels  */
209*25202Skarels #ifdef RDP_CS
210*25202Skarels #define RDP_ACTION1 (rdpcb)->r_entered[newstate] = iptime();
211*25202Skarels #else
212*25202Skarels #define RDP_ACTION1 /**/
213*25202Skarels #endif
214*25202Skarels 
215*25202Skarels #define debug_rdpcb(r) ((r)->r_inpcb->inp_socket->so_options & SO_DEBUG)
216*25202Skarels 
217*25202Skarels #define RDP_ACTION(input, rdpcb, arg, newstate) \
218*25202Skarels 	{ int	(*func)();						\
219*25202Skarels \
220*25202Skarels 	func = rdp_action_table[(rdpcb)->r_state][input];		\
221*25202Skarels 	if (! func){							\
222*25202Skarels 		/*							\
223*25202Skarels 		 * invalid state transition, just print a message and ignore \
224*25202Skarels 		 */							\
225*25202Skarels 		printf("rdp bad transition: rdpcb 0x%x state %d input %d\n", \
226*25202Skarels 			(rdpcb), (rdpcb)->r_state, (input));		\
227*25202Skarels 		if (arg && (input == RDP_iNETR))			\
228*25202Skarels 			m_freem(dtom(arg));				\
229*25202Skarels 		newstate = RDP_sSAME;					\
230*25202Skarels 	} else {							\
231*25202Skarels 		boolean debug_on;					\
232*25202Skarels \
233*25202Skarels 		debug_on = debug_rdpcb(rdpcb);				\
234*25202Skarels 		newstate = (*func)(rdpcb, arg);				\
235*25202Skarels 		if (debug_on)						\
236*25202Skarels 			rdp_debug (rdpcb, arg, input, newstate);	\
237*25202Skarels \
238*25202Skarels 		/*							\
239*25202Skarels 		 * No longer have mbufs for protocol control blocks if closed \
240*25202Skarels 		 */							\
241*25202Skarels 		if ((newstate != RDP_sSAME) && (newstate != RDP_sCLOSED)){ \
242*25202Skarels 			rdpcb->r_state = newstate;			\
243*25202Skarels 			RDP_ACTION1					\
244*25202Skarels 	} } }
245*25202Skarels 
246