xref: /original-bsd/sys/deprecated/bbnnet/macros.h (revision 0a83ae40)
1 
2 	/*** macros to simulate action() ***/
3 
4 extern int tcprint;
5 
6 #define TCP_DEBUG(soptr,tptr,wptr,act,newstate) \
7 	if (soptr){ \
8 		if ((soptr)->so_options & SO_DEBUG) { \
9 			if (tcprint) \
10 				printf("via 0x%x, ", fsactab[act]); \
11 			tcp_debug(tptr, wptr, newstate); \
12 		} \
13 	}
14 
15 
16 /*
17  * Simulates calls to action.
18  *	tp	valid tcpcb pointer ( == wp->w_tcb )
19  *	so	valid socket pointer ( == tp->t_in_pcb->inp_socket )
20  *	wp	valid work pointer
21  *	wtype	== wp->w_type, used so compiler can remove constant conditionals
22  *	wdat	== wp->w_dat
23  *
24  *	act, newstate	integers
25  *
26  * Remember that if the state transition results in CLOSED, then we have
27  * lost the mbuf(s) containing the tcpcb...
28  *
29  * moved tcp->net_keep to tcp_net_keep to avoid race condition since don't
30  * always have MBUF holding tcp after state transition function returns.
31  */
32 extern int tcp_net_keep;
33 
34 #define ACTION(tp, so, wp, wtype, wdat, act, newstate) \
35 {	act = fstab[(tp)->t_state][wtype]; \
36 	if (act == 0)  { \
37 		/* \
38 		 * invalid state transition, just print a message and ignore \
39 		 */ \
40 		printf("tcp bad state: tcb=%x state=%d input=%d\n", \
41 			tp, (tp)->t_state, wtype); \
42 		if (wdat != NULL && wtype == INRECV) \
43 			m_freem(dtom(wdat)); \
44 	} else { \
45 		tcp_net_keep = FALSE; \
46 		newstate = (*fsactab[act])(wp); \
47 		TCP_DEBUG (so, tp, wp, act, newstate); \
48 		if (wdat != NULL && !tcp_net_keep && wtype == INRECV) \
49 			m_freem(dtom(wdat)); \
50 		if ((newstate != SAME) && (newstate != CLOSED)) \
51 			(tp)->t_state = newstate; \
52 	} \
53 }
54 
55 extern char	fstab[TCP_NSTATES][INOP];
56 extern int	(*fsactab[])();
57 
58 /*
59  * like w_alloc() macro, but suitable for above ACTION.
60  */
61 #define W_ALLOC(type, stype, tp, m, so, act, newstate) \
62 {									\
63 	struct work w; \
64 	w.w_type = type; w.w_stype = stype; w.w_tcb = tp; w.w_dat = (char *)m; \
65 	ACTION(tp, so, &w, type, m, act, newstate); \
66 }
67 
68 
69 /*
70  * Enqueue/dequeue segment on tcp sequencing queue
71  */
72 #define TCP_ENQ(new, list, tp) \
73 {	(tp)->t_rcv_len += (new)->t_len; \
74 	insque(new, list); \
75 }
76 
77 #define TCP_DEQ(old, tp) \
78 {	(tp)->t_rcv_len -= (old)->t_len; \
79 	remque(old); \
80 }
81 
82 /*
83  * Macro form of firstempty().  Find the first empty spot in rcv buffer.
84  */
85 #define FIRSTEMPTY(tp, retval) \
86 {	register struct th *p; \
87  \
88 	if ((p = (tp)->t_rcv_next) == (struct th *)(tp) || \
89 	    SEQ_LT((tp)->rcv_nxt, p->t_seq)) \
90 		retval = (tp)->rcv_nxt; \
91 	else { \
92 		register struct th *q; \
93  \
94 		while ((q = p->t_next) != (struct th *)(tp) && \
95 		       SEQ_EQ(t_end(p)+1, q->t_seq)) \
96 			p = q; \
97  \
98 		retval = t_end(p) + 1; \
99 	}}
100 
101 /*
102  * macro form of present_data().
103  */
104 extern struct mbuf *extract_oob();
105 
106 #define PRESENT_DATA(tp) \
107 { \
108 	/* connection must be synced and data available for user */ \
109  \
110 	if ((tp)->syn_acked){ \
111 		register struct th *t; \
112 			 struct socket *so; \
113  \
114 		so = (tp)->t_in_pcb->inp_socket; \
115 		if ((t = (tp)->t_rcv_next) != (struct th *)(tp)) { \
116 		    /* \
117 		     * move as many mbufs as possible from tcb \
118 		     * to user queue.  Used to use firstempty(), \
119 		     * but that caused traversal of list twice. \
120 		     */ \
121 		    if (SEQ_LEQ(t->t_seq, (tp)->rcv_nxt)) { \
122 		        register struct sockbuf *sorcv; \
123 			register int	done; \
124 			register struct mbuf *m; \
125 			register struct th *next; \
126  \
127 		        sorcv = &so->so_rcv; \
128 			done = FALSE; \
129 			while (sbspace(sorcv) > 0 && !done) { \
130 				/* \
131 				 * Note order of events: sbappend tries to \
132 				 * coalesce mbufs, so if get a packet in, it \
133 				 * may use the mbuf that sbappend may free. \
134 				 */ \
135  \
136 				/* dequeue chunk from tcb */ \
137  \
138 				next = t->t_next; \
139 				TCP_DEQ(t, tp); \
140 				m = dtom(t); \
141  \
142 				/* \
143 				 * check for end of list and gaps. \
144 				 */ \
145 				if ((next == (struct th *)tp) || \
146 				    (t_end(t)+1 != next->t_seq)) \
147 					done = TRUE; \
148  \
149 				/* SS_CANTRCVMORE == usr_abort */  \
150 				if (so->so_state & SS_CANTRCVMORE) \
151 					m_freem(m); \
152 				else { \
153 					/* \
154 					 * remove urgent data from input stream\
155 					 */ \
156 					if (SEQ_GEQ((tp)->rcv_urpend, (tp)->rcv_urp)) \
157 						m = extract_oob(tp, m, sorcv); \
158  \
159 					if (m) \
160 						/* \
161 						 * chain new data to user \
162 						 * receive buf \
163 						 */ \
164 						sbappend(sorcv, m); \
165 				} \
166  \
167 				t = next; \
168 			} \
169  \
170 		        /* awaken reader only if any data on user rcv queue */ \
171 		        if (sorcv->sb_cc > 0) \
172 				sbwakeup(sorcv); \
173 		    } \
174 		} \
175  \
176 		/* let user know about foreign tcp close if no more data \
177 		 * OR if no data ever transferred. \
178 		 */ \
179  \
180 		if ((tp)->fin_rcvd && /* !tp->usr_closed && */ rcv_empty(tp)) \
181 			socantrcvmore(so); \
182 	}}
183