/* $Log: rdp_macros.h,v $ * Revision 2.6 84/11/14 13:24:53 walsh * macro to go with monitoring outgoing packets on a debugged RDP connection. * * Revision 2.5 84/11/08 16:11:38 walsh * Added code to gather statistics on RDP traffic. This makes the RDPCB * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off * unless you do. * * Revision 2.4 84/11/05 15:53:21 walsh * update_nulltimer() macro began to look inappropriate with recent * changes, so its been stripped out and put in-line. * * Revision 2.3 84/11/05 14:24:45 walsh * added comment. * * Revision 2.2 84/11/02 18:23:51 walsh * Protocol specifiers want NULL message to have own sequence number in * case of slow (t>NULL msg timeout) packets. I don't see this as a problem, * and even if happened (dubious) would only delay discovery, but I * didn't win this one. Initially not designed for this, but fixes are * in almost neatly. * * Revision 2.1 84/11/02 10:13:25 walsh * Fixed to include RCS comments in checked out source. * * * description: * Organized macros used by RDP and put most of them here. * * revision 1.3 * date: 84/07/19 13:53:16; author: walsh; state: Exp; lines added/del: 24/4 * worked on retransmit took too long macro. Should now advise * sockets sleeping in connect(2) and does trash child sockets * who cannot connect to their peers. * * revision 1.2 * date: 84/07/19 10:53:06; author: walsh; state: Exp; lines added/del: 8/5 * Changed retransmit took too long timer to be advisory in nature. It * reports error to user, but does not affect connection state. * * revision 1.1 * date: 84/07/19 10:24:08; author: walsh; state: Exp; * Initial revision */ /********** Macros to hide (socket) level above **********/ /* * The user notifies the RDP of the maximum sized datagram he's willing to * receive by adjusting the socket receive buffering accordingly. */ #define pick_ourmaxlen(rdpcb) \ ((rdpcb)->r_ourmaxlen = (rdpcb)->r_inpcb->inp_socket->so_rcv.sb_hiwat) /* * Notify user of error condition via the socket */ #define set_error(rdpcb, error) (rdpcb)->r_inpcb->inp_socket->so_error = error; /* * On packet reception, can we q a datagram on the socket for the user? * We only q one on the socket at a time. */ #define usr_rbuf_is_empty(rdpcb) \ ((rdpcb)->r_inpcb->inp_socket->so_rcv.sb_cc == 0) /* * All the datagrams are buffered by RDP. RDP has reached its buffering * limit, so prevent the user from queueing more up until we get some * acknowledgements back from the other side. */ #define sendbufisfull(rdpcb) \ { struct sockbuf *sosnd; \ sosnd = &(rdpcb)->r_inpcb->inp_socket->so_snd; \ sosnd->sb_cc = sosnd->sb_hiwat; \ } /* * Permit the user to q up more datagrams for sending. * * We only need to wake up a writer if he's blocked for * buffering space. RDP allows at most 1 datagram in * the socket code, and no datagrams for transmission * are stored on the socket due to RDP's messing with * so_snd.sb_cc, so we are able to do the wakeup iff necessary */ #define sendbufhasspace(rdpcb) \ { struct socket *so; \ so = (rdpcb)->r_inpcb->inp_socket; \ if (so->so_snd.sb_cc) { \ so->so_snd.sb_cc = 0; \ sowwakeup(so); \ }} #define wakeup_reader(rdpcb) sorwakeup((rdpcb)->r_inpcb->inp_socket) #define wakeup_writer(rdpcb) sowwakeup((rdpcb)->r_inpcb->inp_socket) /* * We can't send any new datagrams after we've been reset. */ #define user_cantsendmore(rdpcb) socantsendmore((rdpcb)->r_inpcb->inp_socket) #define user_cantreadmore(rdpcb) socantrcvmore((rdpcb)->r_inpcb->inp_socket) /* * The socket code prevents read(2) or write(2) until we're connected to * the other end. Nor can a child socket be accept(2)ed until the connection * is established. */ #define rdpisconnected(rdpcb) soisconnected((rdpcb)->r_inpcb->inp_socket) /********** Macros to save duplicating code fragments **********/ /* * set up re-transmission timer for packet we just sent. */ #define set_rxtimer(rdpcb, N) \ { (rdpcb)->r_rxtimers[N] = (rdpcb)->r_rxmitime; \ (rdpcb)->r_timers[RDP_tRXMIT] = RDP_tvRXCHECK; \ if ((rdpcb)->r_rttlindex < 0) { \ (rdpcb)->r_rttlindex = N; \ (rdpcb)->r_timers[RDP_tRTTL] = (rdpcb)->r_rttl; \ } } /* * we received the other guy's SYN, and it was in packet seqnum */ #define got_syn(rdpcb, seqnum) \ { (rdpcb)->r_synrcvd = TRUE; \ (rdpcb)->r_rcvq.rq_baseseq = (seqnum) +1; \ (rdpcb)->r_irs = seqnum; \ } /* * RFC 908 section 3.5 page 16 says to use twice the advertised buffering * This is a bad idea that is an attempt to make up for network latency * and to try to keep things pipelined. We'll use only advertised buffering. * Approach: Don't make trouble, other end must ask for it. (by * advertising more than has) */ #define process_synopt(rdpcb, synopt) \ { (rdpcb)->r_hisnbuf = MAX(1, MIN (ntohs((u_short)(synopt)->rh_nbuf), \ RDP_MAXDGRAMS)); \ (rdpcb)->r_hismaxlen = ntohs((u_short)(synopt)->rh_maxlen); \ (rdpcb)->r_sequential = (rdpcb)->r_sequential || \ (ntohs((u_short)(synopt)->rh_options) & RDP_oSEQUENTIAL); \ sbreserve(&((rdpcb)->r_inpcb->inp_socket->so_snd), \ (rdpcb)->r_hismaxlen - HDRSLOP); \ } /* * Advisory and does not close connection. Allows user to pick up any * q'd received datagrams. But, if there's no host-host communications * then these probably aren't useful. The real reason for advisory nature * is that the user process knows best what to do, having contextual info. * ??? break this up into specific code in state timeout functions ??? * * RTTL occurs for 1) normal user datagrams, and 2) NULL messages */ #define rttl(rdpcb) \ { struct socket *rttlso; \ \ rttlso = (rdpcb)->r_inpcb->inp_socket; \ if (rttlso->so_state & SS_NOFDREF) \ /* \ * was a child socket of a listen(2)er trying to \ * establish connection with other end. RDP_sLSYNRCVD \ */ \ trash_pcbs(rdpcb); \ else { \ set_error(rdpcb, ETIMEDOUT); \ /* \ * sleeping in connect(2) and not using NBIO. \ * RDP_sSYNSENT (syn not acked yet) \ */ \ wakeup((caddr_t) &rttlso->so_timeo); \ /* \ * sleeping in write(2) waiting for buffer space \ * or sleeping in select(2). RDP_sESTAB \ */ \ wakeup_writer(rdpcb); \ /* \ * sleeping in read(2) for datagram from other side \ * and NULL msgs imply connection lost RDP_sESTAB \ */ \ wakeup_reader(rdpcb); \ (rdpcb)->r_timers[RDP_tRTTL] = (rdpcb)->r_rttl; \ }} /* * Pass datagram to user. * On UNIX, mark end of datagram by setting m_act on last mbuf in chain. */ #define usr_rbuf_append(rdpcb, m) \ { MBUF *x; \ for (x = (m); x->m_next; x = x->m_next) \ ; \ x->m_act = ((MBUF *) 1); \ sbappend(&(rdpcb)->r_inpcb->inp_socket->so_rcv, m); \ } /* * For in-line coding of the state transition function. */ #ifdef RDP_CS #define RDP_ACTION1 (rdpcb)->r_entered[newstate] = iptime(); #else #define RDP_ACTION1 /**/ #endif #define debug_rdpcb(r) ((r)->r_inpcb->inp_socket->so_options & SO_DEBUG) #define RDP_ACTION(input, rdpcb, arg, newstate) \ { int (*func)(); \ \ func = rdp_action_table[(rdpcb)->r_state][input]; \ if (! func){ \ /* \ * invalid state transition, just print a message and ignore \ */ \ printf("rdp bad transition: rdpcb 0x%x state %d input %d\n", \ (rdpcb), (rdpcb)->r_state, (input)); \ if (arg && (input == RDP_iNETR)) \ m_freem(dtom(arg)); \ newstate = RDP_sSAME; \ } else { \ boolean debug_on; \ \ debug_on = debug_rdpcb(rdpcb); \ newstate = (*func)(rdpcb, arg); \ if (debug_on) \ rdp_debug (rdpcb, arg, input, newstate); \ \ /* \ * No longer have mbufs for protocol control blocks if closed \ */ \ if ((newstate != RDP_sSAME) && (newstate != RDP_sCLOSED)){ \ rdpcb->r_state = newstate; \ RDP_ACTION1 \ } } }