1*1ef5f7b1Ssam /*	nsp_output.c	1.5	82/12/18	*/
242c52f3aSsam 
342c52f3aSsam #include "../h/param.h"
442c52f3aSsam #include "../h/systm.h"
542c52f3aSsam #include "../h/mbuf.h"
642c52f3aSsam #include "../h/protosw.h"
742c52f3aSsam #include "../h/socket.h"
842c52f3aSsam #include "../h/socketvar.h"
958e86109Swnj #include "../netdecnet/dn_systm.h"
1058e86109Swnj #include "../netdecnet/nsp.h"
1158e86109Swnj #include "../netdecnet/nsp_var.h"
1258e86109Swnj #include <errno.h>
1342c52f3aSsam 
1442c52f3aSsam /*
1542c52f3aSsam  * NSP output routine: figure out what should be sent and send it.
1642c52f3aSsam  */
nsp_output(np)1742c52f3aSsam nsp_output(np)
1842c52f3aSsam 	register struct nspcb *np;
1942c52f3aSsam {
2042c52f3aSsam 	register struct socket *so = np->n_socket;
2142c52f3aSsam 	register int len;
2242c52f3aSsam 	int off, flags;
2342c52f3aSsam 	register struct mbuf *m;
2442c52f3aSsam 
2542c52f3aSsam 
2642c52f3aSsam 	/*
2742c52f3aSsam 	 * Determine what type of message to send and send it.
2842c52f3aSsam 	 */
2942c52f3aSsam top:
3042c52f3aSsam 	/* interrupt to be sent? */
3142c52f3aSsam 	if (np->n_flags & NF_INTAVAIL) && np->nf_remint > 0 &&
3242c52f3aSsam 	    (np->n_flags & NF_OTHSENT) == 0) {
3342c52f3aSsam 		register struct nspi *n;
3442c52f3aSsam 
35*1ef5f7b1Ssam 		m = m_get(M_CANTWAIT, MT_HEADER);
3642c52f3aSsam 		if (m == 0)
3742c52f3aSsam 			return (0);
3842c52f3aSsam 		if (np->nb_xmt)
3942c52f3aSsam 			len = np->nb_xmt->m_len;
4042c52f3aSsam 		else
4142c52f3aSsam 			len = 0;
4242c52f3aSsam 		m->m_len = sizeof (struct nspi) + len;
4342c52f3aSsam 		m->m_off = MMAXOFF - m->m_len;
4442c52f3aSsam 		n = mtod(m, struct nspi *);
4542c52f3aSsam 		n->nsp_msgflg = NSP_INTR;
4642c52f3aSsam 		n->nsp_dstaddr = np->n_rem;
4742c52f3aSsam 		n->nsp_srcaddr = np->n_loc;
4842c52f3aSsam 		n->nsp_acknum = NSPA_ACK | np->na_xmtoth;
4942c52f3aSsam 		n->nsp_segnum = np->nn_oth;
5042c52f3aSsam 		if (len)
5142c52f3aSsam 			bcopy((char *)(n + 1), mtod(np->nb_xmt, char *), len);
5242c52f3aSsam 		if (tp_output(m, np->n_node)) {
53a33d1446Sroot 			(void) m_free(m);
5442c52f3aSsam 			return (0);
5542c52f3aSsam 		}
5642c52f3aSsam 		np->n_flags &= ~(NF_INTAVAIL|NF_OTHACK);
5742c52f3aSsam 		np->n_flags |= NF_OTHSENT;
5842c52f3aSsam 		if (len)
59a33d1446Sroot 			(void) m_free(np->nb_xmt);
6042c52f3aSsam 		nsp_insrtq(m, np->nt_oth);
6142c52f3aSsam 		goto top;
6242c52f3aSsam 	}
6342c52f3aSsam 
6442c52f3aSsam 	/* interrupt request to be sent? */
6542c52f3aSsam 	if (np->nf_locint == NFL_SEND && (np->n_flags & NF_OTHSENT) == 0) {
6642c52f3aSsam 		register struct nspls *n;
6742c52f3aSsam 
68*1ef5f7b1Ssam 		m = m_get(M_CANTWAIT, MT_HEADER);
6942c52f3aSsam 		if (m == 0)
7042c52f3aSsam 			return (0);
7142c52f3aSsam 		m->m_len = sizeof (struct nspls);
7242c52f3aSsam 		m->m_off = MMAXOFF - m->m_len;
7342c52f3aSsam 		n = mtod(m, struct nspls *);
7442c52f3aSsam 		n->nsp_msgflg = NSP_LS;
7542c52f3aSsam 		n->nsp_dstaddr = np->n_rem;
7642c52f3aSsam 		n->nsp_srcaddr = np->n_loc;
7742c52f3aSsam 		n->nsp_acknum = NSPA_ACK | np->na_xmtoth;
7842c52f3aSsam 		n->nsp_segnum = np->nn_oth;
7942c52f3aSsam 		n->nsp_lsflags = NSPLS_INTREQ | NSPLS_ON;
8042c52f3aSsam 		n->nsp_fcval = 1;
8142c52f3aSsam 		if (tp_output(m, np->n_node)) {
82a33d1446Sroot 			(void) m_free(m);
8342c52f3aSsam 			return (0);
8442c52f3aSsam 		}
8542c52f3aSsam 		np->n_flags &= ~NF_OTHACK;
8642c52f3aSsam 		np->n_flags |= NF_OTHSENT;
8742c52f3aSsam 		nsp_insrtq(m, np->nt_oth);
8842c52f3aSsam 		goto top;
8942c52f3aSsam 	}
9042c52f3aSsam 
9142c52f3aSsam 	/* data request to be sent? */
9242c52f3aSsam 	if (np->nf_locdat > 0 && (np->n_flags & NF_OTHSENT == 0)) {
9342c52f3aSsam 		register struct nspls *n;
9442c52f3aSsam 
95*1ef5f7b1Ssam 		m = m_get(M_CANTWAIT, MT_HEADER);
9642c52f3aSsam 		if (m == 0)
9742c52f3aSsam 			return (0);
9842c52f3aSsam 		m->m_len = sizeof (struct nspls);
9942c52f3aSsam 		m->m_off = MMAXOFF - m->m_len;
10042c52f3aSsam 		n = mtod(m, struct nspls *);
10142c52f3aSsam 		n->nsp_msgflg = NSP_LS;
10242c52f3aSsam 		n->nsp_dstaddr = np->n_rem;
10342c52f3aSsam 		n->nsp_srcaddr = np->n_loc;
10442c52f3aSsam 		n->nsp_acknum = NSPA_ACK | np->na_xmtoth;
10542c52f3aSsam 		n->nsp_segnum = np->nn_oth;
10642c52f3aSsam 		n->nsp_lsflags = NSPLS_DATREQ | NSPLS_ON;
10742c52f3aSsam 		n->nsp_fcval = np->nf_locdat;
10842c52f3aSsam 		if (tp_output(m, np->n_node)) {
109a33d1446Sroot 			(void) m_free(m);
11042c52f3aSsam 			return (0);
11142c52f3aSsam 		}
11242c52f3aSsam 		np->n_flags &= ~NF_OTHACK;
11342c52f3aSsam 		np->n_flags |= NF_OTHSENT;
11442c52f3aSsam 		nsp_insrtq(m, np->nt_oth);
11542c52f3aSsam 		goto top;
11642c52f3aSsam 	}
11742c52f3aSsam 
11842c52f3aSsam 	/* other data ack to be sent? */
11942c52f3aSsam 	if (np->n_flags & NF_OTHACK) {
12042c52f3aSsam 		register struct nspack *n;
12142c52f3aSsam 
122*1ef5f7b1Ssam 		m = m_get(M_CANTWAIT, MT_HEADER);
12342c52f3aSsam 		if (m == 0)
12442c52f3aSsam 			return (0);
12542c52f3aSsam 		m->m_len = sizeof (struct nspack);
12642c52f3aSsam 		m->m_off = MMAXOFF - m->m_len;
12742c52f3aSsam 		n = mtod(m, struct nspack *);
12842c52f3aSsam 		n->nsp_msgflg = NSP_OTHACK;
12942c52f3aSsam 		n->nsp_dstaddr = np->n_rem;
13042c52f3aSsam 		n->nsp_srcaddr = np->n_loc;
13142c52f3aSsam 		n->nsp_acknum = NSPA_ACK | np->na_xmtoth;
13242c52f3aSsam 		if (tp_output(m, np->n_node)) {
133a33d1446Sroot 			(void) m_free(m);
13442c52f3aSsam 			return (0);
13542c52f3aSsam 		}
13642c52f3aSsam 		np->n_flags &= ~NF_OTHACK;
137a33d1446Sroot 		(void) m_free(m);
13842c52f3aSsam 		goto top;
13942c52f3aSsam 	}
14042c52f3aSsam 
14142c52f3aSsam 	/* data to be sent? */
14242c52f3aSsam 	if () {
14342c52f3aSsam 		register struct nspd *n;
14442c52f3aSsam 
14542c52f3aSsam 		m = nsp_mgetcl();
14642c52f3aSsam 		if (m == 0)
14742c52f3aSsam 			return (0);
14842c52f3aSsam 		if (len <= np->n_segsize) {
14942c52f3aSsam 			m->m_next = so->so_snd.sb_mb;
15042c52f3aSsam 			so->so_snd.sb_mb = m->m_next->m_act;
15142c52f3aSsam 		}
15242c52f3aSsam 
15342c52f3aSsam 		/* MORE */
15442c52f3aSsam 
15542c52f3aSsam 	}
15642c52f3aSsam 
15742c52f3aSsam 	/* data ack to be sent? */
15842c52f3aSsam 	if (np->n_flags & NF_DATACK) {
15942c52f3aSsam 		register struct nspack *n;
16042c52f3aSsam 
161*1ef5f7b1Ssam 		m = m_get(M_CANTWAIT, MT_HEADER);
16242c52f3aSsam 		if (m == 0)
16342c52f3aSsam 			return (0);
16442c52f3aSsam 		m->m_len = sizeof (struct nspack);
16542c52f3aSsam 		m->m_off = MMAXOFF - m->m_len;
16642c52f3aSsam 		n = mtod(m, struct nspack *);
16742c52f3aSsam 		n->nsp_msgflg = NSP_DATACK;
16842c52f3aSsam 		n->nsp_dstaddr = np->n_rem;
16942c52f3aSsam 		n->nsp_srcaddr = np->n_loc;
17042c52f3aSsam 		n->nsp_acknum = NSPA_ACK | np->na_xmtdat;
17142c52f3aSsam 		if (tp_output(m, np->n_node)) {
172a33d1446Sroot 			(void) m_free(m);
17342c52f3aSsam 			return (0);
17442c52f3aSsam 		}
17542c52f3aSsam 		np->n_flags &= ~NF_DATACK;
176a33d1446Sroot 		(void) m_free(m);
17742c52f3aSsam 		goto top;
17842c52f3aSsam 	}
17942c52f3aSsam 
18042c52f3aSsam 	/*
18142c52f3aSsam 	 * Nothing left to do, return success.
18242c52f3aSsam 	 */
18342c52f3aSsam 	return (1);
18442c52f3aSsam }
185