V10/sys/inet/tcp_ld.c

Compare this file to the similar file:
Show the results in this format:

/*
 * tcp line discipline; only one, to be pushed on /dev/ip6.
 */

#include "sys/param.h"
#include "sys/stream.h"
#include "sys/inio.h"
#include "sys/conf.h"

#include "sys/inet/in.h"
#include "sys/inet/ip.h"
#include "sys/inet/ip_var.h"
#include "sys/inet/tcp.h"
#include "sys/inet/tcp_fsm.h"
#include "sys/inet/tcp_seq.h"
#include "sys/inet/tcp_timer.h"
#include "sys/inet/tcp_var.h"
#include "sys/inet/tcpip.h"

extern int tcp_busy;	/* set to discourage timers */
int tcp_maxseg = 4096-sizeof(struct tcpiphdr);	/* to fit in a 4k block */
struct queue *tcpqueue;

int	tcpiput(), tcpisrv(), tcpclose();
long	tcpopen();
int	tcposrv();
static	struct qinit tcprinit = { tcpiput, tcpisrv, tcpopen, tcpclose, 4096, 64 };
static	struct qinit tcpwinit = { putq, tcposrv, tcpopen, tcpclose, 512, 64 };
struct streamtab tcpstream = { &tcprinit, &tcpwinit };

long
tcpopen(q, dev)
register struct queue *q;
{
	static int timing;

	if (q->ptr)
		return(0);
	tcpqueue = q;	/* RD queue */
	if(!timing){
		timing = 1;
		tcp_fasttimo();
		tcp_slowtimo();
	}
	q->flag |= QDELIM;
	WR(q)->flag |= QDELIM;
	q->ptr = (caddr_t)1;
	WR(q)->ptr = (caddr_t)1;
	q->flag |= QNOENB;	/* ipiput calls qenable() */
	return(1);
}

tcpclose(q)
register struct queue *q;
{
	if(tcpqueue == q)
		tcpqueue = NULL;
}

/*
 * pass a whole packet to tcp_input
 */
tcpisrv(q)
register struct queue *q;
{
	register struct block *bp, *head, *tail;

	head = tail = NULL;
	while(bp = getq(q)){
		switch (bp->type) {
		case M_DATA:
			bp->next = NULL;
			if (head == NULL)
				head = bp;
			else
				tail->next = bp;
			tail = bp;
			if (bp->class&S_DELIM) {
				bp->class &=~ S_DELIM;
				tcp_busy++;
				MCHECK(head);
				tcp_input(head);
				--tcp_busy;
				head = tail = NULL;
			}
			break;

		default:
			panic("tcpisrv");
		}
	}
	if (head)
		bp_putback(q, head);
}

tcpiput(q, bp)
register struct queue *q;
register struct block *bp;
{
	switch(bp->type){
	case M_DATA:
		putq(q, bp);
		if (bp->class&S_DELIM)
			qenable(q);
		break;
	default:
		(*q->next->qinfo->putp)(q->next, bp);
		break;
	}
		
}

tcposrv(q)
register struct queue *q;
{
	register struct block *bp;

	while(bp = getq(q)){
		switch (bp->type) {
		case M_IOCTL:
			switch(stiocom(bp)){
			case TCPIOMAXSEG:
				tcp_maxseg = *(int *)stiodata(bp);
				bp->type = M_IOCACK;
				qreply(q, bp);
				continue;
			}
			/* default: fall through and put if room */

		default:
			if (q->next->flag & QFULL) {
				putbq(q, bp);
				return;
			}
			(*q->next->qinfo->putp)(q->next, bp);
			continue;
		}
	}
}

/*
 * hand list bp (an IP packet)
 * to the next stream module,
 * usually IP
 */

tcp_ldout(bp)
register struct block *bp;
{
	register struct block *bp1;
	register struct queue *nq;

	if(tcpqueue == NULL){
		bp_free(bp);
		return(1);
	}
	nq = WR(tcpqueue)->next;
	if(nq->flag&QFULL){
		printf("tcp_ldout: QFULL\n");
		bp_free(bp);
		return(1);
	}
	MCHECK(bp);
	while(bp){
		bp1 = bp->next;
		if (bp1==NULL)
			bp->class |= S_DELIM;
		(*nq->qinfo->putp)(nq, bp);
		bp = bp1;
	}
	return(0);
}