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