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 246