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