plan 9 kernel history: overview | file list | diff list

2001/0527/ip/tcp.c (diff list | history)

1997/0327/sys/src/9/ip/tcp.c:239,2511997/0403/sys/src/9/ip/tcp.c:239,252 (short | long)
1997/0327    
static char* 
tcpconnect(Conv *c, char **argv, int argc) 
{ 
	char *rv; 
1997/0403    
	char *e; 
1997/0327    
 
	rv = Fsstdconnect(c, argv, argc); 
	if(rv) 
		return rv; 
1997/0403    
	e = Fsstdconnect(c, argv, argc); 
	if(e != nil) 
		return e; 
1997/0327    
	tcpstart(c, TCP_CONNECT, QMAX); 
	return rv; 
1997/0403    
 
	return nil; 
1997/0327    
} 
 
int 
1997/0327/sys/src/9/ip/tcp.c:273,2831997/0403/sys/src/9/ip/tcp.c:274,291
1997/0327    
	return isclose; 
} 
 
static void 
tcpannounce(Conv *c) 
1997/0403    
static char* 
tcpannounce(Conv *c, char **argv, int argc) 
1997/0327    
{ 
1997/0403    
	char *e; 
 
	e = Fsstdannounce(c, argv, argc); 
	if(e != nil) 
		return e; 
1997/0327    
	tcpstart(c, TCP_LISTEN, QMAX); 
	Fsconnected(&fs, c, nil); 
1997/0403    
 
	return nil; 
1997/0327    
} 
 
static void 
1997/0403/sys/src/9/ip/tcp.c:190,1961997/0423/sys/src/9/ip/tcp.c:190,196 (short | long)
1997/0327    
void	getreseq(Tcpctl*, Tcp*, Block**, ushort*); 
void	localclose(Conv*, char*); 
void	procsyn(Conv*, Tcp*); 
void	tcpiput(Block*); 
1997/0423    
void	tcpiput(Media*, Block*); 
1997/0327    
void	tcpoutput(Conv*); 
int	tcptrim(Tcpctl*, Tcp*, Block**, ushort*); 
void	tcpstart(Conv*, int, ushort); 
1997/0403/sys/src/9/ip/tcp.c:1052,10581997/0423/sys/src/9/ip/tcp.c:1052,1058
1997/0327    
} 
 
void 
tcpiput(Block *bp) 
1997/0423    
tcpiput(Media *m, Block *bp) 
1997/0327    
{ 
	Tcp seg; 
	Tcphdr *h; 
1997/0403/sys/src/9/ip/tcp.c:1062,10671997/0423/sys/src/9/ip/tcp.c:1062,1068
1997/0327    
	Ipaddr source, dest; 
	Conv *spec, *gen, *s, **p; 
 
1997/0423    
	USED(m); 
1997/0327    
	h = (Tcphdr*)(bp->rp); 
 
	dest = nhgetl(h->tcpdst); 
1997/0423/sys/src/9/ip/tcp.c:232,2381997/0515/sys/src/9/ip/tcp.c:232,238 (short | long)
1997/0327    
		break; 
	} 
 
	if(oldstate == Syn_sent) 
1997/0515    
	if(oldstate == Syn_sent && newstate != Closed) 
1997/0327    
		Fsconnected(&fs, s, nil); 
} 
 
1997/0515/sys/src/9/ip/tcp.c:900,9061997/0802/sys/src/9/ip/tcp.c:900,906 (short | long)
1997/0327    
			return 1; 
	} 
	else { 
		if(low >= x && x >= high) 
1997/0802    
		if(x >= low || x <= high) 
1997/0327    
			return 1; 
	} 
	return 0; 
1997/0802/sys/src/9/ip/tcp.c:1469,14741997/0806/sys/src/9/ip/tcp.c:1469,1475 (short | long)
1997/0327    
		 * window probes to one 
		 */ 
		if(tcb->snd.wnd == 0){ 
1997/0806    
			tcp.wclosed++; 
1997/0327    
			if(sent != 0) { 
				if ((tcb->flags&FORCE) == 0) 
					break; 
1997/0806/sys/src/9/ip/tcp.c:186,1911997/0916/sys/src/9/ip/tcp.c:186,197 (short | long)
1997/0327    
Timer 	*timers;		/* List of active timers */ 
QLock 	tl;			/* Protect timer list */ 
 
1997/0916    
static struct Tcpstats 
{ 
	ulong	dup;		/* (partially) duplicated packets */ 
	ulong	dupb;		/* duplicated bytes */ 
} tstats; 
 
1997/0327    
void	addreseq(Tcpctl*, Tcp*, Block*, ushort); 
void	getreseq(Tcpctl*, Tcp*, Block**, ushort*); 
void	localclose(Conv*, char*); 
1997/0806/sys/src/9/ip/tcp.c:1250,12551997/0916/sys/src/9/ip/tcp.c:1256,1262
1997/0327    
	if(seg.seq != tcb->rcv.nxt) 
	if(length != 0 || (seg.flags & (SYN|FIN))) { 
		update(s, &seg); 
1997/0916    
		tcp.order++; 
1997/0327    
		addreseq(tcb, &seg, bp, length); 
		tcb->flags |= FORCE; 
		goto output; 
1997/0806/sys/src/9/ip/tcp.c:1469,14751997/0916/sys/src/9/ip/tcp.c:1476,1481
1997/0327    
		 * window probes to one 
		 */ 
		if(tcb->snd.wnd == 0){ 
1997/0806    
			tcp.wclosed++; 
1997/0327    
			if(sent != 0) { 
				if ((tcb->flags&FORCE) == 0) 
					break; 
1997/0806/sys/src/9/ip/tcp.c:1846,18511997/0916/sys/src/9/ip/tcp.c:1852,1859
1997/0327    
	dupcnt = tcb->rcv.nxt - seg->seq; 
	if(dupcnt > 0){ 
		tcb->rerecv += dupcnt; 
1997/0916    
		tstats.dup++; 
		tstats.dupb += dupcnt; 
1997/0327    
		if(seg->flags & SYN){ 
			seg->flags &= ~SYN; 
			seg->seq++; 
1997/0806/sys/src/9/ip/tcp.c:1924,19291997/0916/sys/src/9/ip/tcp.c:1932,1943
1997/0327    
	return "unknown control request"; 
} 
 
1997/0916    
int 
tcpstats(char *buf, int len) 
{ 
	return snprint(buf, len, "\tdupp %d dupb %d\n", tstats.dup, tstats.dupb); 
} 
 
1997/0327    
void 
tcpinit(Fs *fs) 
{ 
1997/0806/sys/src/9/ip/tcp.c:1937,19421997/0916/sys/src/9/ip/tcp.c:1951,1957
1997/0327    
	tcp.close = tcpclose; 
	tcp.rcv = tcpiput; 
	tcp.advise = tcpadvise; 
1997/0916    
	tcp.stats = tcpstats; 
1997/0327    
	tcp.ipproto = IP_TCPPROTO; 
	tcp.nc = Nchans; 
	tcp.ptclsize = sizeof(Tcpctl); 
1997/0916/sys/src/9/ip/tcp.c:805,8381997/1104/sys/src/9/ip/tcp.c:805,810 (short | long)
1997/0327    
} 
 
/* 
 *  flush an incoming call; send a reset to the remote side and close the 
 *  conversation 
 */ 
void 
tcpflushincoming(Conv *s) 
{ 
	Tcp seg; 
	byte dst[4]; 
	Tcpctl *tcb; 
                 
	tcb = (Tcpctl*)s->ptcl; 
                 
	seg.source = s->rport; 
	seg.dest = s->lport; 
	seg.flags = ACK; 
	seg.seq = tcb->snd.ptr; 
	tcb->last_ack = tcb->rcv.nxt; 
	seg.ack = tcb->rcv.nxt; 
                 
	if(s->laddr == 0) { 
		hnputl(dst, s->raddr); 
		s->laddr = Mediagetsrc(dst); 
	} 
	sndrst(s->raddr, s->laddr, 0, &seg); 
	localclose(s, nil); 
} 
                 
/* 
 *  send a reset to the remote side and close the conversation 
 */ 
char* 
1997/1104/sys/src/9/ip/tcp.c:14,191998/0306/sys/src/9/ip/tcp.c:14,20 (short | long)
1997/0327    
	TCP_IPLEN	= 8, 
	TCP_PHDRSIZE	= 12, 
	TCP_HDRSIZE	= 20, 
1998/0306    
	TCP_TCBPHDRSZ	= 40, 
1997/0327    
	TCP_PKT		= TCP_IPLEN+TCP_PHDRSIZE, 
	TimerOFF	= 0, 
	TimerON		= 1, 
1997/1104/sys/src/9/ip/tcp.c:85,1111998/0306/sys/src/9/ip/tcp.c:86,112
1997/0327    
typedef struct Tcphdr Tcphdr; 
struct Tcphdr 
{ 
	byte	vihl;		/* Version and header length */ 
	byte	tos;		/* Type of service */ 
	byte	length[2];	/* packet length */ 
	byte	id[2];		/* Identification */ 
	byte	frag[2];	/* Fragment information */ 
	byte	Unused; 
	byte	proto; 
	byte	tcplen[2]; 
	byte	tcpsrc[4]; 
	byte	tcpdst[4]; 
	byte	tcpsport[2]; 
	byte	tcpdport[2]; 
	byte	tcpseq[4]; 
	byte	tcpack[4]; 
	byte	tcpflag[2]; 
	byte	tcpwin[2]; 
	byte	tcpcksum[2]; 
	byte	tcpurg[2]; 
1998/0306    
	uchar	vihl;		/* Version and header length */ 
	uchar	tos;		/* Type of service */ 
	uchar	length[2];	/* packet length */ 
	uchar	id[2];		/* Identification */ 
	uchar	frag[2];	/* Fragment information */ 
	uchar	Unused; 
	uchar	proto; 
	uchar	tcplen[2]; 
	uchar	tcpsrc[4]; 
	uchar	tcpdst[4]; 
	uchar	tcpsport[2]; 
	uchar	tcpdport[2]; 
	uchar	tcpseq[4]; 
	uchar	tcpack[4]; 
	uchar	tcpflag[2]; 
	uchar	tcpwin[2]; 
	uchar	tcpcksum[2]; 
	uchar	tcpurg[2]; 
1997/0327    
	/* Options segment */ 
	byte	tcpopt[2]; 
	byte	tcpmss[2]; 
1998/0306    
	uchar	tcpopt[2]; 
	uchar	tcpmss[2]; 
1997/0327    
}; 
 
typedef struct Tcp Tcp; 
1997/1104/sys/src/9/ip/tcp.c:115,1211998/0306/sys/src/9/ip/tcp.c:116,122
1997/0327    
	ushort	dest; 
	ulong	seq; 
	ulong	ack; 
	byte	flags; 
1998/0306    
	uchar	flags; 
1997/0327    
	ushort	wnd; 
	ushort	urg; 
	ushort	mss; 
1997/1104/sys/src/9/ip/tcp.c:134,1421998/0306/sys/src/9/ip/tcp.c:135,143
1997/0327    
struct Tcpctl 
{ 
	QLock; 
	byte	state;			/* Connection state */ 
	byte	type;			/* Listening or active connection */ 
	byte	code;			/* Icmp code */ 
1998/0306    
	uchar	state;			/* Connection state */ 
	uchar	type;			/* Listening or active connection */ 
	uchar	code;			/* Icmp code */ 
1997/0327    
	struct { 
		ulong	una;		/* Unacked data pointer */ 
		ulong	nxt;		/* Next sequence expected */ 
1997/1104/sys/src/9/ip/tcp.c:147,1531998/0306/sys/src/9/ip/tcp.c:148,154
1997/0327    
		ulong	wl2; 
	} snd; 
	struct { 
		ulong	nxt;		/* Receive pointer to next byte slot */ 
1998/0306    
		ulong	nxt;		/* Receive pointer to next uchar slot */ 
1997/0327    
		ushort	wnd;		/* Receive window incoming */ 
		ulong	urg;		/* Urgent pointer */ 
		int	blocked; 
1997/1104/sys/src/9/ip/tcp.c:162,1691998/0306/sys/src/9/ip/tcp.c:163,170
1997/0327    
	ushort	window;			/* Recevive window */ 
	int	max_snd;		/* Max send */ 
	ulong	last_ack;		/* Last acknowledege received */ 
	byte	backoff;		/* Exponential backoff counter */ 
	byte	flags;			/* State flags */ 
1998/0306    
	uchar	backoff;		/* Exponential backoff counter */ 
	uchar	flags;			/* State flags */ 
1997/0327    
	ulong	sndcnt;			/* Amount of data in send queue */ 
	Reseq	*reseq;			/* Resequencing queue */ 
	Timer	timer;			/* Activity timer */ 
1997/1104/sys/src/9/ip/tcp.c:175,1841998/0306/sys/src/9/ip/tcp.c:176,186
1997/0327    
	int	kacounter;		/* count down for keep alive */ 
	int	f2counter;		/* count down for finwait2 state */ 
	uint	sndsyntime;		/* time syn sent */ 
	char	ascstate[128]; 
1998/0306    
 
	Tcphdr	protohdr;		/* prototype header */ 
1997/0327    
}; 
 
#define DBG(x)	if((logmask & Logtcpmsg) && (iponly == 0 || x == iponly))netlog 
1998/0306    
#define DBG(x)	if((logmask & Logtcpmsg) && (iponlyset == 0 || memcmp(x, iponly+12, 4) == 0))netlog 
1997/0327    
 
Proto	tcp; 
int	tcp_irtt = DEF_RTT;	/* Initial guess at round trip time */ 
1997/1104/sys/src/9/ip/tcp.c:189,1951998/0306/sys/src/9/ip/tcp.c:191,197
1997/0916    
static struct Tcpstats 
{ 
	ulong	dup;		/* (partially) duplicated packets */ 
	ulong	dupb;		/* duplicated bytes */ 
1998/0306    
	ulong	dupb;		/* duplicated uchars */ 
1997/0916    
} tstats; 
 
1997/0327    
void	addreseq(Tcpctl*, Tcp*, Block*, ushort); 
1997/1104/sys/src/9/ip/tcp.c:196,2021998/0306/sys/src/9/ip/tcp.c:198,204
1997/0327    
void	getreseq(Tcpctl*, Tcp*, Block**, ushort*); 
void	localclose(Conv*, char*); 
void	procsyn(Conv*, Tcp*); 
1997/0423    
void	tcpiput(Media*, Block*); 
1998/0306    
void	tcpiput(uchar*, Block*); 
1997/0327    
void	tcpoutput(Conv*); 
int	tcptrim(Tcpctl*, Tcp*, Block**, ushort*); 
void	tcpstart(Conv*, int, ushort); 
1997/1104/sys/src/9/ip/tcp.c:206,2151998/0306/sys/src/9/ip/tcp.c:208,217
1997/0327    
void	tcpacktimer(Conv*); 
 
void 
tcpsetstate(Conv *s, byte newstate) 
1998/0306    
tcpsetstate(Conv *s, uchar newstate) 
1997/0327    
{ 
	Tcpctl *tcb; 
	byte oldstate; 
1998/0306    
	uchar oldstate; 
1997/0327    
 
	tcb = (Tcpctl*)s->ptcl; 
 
1997/1104/sys/src/9/ip/tcp.c:231,2371998/0306/sys/src/9/ip/tcp.c:233,239
1997/0327    
		qclose(s->eq); 
		s->lport = 0;		/* This connection is toast */ 
		s->rport = 0; 
		s->raddr = 0; 
1998/0306    
		ipmove(s->raddr, IPnoaddr); 
1997/0327    
 
	case Close_wait:		/* Remote closes */ 
		qhangup(s->rq, nil); 
1997/1104/sys/src/9/ip/tcp.c:255,2831998/0306/sys/src/9/ip/tcp.c:257,282
1997/0403    
	return nil; 
1997/0327    
} 
 
int 
tcpstate(char **msg, Conv *c) 
1998/0306    
static int 
tcpstate(Conv *c, char *state, int n) 
1997/0327    
{ 
	Tcpctl *s; 
	int isclose; 
 
	s = (Tcpctl*)(c->ptcl); 
 
	isclose = 0; 
	if(s->state == Closed) 
		isclose = 1; 
                 
/*	snprint(s->ascstate, sizeof(s->ascstate), 
		"tcnt %d tnxt %lux tuna %lux twnd %d rack %lux rnxt %lux rwnd %d", 
		s->sndcnt, s->snd.nxt, s->snd.una, s->snd.wnd, 
		s->last_ack, s->rcv.nxt, s->rcv.wnd);*/ 
	snprint(s->ascstate, sizeof(s->ascstate), 
1998/0306    
	return snprint(state, n, 
1997/0327    
		"%s srtt %d mdev %d timer.start %d timer.count %d\n", 
		tcpstates[s->state], s->srtt, s->mdev, 
		s->timer.start, s->timer.count); 
1998/0306    
} 
1997/0327    
 
	*msg = s->ascstate; 
	return isclose; 
1998/0306    
static int 
tcpinuse(Conv *c) 
{ 
	Tcpctl *s; 
 
	s = (Tcpctl*)(c->ptcl); 
	return s->state != Closed; 
1997/0327    
} 
 
1997/0403    
static char* 
1997/1104/sys/src/9/ip/tcp.c:533,5381998/0306/sys/src/9/ip/tcp.c:532,538
1997/0327    
inittcpctl(Conv *s) 
{ 
	Tcpctl *tcb; 
1998/0306    
	Tcphdr *h; 
1997/0327    
 
	tcb = (Tcpctl*)s->ptcl; 
 
1997/1104/sys/src/9/ip/tcp.c:550,5551998/0306/sys/src/9/ip/tcp.c:550,566
1997/0327    
	tcb->acktimer.start = TCP_ACK / MSPTICK; 
	tcb->acktimer.func = tcpacktimer; 
	tcb->acktimer.arg = s; 
1998/0306    
 
	/* create a prototype(pseudo) header */ 
	if(ipcmp(s->laddr, IPnoaddr) == 0) 
		findlocalip(s->laddr, s->raddr); 
	h = &tcb->protohdr; 
	memset(h, 0, sizeof(*h)); 
	h->proto = IP_TCPPROTO; 
	hnputs(h->tcpsport, s->lport); 
	hnputs(h->tcpdport, s->rport); 
	v6tov4(h->tcpsrc, s->laddr); 
	v6tov4(h->tcpdst, s->raddr); 
1997/0327    
} 
 
/* mtu (- TCP + IP hdr len) of 1st hop */ 
1997/1104/sys/src/9/ip/tcp.c:556,5701998/0306/sys/src/9/ip/tcp.c:567,579
1997/0327    
int 
tcpmtu(Conv *s) 
{ 
	Media *m; 
	byte dst[4], dummy[4]; 
1998/0306    
	Ipifc *ifc; 
1997/0327    
	int mtu; 
 
	mtu = 0; 
	hnputl(dst, s->raddr); 
	m = Mediaroute(dst, dummy); 
	if(m != nil) 
		mtu = m->maxmtu - m->hsize - (TCP_PKT + TCP_HDRSIZE); 
1998/0306    
	ifc = findipifc(s->raddr, 0); 
	if(ifc != nil) 
		mtu = ifc->maxmtu - ifc->m->hsize - (TCP_PKT + TCP_HDRSIZE); 
1997/0327    
	if(mtu < 4) 
		mtu = DEF_MSS; 
	return mtu; 
1997/1104/sys/src/9/ip/tcp.c:647,6691998/0306/sys/src/9/ip/tcp.c:656,671
1997/0327    
		data->wp += hdrlen + TCP_PKT; 
	} 
 
                 
	memmove(data->rp, ph, TCP_PKT); 
                 
1998/0306    
	/* copy in pseudo ip header plus port numbers */ 
1997/0327    
	h = (Tcphdr *)(data->rp); 
	h->proto = IP_TCPPROTO; 
	h->frag[0] = 0; 
	h->frag[1] = 0; 
1998/0306    
	memmove(h, ph, TCP_TCBPHDRSZ); 
 
	/* copy in variable bits */ 
1997/0327    
	hnputs(h->tcplen, hdrlen + dlen); 
	hnputs(h->tcpsport, tcph->source); 
	hnputs(h->tcpdport, tcph->dest); 
	hnputl(h->tcpseq, tcph->seq); 
	hnputl(h->tcpack, tcph->ack); 
	hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags); 
	hnputs(h->tcpwin, tcph->wnd); 
	h->tcpcksum[0] = 0; 
	h->tcpcksum[1] = 0; 
	h->Unused = 0; 
	hnputs(h->tcpurg, tcph->urg); 
 
	if(tcph->mss != 0){ 
1997/1104/sys/src/9/ip/tcp.c:674,6801998/0306/sys/src/9/ip/tcp.c:676,682
1997/0327    
	csum = ptclcsum(data, TCP_IPLEN, hdrlen+dlen+TCP_PHDRSIZE); 
	hnputs(h->tcpcksum, csum); 
 
	DBG(nhgetl(h->tcpdst))(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1998/0306    
	DBG(h->tcpdst)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1997/0327    
		tcph->source, tcph->dest, 
		tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), 
		tcph->wnd, dlen); 
1997/1104/sys/src/9/ip/tcp.c:686,6921998/0306/sys/src/9/ip/tcp.c:688,694
1997/0327    
ntohtcp(Tcp *tcph, Block **bpp) 
{ 
	Tcphdr *h; 
	byte *optr; 
1998/0306    
	uchar *optr; 
1997/0327    
	ushort hdrlen; 
	ushort i, optlen; 
 
1997/1104/sys/src/9/ip/tcp.c:715,7211998/0306/sys/src/9/ip/tcp.c:717,723
1997/0327    
	if(*bpp == nil) 
		return -1; 
 
	DBG(nhgetl(h->tcpsrc))(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1998/0306    
	DBG(h->tcpsrc)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1997/0327    
		tcph->source, tcph->dest, 
		tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), 
		tcph->wnd, nhgets(h->length)-hdrlen-TCP_PKT); 
1997/1104/sys/src/9/ip/tcp.c:754,7811998/0306/sys/src/9/ip/tcp.c:756,784
1997/0327    
	tcb->sndsyntime = msec; 
} 
 
1998/0306    
 
/* 
 *  called with v4 (4 byte) addresses 
 */ 
1997/0327    
void 
sndrst(Ipaddr source, Ipaddr dest, ushort length, Tcp *seg) 
1998/0306    
sndrst(uchar *source, uchar *dest, ushort length, Tcp *seg) 
1997/0327    
{ 
	ushort tmp; 
	Tcphdr ph; 
	Block *hbp; 
	byte rflags; 
1998/0306    
	uchar rflags; 
1997/0327    
 
	if(seg->flags & RST) 
		return; 
 
                 
	hnputl(ph.tcpsrc, dest); 
	hnputl(ph.tcpdst, source); 
1998/0306    
	/* make pseudo header */ 
	memset(&ph, 0, sizeof(ph)); 
	v6tov4(ph.tcpsrc, dest); 
	v6tov4(ph.tcpdst, source); 
1997/0327    
	ph.proto = IP_TCPPROTO; 
	hnputs(ph.tcplen, TCP_HDRSIZE); 
1998/0306    
	hnputs(ph.tcpsport, seg->dest); 
	hnputs(ph.tcpdport, seg->source); 
1997/0327    
 
	/* Swap port numbers */ 
	tmp = seg->dest; 
	seg->dest = seg->source; 
	seg->source = tmp; 
                 
	rflags = RST; 
 
	/* convince the other end that this reset is in band */ 
1997/1104/sys/src/9/ip/tcp.c:811,8171998/0306/sys/src/9/ip/tcp.c:814,819
1997/0327    
tcphangup(Conv *s) 
{ 
	Tcp seg; 
	byte dst[4]; 
	Tcpctl *tcb; 
	Tcphdr ph; 
	Block *hbp; 
1997/1104/sys/src/9/ip/tcp.c:823,8301998/0306/sys/src/9/ip/tcp.c:825,830
1997/0327    
	} 
	qlock(tcb); 
	if(s->raddr != 0) { 
		seg.source = s->lport; 
		seg.dest = s->rport; 
		seg.flags = RST | ACK; 
		seg.ack = tcb->rcv.nxt; 
		seg.seq = tcb->snd.ptr; 
1997/1104/sys/src/9/ip/tcp.c:832,8461998/0306/sys/src/9/ip/tcp.c:832,839
1997/0327    
		seg.urg = 0; 
		seg.mss = 0; 
		tcb->last_ack = tcb->rcv.nxt; 
		if(s->laddr == 0) { 
			hnputl(dst, s->raddr); 
			s->laddr = Mediagetsrc(dst); 
		} 
		hnputl(ph.tcpsrc, s->laddr); 
		hnputl(ph.tcpdst, s->raddr); 
		ph.proto = IP_TCPPROTO; 
		hnputs(ph.tcplen, TCP_HDRSIZE); 
		hbp = htontcp(&seg, nil, &ph); 
1998/0306    
		hbp = htontcp(&seg, nil, &tcb->protohdr); 
1997/0327    
		ipoput(hbp, 0, s->ttl); 
	} 
	localclose(s, nil); 
1997/1104/sys/src/9/ip/tcp.c:850,8591998/0306/sys/src/9/ip/tcp.c:843,853
1997/0327    
} 
 
Conv* 
tcpincoming(Conv *s, Tcp *segp, Ipaddr src, Ipaddr dst) 
1998/0306    
tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst) 
1997/0327    
{ 
	Conv *new; 
	Tcpctl *tcb; 
1998/0306    
	Tcphdr *h; 
1997/0327    
 
	new = Fsnewcall(&fs, s, src, segp->source, dst, segp->dest); 
	if(new == nil) 
1997/1104/sys/src/9/ip/tcp.c:867,8721998/0306/sys/src/9/ip/tcp.c:861,874
1997/0327    
	tcb->acktimer.arg = new; 
	tcb->acktimer.state = TimerOFF; 
 
1998/0306    
	h = &tcb->protohdr; 
	memset(h, 0, sizeof(*h)); 
	h->proto = IP_TCPPROTO; 
	hnputs(h->tcpsport, new->lport); 
	hnputs(h->tcpdport, new->rport); 
	v6tov4(h->tcpsrc, dst); 
	v6tov4(h->tcpdst, src); 
 
1997/0327    
	return new; 
} 
 
1997/1104/sys/src/9/ip/tcp.c:1030,10361998/0306/sys/src/9/ip/tcp.c:1032,1038
1997/0327    
} 
 
void 
1997/0423    
tcpiput(Media *m, Block *bp) 
1998/0306    
tcpiput(uchar*, Block *bp) 
1997/0327    
{ 
	Tcp seg; 
	Tcphdr *h; 
1997/1104/sys/src/9/ip/tcp.c:1037,10501998/0306/sys/src/9/ip/tcp.c:1039,1051
1997/0327    
	int hdrlen; 
	Tcpctl *tcb; 
	ushort length; 
	Ipaddr source, dest; 
1998/0306    
	uchar source[IPaddrlen], dest[IPaddrlen]; 
1997/0327    
	Conv *spec, *gen, *s, **p; 
 
1997/0423    
	USED(m); 
1997/0327    
	h = (Tcphdr*)(bp->rp); 
 
	dest = nhgetl(h->tcpdst); 
	source = nhgetl(h->tcpsrc); 
1998/0306    
	v4tov6(dest, h->tcpdst); 
	v4tov6(source, h->tcpsrc); 
1997/0327    
	length = nhgets(h->length); 
 
	h->Unused = 0; 
1997/1104/sys/src/9/ip/tcp.c:1076,10831998/0306/sys/src/9/ip/tcp.c:1077,1085
1997/0327    
	/* Look for a connection. failing that look for a listener. */ 
	for(p = tcp.conv; *p; p++) { 
		s = *p; 
		if(s->rport == seg.source && 
		   s->lport == seg.dest && s->raddr == source) 
1998/0306    
		if(s->rport == seg.source) 
		if(s->lport == seg.dest) 
		if(ipcmp(s->raddr, source) == 0) 
1997/0327    
			break; 
	} 
	s = *p; 
1997/1104/sys/src/9/ip/tcp.c:1116,11221998/0306/sys/src/9/ip/tcp.c:1118,1124
1997/0327    
				continue; 
			if(tcb->state != Listen) 
				continue; 
			if(s->rport == 0 && s->raddr == 0) { 
1998/0306    
			if(s->rport == 0 && ipcmp(s->raddr, IPnoaddr) == 0) { 
1997/0327    
				if(s->lport == seg.dest){ 
					spec = s; 
					break; 
1997/1104/sys/src/9/ip/tcp.c:1414,14201998/0306/sys/src/9/ip/tcp.c:1416,1421
1997/0327    
	int x; 
	Tcp seg; 
	int msgs; 
	Tcphdr ph; 
	Tcpctl *tcb; 
	Block *hbp, *bp; 
	int sndcnt, n, first; 
1997/1104/sys/src/9/ip/tcp.c:1547,15631998/0306/sys/src/9/ip/tcp.c:1548,1555
1997/0327    
		if(seq_gt(tcb->snd.ptr,tcb->snd.nxt)) 
			tcb->snd.nxt = tcb->snd.ptr; 
 
		/* Fill in fields of pseudo IP header */ 
		hnputl(ph.tcpdst, s->raddr); 
		if(s->laddr == 0) 
			s->laddr = Mediagetsrc(ph.tcpdst); 
                 
		hnputl(ph.tcpsrc, s->laddr); 
		hnputs(ph.tcpsport, s->lport); 
		hnputs(ph.tcpdport, s->rport); 
                 
		/* Build header, link data and compute cksum */ 
		hbp = htontcp(&seg, bp, &ph); 
1998/0306    
		hbp = htontcp(&seg, bp, &tcb->protohdr); 
1997/0327    
		if(hbp == nil) { 
			freeblist(bp); 
			return; 
1997/1104/sys/src/9/ip/tcp.c:1588,16001998/0306/sys/src/9/ip/tcp.c:1580,1591
1997/0327    
} 
 
/* 
 *  the BSD convention (hack?) for keep alives.  resend last byte acked. 
1998/0306    
 *  the BSD convention (hack?) for keep alives.  resend last uchar acked. 
1997/0327    
 */ 
void 
tcpkeepalive(Conv *s) 
{ 
	Tcp seg; 
	Tcphdr ph; 
	Tcpctl *tcb; 
	Block *hbp,*dbp; 
 
1997/1104/sys/src/9/ip/tcp.c:1618,16331998/0306/sys/src/9/ip/tcp.c:1609,1616
1997/0327    
		dbp->wp++; 
	} 
 
	/* Fill in fields of pseudo IP header */ 
	hnputl(ph.tcpdst, s->raddr); 
	if(s->laddr == 0) 
		s->laddr = Mediagetsrc(ph.tcpdst); 
	hnputl(ph.tcpsrc, s->laddr); 
	hnputs(ph.tcpsport, s->lport); 
	hnputs(ph.tcpdport, s->rport); 
                 
	/* Build header, link data and compute cksum */ 
	hbp = htontcp(&seg, dbp, &ph); 
1998/0306    
	hbp = htontcp(&seg, dbp, &tcb->protohdr); 
1997/0327    
	if(hbp == nil) { 
		freeblist(dbp); 
		return; 
1997/1104/sys/src/9/ip/tcp.c:1792,17981998/0306/sys/src/9/ip/tcp.c:1775,1781
1997/0327    
{ 
	ushort len; 
	Block *nbp; 
	byte accept; 
1998/0306    
	uchar accept; 
1997/0327    
	int dupcnt, excess; 
 
	accept = 0; 
1997/1104/sys/src/9/ip/tcp.c:1866,18791998/0306/sys/src/9/ip/tcp.c:1849,1863
1997/0327    
{ 
	Tcphdr *h; 
	Tcpctl *tcb; 
	Ipaddr source, dest; 
1998/0306    
	uchar source[IPaddrlen]; 
	uchar dest[IPaddrlen]; 
1997/0327    
	ushort psource, pdest; 
	Conv *s, **p; 
 
	h = (Tcphdr*)(bp->rp); 
 
	dest = nhgetl(h->tcpdst); 
	source = nhgetl(h->tcpsrc); 
1998/0306    
	v4tov6(dest, h->tcpdst); 
	v4tov6(source, h->tcpsrc); 
1997/0327    
	psource = nhgets(h->tcpsport); 
	pdest = nhgets(h->tcpdport); 
 
1997/1104/sys/src/9/ip/tcp.c:1880,18871998/0306/sys/src/9/ip/tcp.c:1864,1873
1997/0327    
	/* Look for a connection */ 
	for(p = tcp.conv; *p; p++) { 
		s = *p; 
		if(s->rport == pdest && s->lport == psource) 
		if(s->raddr == dest && s->laddr == source){ 
1998/0306    
		if(s->rport == pdest) 
		if(s->lport == psource) 
		if(ipcmp(s->raddr, dest) == 0) 
		if(ipcmp(s->laddr, source) == 0){ 
1997/0327    
			tcb = (Tcpctl*)s->ptcl; 
			qlock(tcb); 
			switch(tcb->state){ 
1997/1104/sys/src/9/ip/tcp.c:1896,19011998/0306/sys/src/9/ip/tcp.c:1882,1888
1997/0327    
	freeblist(bp); 
} 
 
1998/0306    
/* called with c->car qlocked */ 
1997/0327    
char* 
tcpctl(Conv* c, char** f, int n) 
{ 
1997/1104/sys/src/9/ip/tcp.c:1907,19131998/0306/sys/src/9/ip/tcp.c:1894,1907
1997/0916    
int 
tcpstats(char *buf, int len) 
{ 
	return snprint(buf, len, "\tdupp %d dupb %d\n", tstats.dup, tstats.dupb); 
1998/0306    
	int n; 
 
	n = snprint(buf, len, 
		"tcp: csum %d hlen %d len %d order %d rexmit %d", 
		tcp.csumerr, tcp.hlenerr, tcp.lenerr, tcp.order, tcp.rexmit); 
	n += snprint(buf+n, len-n, " dupp %d dupb %d\n", 
		tstats.dup, tstats.dupb); 
	return n; 
1997/0916    
} 
 
1997/0327    
void 
1997/1104/sys/src/9/ip/tcp.c:1924,19291998/0306/sys/src/9/ip/tcp.c:1918,1924
1997/0327    
	tcp.rcv = tcpiput; 
	tcp.advise = tcpadvise; 
1997/0916    
	tcp.stats = tcpstats; 
1998/0306    
	tcp.inuse = tcpinuse; 
1997/0327    
	tcp.ipproto = IP_TCPPROTO; 
	tcp.nc = Nchans; 
	tcp.ptclsize = sizeof(Tcpctl); 
1997/1104/sys/src/9/ip/tcp.c:1932,19341998/0306/sys/src/9/ip/tcp.c:1927,1930
1997/0327    
 
	Fsproto(fs, &tcp); 
} 
1998/0306    
 
1998/0306/sys/src/9/ip/tcp.c:180,2041998/0313/sys/src/9/ip/tcp.c:180,231 (short | long)
1998/0306    
	Tcphdr	protohdr;		/* prototype header */ 
1997/0327    
}; 
 
1998/0306    
#define DBG(x)	if((logmask & Logtcpmsg) && (iponlyset == 0 || memcmp(x, iponly+12, 4) == 0))netlog 
1997/0327    
                 
Proto	tcp; 
int	tcp_irtt = DEF_RTT;	/* Initial guess at round trip time */ 
ushort	tcp_mss  = DEF_MSS;	/* Maximum segment size to be sent */ 
Timer 	*timers;		/* List of active timers */ 
QLock 	tl;			/* Protect timer list */ 
 
1997/0916    
static struct Tcpstats 
1998/0313    
/* MIB II counters */ 
typedef struct Tcpstats Tcpstats; 
struct Tcpstats 
1997/0916    
{ 
	ulong	dup;		/* (partially) duplicated packets */ 
1998/0306    
	ulong	dupb;		/* duplicated uchars */ 
1997/0916    
} tstats; 
1998/0313    
	ulong	tcpRtoAlgorithm; 
	ulong	tcpRtoMin; 
	ulong	tcpRtoMax; 
	ulong	tcpMaxConn; 
	ulong	tcpActiveOpens; 
	ulong	tcpPassiveOpens; 
	ulong	tcpAttemptFails; 
	ulong	tcpEstabResets; 
	ulong	tcpCurrEstab; 
	ulong	tcpInSegs; 
	ulong	tcpOutSegs; 
	ulong	tcpRetransSegs; 
	ulong	InErrs; 
	ulong	OutRsts; 
}; 
1997/0916    
 
1998/0313    
typedef struct Tcppriv Tcppriv; 
struct Tcppriv 
{ 
	Timer 	*timers;		/* List of active timers */ 
	QLock 	tl;			/* Protect timer list */ 
	Rendez	tcpr;			/* used by tcpackproc */ 
 
	/* MIB stats */ 
	Tcpstats tstats; 
 
	/* non-MIB stats */ 
	ulong		csumerr;		/* checksum errors */ 
	ulong		hlenerr;		/* header length error */ 
	ulong		lenerr;			/* short packet */ 
	ulong		order;			/* out of order */ 
 
}; 
 
1997/0327    
void	addreseq(Tcpctl*, Tcp*, Block*, ushort); 
void	getreseq(Tcpctl*, Tcp*, Block**, ushort*); 
void	localclose(Conv*, char*); 
void	procsyn(Conv*, Tcp*); 
1998/0306    
void	tcpiput(uchar*, Block*); 
1998/0313    
void	tcpiput(Proto*, uchar*, Block*); 
1997/0327    
void	tcpoutput(Conv*); 
int	tcptrim(Tcpctl*, Tcp*, Block**, ushort*); 
void	tcpstart(Conv*, int, ushort); 
1998/0306/sys/src/9/ip/tcp.c:212,2181998/0313/sys/src/9/ip/tcp.c:239,248
1997/0327    
{ 
	Tcpctl *tcb; 
1998/0306    
	uchar oldstate; 
1998/0313    
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	tpriv = s->p->priv; 
 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
	oldstate = tcb->state; 
1998/0306/sys/src/9/ip/tcp.c:219,2241998/0313/sys/src/9/ip/tcp.c:249,259
1997/0327    
	if(oldstate == newstate) 
		return; 
 
1998/0313    
	if(oldstate == Established) 
		tpriv->tstats.tcpCurrEstab--; 
	if(newstate == Established) 
		tpriv->tstats.tcpCurrEstab++; 
 
1997/0327    
	/* 
	  print("%d/%d %s->%s\n", s->lport, s->rport, 
			tcpstates[oldstate], tcpstates[newstate]); 
1998/0306/sys/src/9/ip/tcp.c:241,2471998/0313/sys/src/9/ip/tcp.c:276,282
1997/0327    
	} 
 
1997/0515    
	if(oldstate == Syn_sent && newstate != Closed) 
1997/0327    
		Fsconnected(&fs, s, nil); 
1998/0313    
		Fsconnected(s, nil); 
1997/0327    
} 
 
static char* 
1998/0306/sys/src/9/ip/tcp.c:288,2941998/0313/sys/src/9/ip/tcp.c:323,329
1997/0403    
	if(e != nil) 
		return e; 
1997/0327    
	tcpstart(c, TCP_LISTEN, QMAX); 
	Fsconnected(&fs, c, nil); 
1998/0313    
	Fsconnected(c, nil); 
1997/0403    
 
	return nil; 
1997/0327    
} 
1998/0306/sys/src/9/ip/tcp.c:311,3171998/0313/sys/src/9/ip/tcp.c:346,352
1997/0327    
		/* 
		 *  reset any incoming calls to this listener 
		 */ 
		Fsconnected(&fs, c, "Hangup"); 
1998/0313    
		Fsconnected(c, "Hangup"); 
1997/0327    
 
		qlock(tcb); 
		localclose(c, nil); 
1998/0306/sys/src/9/ip/tcp.c:376,3851998/0313/sys/src/9/ip/tcp.c:411,420
1997/0327    
 *  get remote sender going if it was flow controlled due to a closed window 
 */ 
static void 
deltimer(Timer *t) 
1998/0313    
deltimer(Tcppriv *tpriv, Timer *t) 
1997/0327    
{ 
	if(timers == t) 
		timers = t->next; 
1998/0313    
	if(tpriv->timers == t) 
		tpriv->timers = t->next; 
1997/0327    
	if(t->next) 
		t->next->prev = t->prev; 
	if(t->prev) 
1998/0306/sys/src/9/ip/tcp.c:423,4441998/0313/sys/src/9/ip/tcp.c:458,483
1997/0327    
} 
 
void 
tcpackproc(void*) 
1998/0313    
tcpackproc(void *a) 
1997/0327    
{ 
	Timer *t, *tp, *timeo; 
	static Rendez tcpr; 
1998/0313    
	Proto *tcp; 
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	tcp = a; 
	tpriv = tcp->priv; 
 
1997/0327    
	for(;;) { 
		tsleep(&tcpr, return0, 0, MSPTICK); 
1998/0313    
		tsleep(&tpriv->tcpr, return0, 0, MSPTICK); 
1997/0327    
 
		qlock(&tl); 
1998/0313    
		qlock(&tpriv->tl); 
1997/0327    
		timeo = nil; 
		for(t = timers; t != nil; t = tp) { 
1998/0313    
		for(t = tpriv->timers; t != nil; t = tp) { 
1997/0327    
			tp = t->next; 
 			if(t->state == TimerON) { 
				t->count--; 
				if(t->count == 0) { 
					deltimer(t); 
1998/0313    
					deltimer(tpriv, t); 
1997/0327    
					t->state = TimerDONE; 
					t->next = timeo; 
					timeo = t; 
1998/0306/sys/src/9/ip/tcp.c:445,4511998/0313/sys/src/9/ip/tcp.c:484,490
1997/0327    
				} 
			} 
		} 
		qunlock(&tl); 
1998/0313    
		qunlock(&tpriv->tl); 
1997/0327    
 
		for(;;) { 
			t = timeo; 
1998/0306/sys/src/9/ip/tcp.c:460,4941998/0313/sys/src/9/ip/tcp.c:499,533
1997/0327    
} 
 
void 
tcpgo(Timer *t) 
1998/0313    
tcpgo(Tcppriv *tpriv, Timer *t) 
1997/0327    
{ 
	if(t == nil || t->start == 0) 
		return; 
 
	qlock(&tl); 
1998/0313    
	qlock(&tpriv->tl); 
1997/0327    
	t->count = t->start; 
	if(t->state != TimerON) { 
		t->state = TimerON; 
		t->prev = nil; 
		t->next = timers; 
1998/0313    
		t->next = tpriv->timers; 
1997/0327    
		if(t->next) 
			t->next->prev = t; 
		timers = t; 
1998/0313    
		tpriv->timers = t; 
1997/0327    
	} 
	qunlock(&tl); 
1998/0313    
	qunlock(&tpriv->tl); 
1997/0327    
} 
 
void 
tcphalt(Timer *t) 
1998/0313    
tcphalt(Tcppriv *tpriv, Timer *t) 
1997/0327    
{ 
	if(t == nil) 
		return; 
 
	qlock(&tl); 
1998/0313    
	qlock(&tpriv->tl); 
1997/0327    
	if(t->state == TimerON) 
		deltimer(t); 
1998/0313    
		deltimer(tpriv, t); 
1997/0327    
	t->state = TimerOFF; 
	qunlock(&tl); 
1998/0313    
	qunlock(&tpriv->tl); 
1997/0327    
} 
 
int 
1998/0306/sys/src/9/ip/tcp.c:505,5151998/0313/sys/src/9/ip/tcp.c:544,556
1997/0327    
{ 
	Tcpctl *tcb; 
	Reseq *rp,*rp1; 
1998/0313    
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	tpriv = s->p->priv; 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
	tcphalt(&tcb->timer); 
	tcphalt(&tcb->rtt_timer); 
1998/0313    
	tcphalt(tpriv, &tcb->timer); 
	tcphalt(tpriv, &tcb->rtt_timer); 
1997/0327    
 
	/* Flush reassembly queue; nothing more can arrive */ 
	for(rp = tcb->reseq; rp != nil; rp = rp1) { 
1998/0306/sys/src/9/ip/tcp.c:519,5251998/0313/sys/src/9/ip/tcp.c:560,566
1997/0327    
	} 
 
	if(tcb->state == Syn_sent) 
		Fsconnected(&fs, s, reason); 
1998/0313    
		Fsconnected(s, reason); 
1997/0327    
 
	qhangup(s->rq, reason); 
	qhangup(s->wq, reason); 
1998/0306/sys/src/9/ip/tcp.c:553,5591998/0313/sys/src/9/ip/tcp.c:594,600
1998/0306    
 
	/* create a prototype(pseudo) header */ 
	if(ipcmp(s->laddr, IPnoaddr) == 0) 
		findlocalip(s->laddr, s->raddr); 
1998/0313    
		findlocalip(s->p->f, s->laddr, s->raddr); 
1998/0306    
	h = &tcb->protohdr; 
	memset(h, 0, sizeof(*h)); 
	h->proto = IP_TCPPROTO; 
1998/0306/sys/src/9/ip/tcp.c:571,5771998/0313/sys/src/9/ip/tcp.c:612,618
1997/0327    
	int mtu; 
 
	mtu = 0; 
1998/0306    
	ifc = findipifc(s->raddr, 0); 
1998/0313    
	ifc = findipifc(s->p->f, s->raddr, 0); 
1998/0306    
	if(ifc != nil) 
		mtu = ifc->maxmtu - ifc->m->hsize - (TCP_PKT + TCP_HDRSIZE); 
1997/0327    
	if(mtu < 4) 
1998/0306/sys/src/9/ip/tcp.c:583,5891998/0313/sys/src/9/ip/tcp.c:624,633
1997/0327    
tcpstart(Conv *s, int mode, ushort window) 
{ 
	Tcpctl *tcb; 
1998/0313    
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	tpriv = s->p->priv; 
 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
	inittcpctl(s); 
1998/0306/sys/src/9/ip/tcp.c:592,6021998/0313/sys/src/9/ip/tcp.c:636,648
1997/0327    
 
	switch(mode) { 
	case TCP_LISTEN: 
1998/0313    
		tpriv->tstats.tcpPassiveOpens++; 
1997/0327    
		tcb->flags |= CLONE; 
		tcpsetstate(s, Listen); 
		break; 
 
	case TCP_CONNECT: 
1998/0313    
		tpriv->tstats.tcpActiveOpens++; 
1997/0327    
		/* Send SYN, go into SYN_SENT state */ 
		qlock(tcb); 
		tcb->flags |= ACTIVE; 
1998/0306/sys/src/9/ip/tcp.c:676,6851998/0313/sys/src/9/ip/tcp.c:722,731
1997/0327    
	csum = ptclcsum(data, TCP_IPLEN, hdrlen+dlen+TCP_PHDRSIZE); 
	hnputs(h->tcpcksum, csum); 
 
1998/0306    
	DBG(h->tcpdst)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1998/0313    
/*	netlog(f, Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1997/0327    
		tcph->source, tcph->dest, 
		tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), 
		tcph->wnd, dlen); 
1998/0313    
		tcph->wnd, dlen); */ 
1997/0327    
 
	return data; 
} 
1998/0306/sys/src/9/ip/tcp.c:717,7261998/0313/sys/src/9/ip/tcp.c:763,772
1997/0327    
	if(*bpp == nil) 
		return -1; 
 
1998/0306    
	DBG(h->tcpsrc)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1998/0313    
/*	netlog(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", 
1997/0327    
		tcph->source, tcph->dest, 
		tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), 
		tcph->wnd, nhgets(h->length)-hdrlen-TCP_PKT); 
1998/0313    
		tcph->wnd, nhgets(h->length)-hdrlen-TCP_PKT); */ 
1997/0327    
 
	optr = h->tcpopt; 
	for(i = TCP_HDRSIZE; i < hdrlen;) { 
1998/0306/sys/src/9/ip/tcp.c:761,7721998/0313/sys/src/9/ip/tcp.c:807,821
1998/0306    
 *  called with v4 (4 byte) addresses 
 */ 
1997/0327    
void 
1998/0306    
sndrst(uchar *source, uchar *dest, ushort length, Tcp *seg) 
1998/0313    
sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg) 
1997/0327    
{ 
	Tcphdr ph; 
	Block *hbp; 
1998/0306    
	uchar rflags; 
1998/0313    
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	tpriv = tcp->priv; 
 
1997/0327    
	if(seg->flags & RST) 
		return; 
 
1998/0306/sys/src/9/ip/tcp.c:779,7841998/0313/sys/src/9/ip/tcp.c:828,834
1998/0306    
	hnputs(ph.tcpsport, seg->dest); 
	hnputs(ph.tcpdport, seg->source); 
1997/0327    
 
1998/0313    
	tpriv->tstats.OutRsts++; 
1997/0327    
	rflags = RST; 
 
	/* convince the other end that this reset is in band */ 
1998/0306/sys/src/9/ip/tcp.c:804,8101998/0313/sys/src/9/ip/tcp.c:854,860
1997/0327    
	if(hbp == nil) 
		return; 
 
	ipoput(hbp, 0, MAXTTL); 
1998/0313    
	ipoput(tcp->f, hbp, 0, MAXTTL); 
1997/0327    
} 
 
/* 
1998/0306/sys/src/9/ip/tcp.c:821,8271998/0313/sys/src/9/ip/tcp.c:871,877
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
	if(waserror()){ 
		qunlock(tcb); 
		return up->error; 
1998/0313    
		return commonerror(); 
1997/0327    
	} 
	qlock(tcb); 
	if(s->raddr != 0) { 
1998/0306/sys/src/9/ip/tcp.c:834,8401998/0313/sys/src/9/ip/tcp.c:884,890
1997/0327    
		tcb->last_ack = tcb->rcv.nxt; 
		hnputs(ph.tcplen, TCP_HDRSIZE); 
1998/0306    
		hbp = htontcp(&seg, nil, &tcb->protohdr); 
1997/0327    
		ipoput(hbp, 0, s->ttl); 
1998/0313    
		ipoput(s->p->f, hbp, 0, s->ttl); 
1997/0327    
	} 
	localclose(s, nil); 
	poperror(); 
1998/0306/sys/src/9/ip/tcp.c:849,8551998/0313/sys/src/9/ip/tcp.c:899,905
1997/0327    
	Tcpctl *tcb; 
1998/0306    
	Tcphdr *h; 
1997/0327    
 
	new = Fsnewcall(&fs, s, src, segp->source, dst, segp->dest); 
1998/0313    
	new = Fsnewcall(s, src, segp->source, dst, segp->dest); 
1997/0327    
	if(new == nil) 
		return nil; 
 
1998/0306/sys/src/9/ip/tcp.c:919,9261998/0313/sys/src/9/ip/tcp.c:969,978
1997/0327    
{ 
	Tcpctl *tcb; 
	int delta; 
1998/0313    
	Tcppriv *tpriv; 
1997/0327    
 
	tcb = (Tcpctl*)s->ptcl; 
1998/0313    
	tpriv = s->p->priv; 
1997/0327    
 
	delta = msec - tcb->sndsyntime; 
	tcb->srtt = delta<<LOGAGAIN; 
1998/0306/sys/src/9/ip/tcp.c:927,9331998/0313/sys/src/9/ip/tcp.c:979,985
1997/0327    
	tcb->mdev = delta<<LOGDGAIN; 
 
	/* halt round trip timer */ 
	tcphalt(&tcb->rtt_timer); 
1998/0313    
	tcphalt(tpriv, &tcb->rtt_timer); 
1997/0327    
} 
 
void 
1998/0306/sys/src/9/ip/tcp.c:936,9421998/0313/sys/src/9/ip/tcp.c:988,996
1997/0327    
	int rtt, delta; 
	Tcpctl *tcb; 
	ushort acked, expand; 
1998/0313    
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	tpriv = s->p->priv; 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
	tcb->kacounter = MAXBACKOFF;	/* keep alive count down */ 
1998/0306/sys/src/9/ip/tcp.c:983,9891998/0313/sys/src/9/ip/tcp.c:1037,1043
1997/0327    
 
	/* Adjust the timers according to the round trip time */ 
	if(tcb->rtt_timer.state == TimerON && seq_ge(seg->ack, tcb->rttseq)) { 
		tcphalt(&tcb->rtt_timer); 
1998/0313    
		tcphalt(tpriv, &tcb->rtt_timer); 
1997/0327    
		if((tcb->flags&RETRAN) == 0) { 
			tcb->backoff = 0; 
			rtt = tcb->rtt_timer.start - tcb->rtt_timer.count; 
1998/0306/sys/src/9/ip/tcp.c:1020,10281998/0313/sys/src/9/ip/tcp.c:1074,1082
1997/0327    
	if(seq_gt(seg->ack, tcb->snd.urg)) 
		tcb->snd.urg = seg->ack; 
 
	tcphalt(&tcb->timer); 
1998/0313    
	tcphalt(tpriv, &tcb->timer); 
1997/0327    
	if(tcb->snd.una != tcb->snd.nxt) 
		tcpgo(&tcb->timer); 
1998/0313    
		tcpgo(tpriv, &tcb->timer); 
1997/0327    
 
	if(seq_lt(tcb->snd.ptr, tcb->snd.una)) 
		tcb->snd.ptr = tcb->snd.una; 
1998/0306/sys/src/9/ip/tcp.c:1032,10381998/0313/sys/src/9/ip/tcp.c:1086,1092
1997/0327    
} 
 
void 
1998/0306    
tcpiput(uchar*, Block *bp) 
1998/0313    
tcpiput(Proto *tcp, uchar*, Block *bp) 
1997/0327    
{ 
	Tcp seg; 
	Tcphdr *h; 
1998/0306/sys/src/9/ip/tcp.c:1041,10471998/0313/sys/src/9/ip/tcp.c:1095,1108
1997/0327    
	ushort length; 
1998/0306    
	uchar source[IPaddrlen], dest[IPaddrlen]; 
1997/0327    
	Conv *spec, *gen, *s, **p; 
1998/0313    
	Fs *f; 
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	f = tcp->f; 
	tpriv = tcp->priv; 
	 
	tpriv->tstats.tcpInSegs++; 
 
1997/0327    
	h = (Tcphdr*)(bp->rp); 
 
1998/0306    
	v4tov6(dest, h->tcpdst); 
1998/0306/sys/src/9/ip/tcp.c:1051,10581998/0313/sys/src/9/ip/tcp.c:1112,1119
1997/0327    
	h->Unused = 0; 
	hnputs(h->tcplen, length-TCP_PKT); 
	if(ptclcsum(bp, TCP_IPLEN, length-TCP_IPLEN)) { 
		tcp.csumerr++; 
		netlog(Logtcp, "bad tcp proto cksum\n"); 
1998/0313    
		tpriv->csumerr++; 
		netlog(f, Logtcp, "bad tcp proto cksum\n"); 
1997/0327    
		freeblist(bp); 
		return; 
	} 
1998/0306/sys/src/9/ip/tcp.c:1059,10661998/0313/sys/src/9/ip/tcp.c:1120,1127
1997/0327    
 
	hdrlen = ntohtcp(&seg, &bp); 
	if(hdrlen < 0){ 
		tcp.hlenerr++; 
		netlog(Logtcp, "bad tcp hdr len\n"); 
1998/0313    
		tpriv->hlenerr++; 
		netlog(f, Logtcp, "bad tcp hdr len\n"); 
1997/0327    
		return; 
	} 
 
1998/0306/sys/src/9/ip/tcp.c:1068,10811998/0313/sys/src/9/ip/tcp.c:1129,1142
1997/0327    
	length -= hdrlen+TCP_PKT; 
	bp = trimblock(bp, hdrlen+TCP_PKT, length); 
	if(bp == nil){ 
		tcp.lenerr++; 
		netlog(Logtcp, "tcp len < 0 after trim\n"); 
1998/0313    
		tpriv->lenerr++; 
		netlog(f, Logtcp, "tcp len < 0 after trim\n"); 
1997/0327    
		return; 
	} 
 
 
	/* Look for a connection. failing that look for a listener. */ 
	for(p = tcp.conv; *p; p++) { 
1998/0313    
	for(p = tcp->conv; *p; p++) { 
1997/0327    
		s = *p; 
1998/0306    
		if(s->rport == seg.source) 
		if(s->lport == seg.dest) 
1998/0306/sys/src/9/ip/tcp.c:1100,11061998/0313/sys/src/9/ip/tcp.c:1161,1167
1997/0327    
			return; 
		} 
		if(seg.flags & ACK) { 
			sndrst(source, dest, length, &seg); 
1998/0313    
			sndrst(tcp, source, dest, length, &seg); 
1997/0327    
			freeblist(bp); 
			return; 
		} 
1998/0306/sys/src/9/ip/tcp.c:1111,11171998/0313/sys/src/9/ip/tcp.c:1172,1178
1997/0327    
		 */ 
		gen = nil; 
		spec = nil; 
		for(p = tcp.conv; *p; p++) { 
1998/0313    
		for(p = tcp->conv; *p; p++) { 
1997/0327    
			s = *p; 
			tcb = (Tcpctl*)s->ptcl; 
			if((tcb->flags & CLONE) == 0) 
1998/0306/sys/src/9/ip/tcp.c:1136,11421998/0313/sys/src/9/ip/tcp.c:1197,1203
1997/0327    
	} 
	if(s == nil) { 
		freeblist(bp); 
		sndrst(source, dest, length, &seg); 
1998/0313    
		sndrst(tcp, source, dest, length, &seg); 
1997/0327    
		return; 
	} 
 
1998/0306/sys/src/9/ip/tcp.c:1149,11551998/0313/sys/src/9/ip/tcp.c:1210,1216
1997/0327    
 
	switch(tcb->state) { 
	case Closed: 
		sndrst(source, dest, length, &seg); 
1998/0313    
		sndrst(tcp, source, dest, length, &seg); 
1997/0327    
		goto raise; 
	case Listen: 
		if(seg.flags & SYN) { 
1998/0306/sys/src/9/ip/tcp.c:1163,11691998/0313/sys/src/9/ip/tcp.c:1224,1230
1997/0327    
	case Syn_sent: 
		if(seg.flags & ACK) { 
			if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) { 
				sndrst(source, dest, length, &seg); 
1998/0313    
				sndrst(tcp, source, dest, length, &seg); 
1997/0327    
				goto raise; 
			} 
		} 
1998/0306/sys/src/9/ip/tcp.c:1203,12141998/0313/sys/src/9/ip/tcp.c:1264,1275
1997/0327    
 
	/* Cut the data to fit the receive window */ 
	if(tcptrim(tcb, &seg, &bp, &length) == -1) { 
		netlog(Logtcp, "tcp len < 0, %lux\n", seg.seq); 
1998/0313    
		netlog(f, Logtcp, "tcp len < 0, %lux\n", seg.seq); 
1997/0327    
		update(s, &seg); 
		if(tcb->sndcnt == 0 && tcb->state == Closing) { 
			tcpsetstate(s, Time_wait); 
			tcb->timer.start = MSL2*(1000 / MSPTICK); 
			tcpgo(&tcb->timer); 
1998/0313    
			tcpgo(tpriv, &tcb->timer); 
1997/0327    
		} 
		if(!(seg.flags & RST)) { 
			tcb->flags |= FORCE; 
1998/0306/sys/src/9/ip/tcp.c:1220,12261998/0313/sys/src/9/ip/tcp.c:1281,1287
1997/0327    
 
	/* Cannot accept so answer with a rst */ 
	if(length && tcb->state == Closed) { 
		sndrst(source, dest, length, &seg); 
1998/0313    
		sndrst(tcp, source, dest, length, &seg); 
1997/0327    
		goto raise; 
	} 
 
1998/0306/sys/src/9/ip/tcp.c:1230,12361998/0313/sys/src/9/ip/tcp.c:1291,1297
1997/0327    
	if(seg.seq != tcb->rcv.nxt) 
	if(length != 0 || (seg.flags & (SYN|FIN))) { 
		update(s, &seg); 
1997/0916    
		tcp.order++; 
1998/0313    
		tpriv->order++; 
1997/0327    
		addreseq(tcb, &seg, bp, length); 
		tcb->flags |= FORCE; 
		goto output; 
1998/0306/sys/src/9/ip/tcp.c:1242,12471998/0313/sys/src/9/ip/tcp.c:1303,1310
1997/0327    
	 */ 
	for(;;) { 
		if(seg.flags & RST) { 
1998/0313    
			if(tcb->state == Established) 
				tpriv->tstats.tcpEstabResets++; 
1997/0327    
			localclose(s, Econrefused); 
			goto raise; 
		} 
1998/0306/sys/src/9/ip/tcp.c:1252,12581998/0313/sys/src/9/ip/tcp.c:1315,1321
1997/0327    
		switch(tcb->state) { 
		case Syn_received: 
			if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){ 
				sndrst(source, dest, length, &seg); 
1998/0313    
				sndrst(tcp, source, dest, length, &seg); 
1997/0327    
				goto raise; 
			} 
			update(s, &seg); 
1998/0306/sys/src/9/ip/tcp.c:1267,12731998/0313/sys/src/9/ip/tcp.c:1330,1336
1997/0327    
				tcb->f2counter = MAXBACKOFF; 
				tcpsetstate(s, Finwait2); 
				tcb->timer.start = MSL2 * (1000 / MSPTICK); 
				tcpgo(&tcb->timer); 
1998/0313    
				tcpgo(tpriv, &tcb->timer); 
1997/0327    
			} 
			break; 
		case Finwait2: 
1998/0306/sys/src/9/ip/tcp.c:1278,12841998/0313/sys/src/9/ip/tcp.c:1341,1347
1997/0327    
			if(tcb->sndcnt == 0) { 
				tcpsetstate(s, Time_wait); 
				tcb->timer.start = MSL2*(1000 / MSPTICK); 
				tcpgo(&tcb->timer); 
1998/0313    
				tcpgo(tpriv, &tcb->timer); 
1997/0327    
			} 
			break; 
		case Last_ack: 
1998/0306/sys/src/9/ip/tcp.c:1290,12961998/0313/sys/src/9/ip/tcp.c:1353,1359
1997/0327    
		case Time_wait: 
			tcb->flags |= FORCE; 
			if(tcb->timer.state != TimerON) 
				tcpgo(&tcb->timer); 
1998/0313    
				tcpgo(tpriv, &tcb->timer); 
1997/0327    
		} 
 
		if((seg.flags&URG) && seg.urg) { 
1998/0306/sys/src/9/ip/tcp.c:1328,13341998/0313/sys/src/9/ip/tcp.c:1391,1397
1997/0327    
				tcb->rcv.nxt += length; 
				tcprcvwin(s); 
				if(tcb->acktimer.state != TimerON) 
					tcpgo(&tcb->acktimer); 
1998/0313    
					tcpgo(tpriv, &tcb->acktimer); 
1997/0327    
 
				/* force an ack if there's a lot of unacked data */ 
				if(tcb->rcv.nxt-tcb->last_ack > (QMAX>>4)) 
1998/0306/sys/src/9/ip/tcp.c:1339,13451998/0313/sys/src/9/ip/tcp.c:1402,1408
1997/0327    
				/* no process to read the data, send a reset */ 
				if(bp != nil) 
					freeblist(bp); 
				sndrst(source, dest, length, &seg); 
1998/0313    
				sndrst(tcp, source, dest, length, &seg); 
1997/0327    
				qunlock(tcb); 
				return; 
			} 
1998/0306/sys/src/9/ip/tcp.c:1359,13651998/0313/sys/src/9/ip/tcp.c:1422,1428
1997/0327    
				if(tcb->sndcnt == 0) { 
					tcpsetstate(s, Time_wait); 
					tcb->timer.start = MSL2*(1000/MSPTICK); 
					tcpgo(&tcb->timer); 
1998/0313    
					tcpgo(tpriv, &tcb->timer); 
1997/0327    
				} 
				else 
					tcpsetstate(s, Closing); 
1998/0306/sys/src/9/ip/tcp.c:1368,13741998/0313/sys/src/9/ip/tcp.c:1431,1437
1997/0327    
				tcb->rcv.nxt++; 
				tcpsetstate(s, Time_wait); 
				tcb->timer.start = MSL2 * (1000/MSPTICK); 
				tcpgo(&tcb->timer); 
1998/0313    
				tcpgo(tpriv, &tcb->timer); 
1997/0327    
				break; 
			case Close_wait: 
			case Closing: 
1998/0306/sys/src/9/ip/tcp.c:1375,13811998/0313/sys/src/9/ip/tcp.c:1438,1444
1997/0327    
			case Last_ack: 
				break; 
			case Time_wait: 
				tcpgo(&tcb->timer); 
1998/0313    
				tcpgo(tpriv, &tcb->timer); 
1997/0327    
				break; 
			} 
		} 
1998/0306/sys/src/9/ip/tcp.c:1420,14261998/0313/sys/src/9/ip/tcp.c:1483,1494
1997/0327    
	Block *hbp, *bp; 
	int sndcnt, n, first; 
	ulong ssize, dsize, usable, sent; 
1998/0313    
	Fs *f; 
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	f = s->p->f; 
	tpriv = s->p->priv; 
 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
	switch(tcb->state) { 
1998/0306/sys/src/9/ip/tcp.c:1489,14951998/0313/sys/src/9/ip/tcp.c:1557,1563
1997/0327    
		if((tcb->flags&FORCE) == 0) 
			break; 
 
		tcphalt(&tcb->acktimer); 
1998/0313    
		tcphalt(tpriv, &tcb->acktimer); 
1997/0327    
 
		tcb->flags &= ~FORCE; 
		tcprcvwin(s); 
1998/0306/sys/src/9/ip/tcp.c:1525,15311998/0313/sys/src/9/ip/tcp.c:1593,1599
1997/0327    
				seg.flags |= FIN; 
				dsize--; 
			} 
			netlog(Logtcp, "qcopy: dlen %d blen %d sndcnt %d qlen %d sent %d rp[0] %d\n", 
1998/0313    
			netlog(f, Logtcp, "qcopy: dlen %d blen %d sndcnt %d qlen %d sent %d rp[0] %d\n", 
1997/0327    
				dsize, BLEN(bp), sndcnt, qlen(s->wq), sent, bp->rp[0]); 
		} 
 
1998/0306/sys/src/9/ip/tcp.c:1566,15811998/0313/sys/src/9/ip/tcp.c:1634,1650
1997/0327    
			tcb->timer.start = x; 
 
			if(tcb->timer.state != TimerON) 
				tcpgo(&tcb->timer); 
1998/0313    
				tcpgo(tpriv, &tcb->timer); 
1997/0327    
 
			/* If round trip timer isn't running, start it */ 
			if(tcb->rtt_timer.state != TimerON) { 
				tcpgo(&tcb->rtt_timer); 
1998/0313    
				tcpgo(tpriv, &tcb->rtt_timer); 
1997/0327    
				tcb->rttseq = tcb->snd.ptr; 
			} 
		} 
 
		ipoput(hbp, 0, s->ttl); 
1998/0313    
		tpriv->tstats.tcpOutSegs++; 
		ipoput(f, hbp, 0, s->ttl); 
1997/0327    
	} 
} 
 
1998/0306/sys/src/9/ip/tcp.c:1616,16221998/0313/sys/src/9/ip/tcp.c:1685,1691
1997/0327    
		return; 
	} 
 
	ipoput(hbp, 0, s->ttl); 
1998/0313    
	ipoput(s->p->f, hbp, 0, s->ttl); 
1997/0327    
} 
 
void 
1998/0306/sys/src/9/ip/tcp.c:1623,16321998/0313/sys/src/9/ip/tcp.c:1692,1702
1997/0327    
tcprxmit(Conv *s) 
{ 
	Tcpctl *tcb; 
1998/0313    
	Tcppriv *tpriv; 
1997/0327    
 
1998/0313    
	tpriv = s->p->priv; 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
                 
	qlock(tcb); 
	tcb->flags |= RETRAN|FORCE; 
	tcb->snd.ptr = tcb->snd.una; 
1998/0306/sys/src/9/ip/tcp.c:1642,16491998/0313/sys/src/9/ip/tcp.c:1712,1718
1997/0327    
	tcb->cwind = tcb->mss; 
	tcpoutput(s); 
 
	tcp.rexmit++; 
                 
1998/0313    
	tpriv->tstats.tcpRetransSegs++; 
1997/0327    
	qunlock(tcb); 
} 
 
1998/0306/sys/src/9/ip/tcp.c:1678,16841998/0313/sys/src/9/ip/tcp.c:1747,1753
1997/0327    
			qlock(tcb); 
			tcpkeepalive(s); 
			qunlock(tcb); 
			tcpgo(&tcb->timer); 
1998/0313    
			tcpgo(s->p->priv, &tcb->timer); 
1997/0327    
		} 
		break; 
	case Time_wait: 
1998/0306/sys/src/9/ip/tcp.c:1807,18141998/0313/sys/src/9/ip/tcp.c:1876,1881
1997/0327    
	dupcnt = tcb->rcv.nxt - seg->seq; 
	if(dupcnt > 0){ 
		tcb->rerecv += dupcnt; 
1997/0916    
		tstats.dup++; 
		tstats.dupb += dupcnt; 
1997/0327    
		if(seg->flags & SYN){ 
			seg->flags &= ~SYN; 
			seg->seq++; 
1998/0306/sys/src/9/ip/tcp.c:1845,18511998/0313/sys/src/9/ip/tcp.c:1912,1918
1997/0327    
} 
 
void 
tcpadvise(Block *bp, char *msg) 
1998/0313    
tcpadvise(Proto *tcp, Block *bp, char *msg) 
1997/0327    
{ 
	Tcphdr *h; 
	Tcpctl *tcb; 
1998/0306/sys/src/9/ip/tcp.c:1862,18681998/0313/sys/src/9/ip/tcp.c:1929,1935
1997/0327    
	pdest = nhgets(h->tcpdport); 
 
	/* Look for a connection */ 
	for(p = tcp.conv; *p; p++) { 
1998/0313    
	for(p = tcp->conv; *p; p++) { 
1997/0327    
		s = *p; 
1998/0306    
		if(s->rport == pdest) 
		if(s->lport == psource) 
1998/0306/sys/src/9/ip/tcp.c:1892,19301998/0313/sys/src/9/ip/tcp.c:1959,2012
1997/0327    
} 
 
1997/0916    
int 
tcpstats(char *buf, int len) 
1998/0313    
tcpstats(Proto *tcp, char *buf, int len) 
1997/0916    
{ 
1998/0306    
	int n; 
1998/0313    
	Tcpstats *tstats; 
1998/0306    
 
	n = snprint(buf, len, 
		"tcp: csum %d hlen %d len %d order %d rexmit %d", 
		tcp.csumerr, tcp.hlenerr, tcp.lenerr, tcp.order, tcp.rexmit); 
	n += snprint(buf+n, len-n, " dupp %d dupb %d\n", 
		tstats.dup, tstats.dupb); 
	return n; 
1998/0313    
	tstats = tcp->priv; 
	return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d", 
		tstats->tcpRtoAlgorithm, 
		tstats->tcpRtoMin, 
		tstats->tcpRtoMax, 
		tstats->tcpMaxConn, 
		tstats->tcpActiveOpens, 
		tstats->tcpPassiveOpens, 
		tstats->tcpAttemptFails, 
		tstats->tcpEstabResets, 
		tstats->tcpCurrEstab, 
		tstats->tcpInSegs, 
		tstats->tcpOutSegs, 
		tstats->tcpRetransSegs, 
		tstats->InErrs, 
		tstats->OutRsts); 
1997/0916    
} 
 
1997/0327    
void 
tcpinit(Fs *fs) 
{ 
	tcp.name = "tcp"; 
	tcp.kick = tcpkick; 
	tcp.connect = tcpconnect; 
	tcp.announce = tcpannounce; 
	tcp.ctl = tcpctl; 
	tcp.state = tcpstate; 
	tcp.create = tcpcreate; 
	tcp.close = tcpclose; 
	tcp.rcv = tcpiput; 
	tcp.advise = tcpadvise; 
1997/0916    
	tcp.stats = tcpstats; 
1998/0306    
	tcp.inuse = tcpinuse; 
1997/0327    
	tcp.ipproto = IP_TCPPROTO; 
	tcp.nc = Nchans; 
	tcp.ptclsize = sizeof(Tcpctl); 
1998/0313    
	Proto *tcp; 
	Tcppriv *tpriv; 
1997/0327    
 
	kproc("tcpack", tcpackproc, 0); 
1998/0313    
	tcp = smalloc(sizeof(Proto)); 
	tpriv = tcp->priv = smalloc(sizeof(Tcppriv)); 
	tcp->name = "tcp"; 
	tcp->kick = tcpkick; 
	tcp->connect = tcpconnect; 
	tcp->announce = tcpannounce; 
	tcp->ctl = tcpctl; 
	tcp->state = tcpstate; 
	tcp->create = tcpcreate; 
	tcp->close = tcpclose; 
	tcp->rcv = tcpiput; 
	tcp->advise = tcpadvise; 
	tcp->stats = tcpstats; 
	tcp->inuse = tcpinuse; 
	tcp->ipproto = IP_TCPPROTO; 
	tcp->nc = Nchans; 
	tcp->ptclsize = sizeof(Tcpctl); 
	tpriv->tstats.tcpMaxConn = Nchans; 
1997/0327    
 
	Fsproto(fs, &tcp); 
} 
1998/0313    
	Fsproto(fs, tcp); 
1998/0306    
 
1998/0313    
	kproc("tcpack", tcpackproc, tcp); 
} 
1998/0313/sys/src/9/ip/tcp.c:37,431998/0421/sys/src/9/ip/tcp.c:37,43 (short | long)
TCP tuning: increase DEF_RTT and set tcb->mdev.
rsc Fri Mar 4 12:44:25 2005
1997/0327    
	MSL2		= 10, 
	MSPTICK		= 50,		/* Milliseconds per timer tick */ 
	DEF_MSS		= 1024,		/* Default mean segment */ 
	DEF_RTT		= 150,		/* Default round trip */ 
1998/0421    
	DEF_RTT		= 500,		/* Default round trip */ 
1997/0327    
	TCP_LISTEN	= 0,		/* Listen connection */ 
	TCP_CONNECT	= 1,		/* Outgoing connection */ 
 
1998/0313/sys/src/9/ip/tcp.c:583,5881998/0421/sys/src/9/ip/tcp.c:583,589
1997/0327    
	tcb->mss = tcp_mss; 
	tcb->ssthresh = 65535; 
	tcb->srtt = 0; 
1998/0421    
	tcb->mdev = tcp_irtt << LOGDGAIN; 
1997/0327    
 
	tcb->timer.start = tcp_irtt / MSPTICK; 
	tcb->timer.func = tcptimeout; 
1998/0421/sys/src/9/ip/tcp.c:37,431998/0630/sys/src/9/ip/tcp.c:37,43 (short | long)
1997/0327    
	MSL2		= 10, 
	MSPTICK		= 50,		/* Milliseconds per timer tick */ 
	DEF_MSS		= 1024,		/* Default mean segment */ 
1998/0421    
	DEF_RTT		= 500,		/* Default round trip */ 
1998/0630    
	DEF_RTT		= 150,		/* Default round trip */ 
1997/0327    
	TCP_LISTEN	= 0,		/* Listen connection */ 
	TCP_CONNECT	= 1,		/* Outgoing connection */ 
 
1998/0421/sys/src/9/ip/tcp.c:254,2631998/0630/sys/src/9/ip/tcp.c:254,263
1998/0313    
	if(newstate == Established) 
		tpriv->tstats.tcpCurrEstab++; 
 
1997/0327    
	/* 
	  print("%d/%d %s->%s\n", s->lport, s->rport, 
			tcpstates[oldstate], tcpstates[newstate]); 
	/**/ 
1998/0630    
	/** 
	print( "%d/%d %s->%s CurrEstab=%d\n", s->lport, s->rport, 
		tcpstates[oldstate], tcpstates[newstate], tpriv->tstats.tcpCurrEstab ); 
	**/ 
1997/0327    
 
	tcb->state = newstate; 
 
1998/0421/sys/src/9/ip/tcp.c:583,5891998/0630/sys/src/9/ip/tcp.c:583,588
1997/0327    
	tcb->mss = tcp_mss; 
	tcb->ssthresh = 65535; 
	tcb->srtt = 0; 
1998/0421    
	tcb->mdev = tcp_irtt << LOGDGAIN; 
1997/0327    
 
	tcb->timer.start = tcp_irtt / MSPTICK; 
	tcb->timer.func = tcptimeout; 
1998/0421/sys/src/9/ip/tcp.c:1962,19851998/0630/sys/src/9/ip/tcp.c:1961,1987
1997/0916    
int 
1998/0313    
tcpstats(Proto *tcp, char *buf, int len) 
1997/0916    
{ 
1998/0313    
	Tcpstats *tstats; 
1998/0630    
	Tcppriv *tpriv; 
1998/0306    
 
1998/0313    
	tstats = tcp->priv; 
1998/0630    
	tpriv = tcp->priv; 
 
 
 
1998/0313    
	return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d", 
		tstats->tcpRtoAlgorithm, 
		tstats->tcpRtoMin, 
		tstats->tcpRtoMax, 
		tstats->tcpMaxConn, 
		tstats->tcpActiveOpens, 
		tstats->tcpPassiveOpens, 
		tstats->tcpAttemptFails, 
		tstats->tcpEstabResets, 
		tstats->tcpCurrEstab, 
		tstats->tcpInSegs, 
		tstats->tcpOutSegs, 
		tstats->tcpRetransSegs, 
		tstats->InErrs, 
		tstats->OutRsts); 
1998/0630    
		tpriv->tstats.tcpRtoAlgorithm, 
		tpriv->tstats.tcpRtoMin, 
		tpriv->tstats.tcpRtoMax, 
		tpriv->tstats.tcpMaxConn, 
		tpriv->tstats.tcpActiveOpens, 
		tpriv->tstats.tcpPassiveOpens, 
		tpriv->tstats.tcpAttemptFails, 
		tpriv->tstats.tcpEstabResets, 
		tpriv->tstats.tcpCurrEstab, 
		tpriv->tstats.tcpInSegs, 
		tpriv->tstats.tcpOutSegs, 
		tpriv->tstats.tcpRetransSegs, 
		tpriv->tstats.InErrs, 
		tpriv->tstats.OutRsts); 
1997/0916    
} 
 
1997/0327    
void 
1998/0630/sys/src/9/ip/tcp.c:266,2741998/0724/sys/src/9/ip/tcp.c:266,274 (short | long)
1997/0327    
		qclose(s->rq); 
		qclose(s->wq); 
		qclose(s->eq); 
		s->lport = 0;		/* This connection is toast */ 
		s->rport = 0; 
1998/0306    
		ipmove(s->raddr, IPnoaddr); 
1998/0724    
//		s->lport = 0;		/* This connection is toast */ 
//		s->rport = 0; 
//		ipmove(s->raddr, IPnoaddr); 
1997/0327    
 
	case Close_wait:		/* Remote closes */ 
		qhangup(s->rq, nil); 
1998/0630/sys/src/9/ip/tcp.c:1138,11451998/0724/sys/src/9/ip/tcp.c:1138,1147
1997/0327    
	/* Look for a connection. failing that look for a listener. */ 
1998/0313    
	for(p = tcp->conv; *p; p++) { 
1997/0327    
		s = *p; 
1998/0724    
		tcb = (Tcpctl*)s->ptcl; 
1998/0306    
		if(s->rport == seg.source) 
		if(s->lport == seg.dest) 
1998/0724    
		if(tcb->state != Closed) 
1998/0306    
		if(ipcmp(s->raddr, source) == 0) 
1997/0327    
			break; 
	} 
1998/0630/sys/src/9/ip/tcp.c:1931,19411998/0724/sys/src/9/ip/tcp.c:1933,1944
1997/0327    
	/* Look for a connection */ 
1998/0313    
	for(p = tcp->conv; *p; p++) { 
1997/0327    
		s = *p; 
1998/0724    
		tcb = (Tcpctl*)s->ptcl; 
1998/0306    
		if(s->rport == pdest) 
		if(s->lport == psource) 
1998/0724    
		if(tcb->state != Closed) 
1998/0306    
		if(ipcmp(s->raddr, dest) == 0) 
		if(ipcmp(s->laddr, source) == 0){ 
1997/0327    
			tcb = (Tcpctl*)s->ptcl; 
			qlock(tcb); 
			switch(tcb->state){ 
			case Syn_sent: 
1998/0724/sys/src/9/ip/tcp.c:1794,17991998/0808/sys/src/9/ip/tcp.c:1794,1800 (short | long)
Debugging: print for very long TCP resequence queue.
rsc Fri Mar 4 12:44:25 2005
1997/0327    
addreseq(Tcpctl *tcb, Tcp *seg, Block *bp, ushort length) 
{ 
	Reseq *rp, *rp1; 
1998/0808    
	int i; 
1997/0327    
 
	rp = malloc(sizeof(Reseq)); 
	if(rp == nil){ 
1998/0724/sys/src/9/ip/tcp.c:1813,18191998/0808/sys/src/9/ip/tcp.c:1814,1822
1997/0327    
		return; 
	} 
 
	for(;;) { 
1998/0808    
	for(i = 0;; i++) { 
		if(i > 100) 
			print("very long tcp resequence queue\n"); 
1997/0327    
		if(rp1->next == nil || seq_lt(seg->seq, rp1->next->seg.seq)) { 
			rp->next = rp1->next; 
			rp1->next = rp; 
1998/0808/sys/src/9/ip/tcp.c:266,2741998/0813/sys/src/9/ip/tcp.c:266,271 (short | long)
1997/0327    
		qclose(s->rq); 
		qclose(s->wq); 
		qclose(s->eq); 
1998/0724    
//		s->lport = 0;		/* This connection is toast */ 
//		s->rport = 0; 
//		ipmove(s->raddr, IPnoaddr); 
1997/0327    
 
	case Close_wait:		/* Remote closes */ 
		qhangup(s->rq, nil); 
1998/0808/sys/src/9/ip/tcp.c:1573,15831998/0813/sys/src/9/ip/tcp.c:1570,1590
1997/0327    
		switch(tcb->state){ 
		case Syn_sent: 
			seg.flags = 0; 
			/* No break */ 
		case Syn_received: 
			if(tcb->snd.ptr == tcb->iss){ 
				seg.flags |= SYN; 
				dsize--; 
1998/0813    
				seg.mss = tcpmtu(s); 
			} 
			break; 
		case Syn_received: 
			/* 
			 *  don't send any data with a SYN/ACK packet 
			 *  because Linux rejects the packet in its 
			 *  attempt to solve the SYN attack problem 
			 */ 
			if(tcb->snd.ptr == tcb->iss){ 
				seg.flags |= SYN; 
				dsize = 0; 
1997/0327    
				seg.mss = tcpmtu(s); 
			} 
			break; 
1998/0813/sys/src/9/ip/tcp.c:1980,19861998/0825/sys/src/9/ip/tcp.c:1980,1986 (short | long)
Bug fix: print format.
rsc Fri Mar 4 12:44:25 2005
1998/0630    
 
 
 
1998/0313    
	return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d", 
1998/0825    
	return snprint(buf, len, "%lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud", 
1998/0630    
		tpriv->tstats.tcpRtoAlgorithm, 
		tpriv->tstats.tcpRtoMin, 
		tpriv->tstats.tcpRtoMax, 
1998/0825/sys/src/9/ip/tcp.c:1585,15901998/0831/sys/src/9/ip/tcp.c:1585,1591 (short | long)
1998/0813    
			if(tcb->snd.ptr == tcb->iss){ 
				seg.flags |= SYN; 
				dsize = 0; 
1998/0831    
				ssize = 1; 
1997/0327    
				seg.mss = tcpmtu(s); 
			} 
			break; 
1998/0831/sys/src/9/ip/tcp.c:1509,15151998/0901/sys/src/9/ip/tcp.c:1509,1515 (short | long)
1997/0327    
		sent = tcb->snd.ptr - tcb->snd.una; 
 
		/* Don't send anything else until our SYN has been acked */ 
		if(sent != 0 && (tcb->flags & (SYNACK|FORCE)) == 0) 
1998/0901    
		if(tcb->snd.ptr != tcb->iss && (tcb->flags & SYNACK) == 0) 
1997/0327    
			break; 
 
		/* Compute usable segment based on offered window and limit 
1998/0901/sys/src/9/ip/tcp.c:20,261998/0918/sys/src/9/ip/tcp.c:20,26 (short | long)
1997/0327    
	TimerON		= 1, 
	TimerDONE	= 2, 
	MAX_TIME 	= (1<<20),	/* Forever */ 
	TCP_ACK		= 50,		/* Timed ack sequence in ms */ 
1998/0918    
	TCP_ACK		= 200,		/* Timed ack sequence in ms */ 
1997/0327    
 
	URG		= 0x20,		/* Data marked urgent */ 
	ACK		= 0x10,		/* Acknowledge is valid */ 
1998/0901/sys/src/9/ip/tcp.c:1384,14001998/0918/sys/src/9/ip/tcp.c:1384,1404
1997/0327    
				 * receive queue 
				 */ 
				if(bp) { 
					qpass(s->rq, bp); 
1998/0918    
					qpassnolim(s->rq, packblock(bp)); 
1997/0327    
					bp = nil; 
				} 
				tcb->rcv.nxt += length; 
				tcprcvwin(s); 
				if(tcb->acktimer.state != TimerON) 
1998/0313    
					tcpgo(tpriv, &tcb->acktimer); 
1997/0327    
 
				/* force an ack if there's a lot of unacked data */ 
				if(tcb->rcv.nxt-tcb->last_ack > (QMAX>>4)) 
1998/0918    
				/* 
				 *  force an ack if we've got 2 segs 
				 *  and the user isn't backing up 
				 */ 
				if(tcb->rcv.nxt - tcb->last_ack >= 2*tcb->mss && 
				   qlen(s->rq) < 8*tcb->mss) 
1997/0327    
					tcb->flags |= FORCE; 
1998/0918    
				else if(tcb->acktimer.state != TimerON) 
					tcpgo(tpriv, &tcb->acktimer); 
1997/0327    
 
				break; 
			case Finwait2: 
1998/0901/sys/src/9/ip/tcp.c:1637,16441998/0918/sys/src/9/ip/tcp.c:1641,1655
1997/0327    
		 * expect acknowledges 
		 */ 
		if(ssize != 0){ 
1998/0918    
			/* round trip depenency */ 
1997/0327    
			x = backoff(tcb->backoff) * 
			    (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK; 
1998/0918    
 
			/* take into account delayed ack */ 
			if(sent <= 2*tcb->mss) 
				x += TCP_ACK/MSPTICK; 
 
			/* sanity check */ 
1997/0327    
			if(x > (10000/MSPTICK)) 
				x = 10000/MSPTICK; 
			tcb->timer.start = x; 
1998/0918/sys/src/9/ip/tcp.c:1384,13901998/0923/sys/src/9/ip/tcp.c:1384,1393 (short | long)
1997/0327    
				 * receive queue 
				 */ 
				if(bp) { 
1998/0918    
					qpassnolim(s->rq, packblock(bp)); 
1998/0923    
					bp = packblock(bp); 
					if(bp == nil) 
						panic("tcp packblock"); 
					qpassnolim(s->rq, bp); 
1997/0327    
					bp = nil; 
				} 
				tcb->rcv.nxt += length; 
1998/0923/sys/src/9/ip/tcp.c:219,2241998/0924/sys/src/9/ip/tcp.c:219,227 (short | long)
1998/0313    
	ulong		lenerr;			/* short packet */ 
	ulong		order;			/* out of order */ 
 
1998/0924    
	/* for keeping track of tcpackproc */ 
	int	ackprocstarted; 
	QLock	apl; 
1998/0313    
}; 
 
1997/0327    
void	addreseq(Tcpctl*, Tcp*, Block*, ushort); 
1998/0923/sys/src/9/ip/tcp.c:622,6301998/0924/sys/src/9/ip/tcp.c:625,644
1997/0327    
{ 
	Tcpctl *tcb; 
1998/0313    
	Tcppriv *tpriv; 
1998/0924    
	char kpname[NAMELEN]; 
1997/0327    
 
1998/0313    
	tpriv = s->p->priv; 
 
1998/0924    
	if(tpriv->ackprocstarted == 0){ 
		qlock(&tpriv->apl); 
		if(tpriv->ackprocstarted == 0){ 
			sprint(kpname, "#I%dtcpack", s->p->f->dev); 
			kproc(kpname, tcpackproc, s->p); 
			tpriv->ackprocstarted = 1; 
		} 
		qunlock(&tpriv->apl); 
	} 
 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
	inittcpctl(s); 
1998/0923/sys/src/9/ip/tcp.c:2038,20431998/0924/sys/src/9/ip/tcp.c:2052,2055
1998/0313    
	tpriv->tstats.tcpMaxConn = Nchans; 
1997/0327    
 
1998/0313    
	Fsproto(fs, tcp); 
1998/0306    
                 
1998/0313    
	kproc("tcpack", tcpackproc, tcp); 
} 
1998/0924/sys/src/9/ip/tcp.c:76,811998/0925/sys/src/9/ip/tcp.c:76,82 (short | long)
1997/0327    
{ 
	Timer	*next; 
	Timer	*prev; 
1998/0925    
	Timer	*readynext; 
1997/0327    
	int	state; 
	int	start; 
	int	count; 
1998/0924/sys/src/9/ip/tcp.c:262,2741998/0925/sys/src/9/ip/tcp.c:263,274
1998/0630    
		tcpstates[oldstate], tcpstates[newstate], tpriv->tstats.tcpCurrEstab ); 
	**/ 
1997/0327    
 
	tcb->state = newstate; 
                 
	switch(newstate) { 
	case Closed: 
		qclose(s->rq); 
		qclose(s->wq); 
		qclose(s->eq); 
1998/0925    
		break; 
1997/0327    
 
	case Close_wait:		/* Remote closes */ 
		qhangup(s->rq, nil); 
1998/0924/sys/src/9/ip/tcp.c:275,2801998/0925/sys/src/9/ip/tcp.c:275,282
1997/0327    
		break; 
	} 
 
1998/0925    
	tcb->state = newstate; 
 
1997/0515    
	if(oldstate == Syn_sent && newstate != Closed) 
1998/0313    
		Fsconnected(s, nil); 
1997/0327    
} 
1998/0924/sys/src/9/ip/tcp.c:419,4241998/0925/sys/src/9/ip/tcp.c:421,427
1997/0327    
		t->next->prev = t->prev; 
	if(t->prev) 
		t->prev->next = t->next; 
1998/0925    
	t->next = t->prev = nil; 
1997/0327    
} 
 
void 
1998/0924/sys/src/9/ip/tcp.c:463,4681998/0925/sys/src/9/ip/tcp.c:466,472
1997/0327    
	Timer *t, *tp, *timeo; 
1998/0313    
	Proto *tcp; 
	Tcppriv *tpriv; 
1998/0925    
	int loop; 
1997/0327    
 
1998/0313    
	tcp = a; 
	tpriv = tcp->priv; 
1998/0924/sys/src/9/ip/tcp.c:472,4781998/0925/sys/src/9/ip/tcp.c:476,485
1997/0327    
 
1998/0313    
		qlock(&tpriv->tl); 
1997/0327    
		timeo = nil; 
1998/0925    
		loop = 0; 
1998/0313    
		for(t = tpriv->timers; t != nil; t = tp) { 
1998/0925    
			if(loop++ > 10000) 
				panic("tcpackproc1"); 
1997/0327    
			tp = t->next; 
 			if(t->state == TimerON) { 
				t->count--; 
1998/0924/sys/src/9/ip/tcp.c:479,4851998/0925/sys/src/9/ip/tcp.c:486,492
1997/0327    
				if(t->count == 0) { 
1998/0313    
					deltimer(tpriv, t); 
1997/0327    
					t->state = TimerDONE; 
					t->next = timeo; 
1998/0925    
					t->readynext = timeo; 
1997/0327    
					timeo = t; 
				} 
			} 
1998/0924/sys/src/9/ip/tcp.c:486,4971998/0925/sys/src/9/ip/tcp.c:493,502
1997/0327    
		} 
1998/0313    
		qunlock(&tpriv->tl); 
1997/0327    
 
		for(;;) { 
			t = timeo; 
			if(t == nil) 
				break; 
                 
			timeo = t->next; 
1998/0925    
		loop = 0; 
		for(t = timeo; t != nil; t = t->readynext) { 
			if(loop++ > 10000) 
				panic("tcpackproc2"); 
1997/0327    
			if(t->state == TimerDONE && t->func != nil) 
				(*t->func)(t->arg); 
		} 
1998/0924/sys/src/9/ip/tcp.c:551,5561998/0925/sys/src/9/ip/tcp.c:556,562
1997/0327    
 
1998/0313    
	tcphalt(tpriv, &tcb->timer); 
	tcphalt(tpriv, &tcb->rtt_timer); 
1998/0925    
	tcphalt(tpriv, &tcb->acktimer); 
1997/0327    
 
	/* Flush reassembly queue; nothing more can arrive */ 
	for(rp = tcb->reseq; rp != nil; rp = rp1) { 
1998/0924/sys/src/9/ip/tcp.c:1412,14211998/0925/sys/src/9/ip/tcp.c:1418,1431
1998/0918    
				 *  and the user isn't backing up 
				 */ 
				if(tcb->rcv.nxt - tcb->last_ack >= 2*tcb->mss && 
				   qlen(s->rq) < 8*tcb->mss) 
1998/0925    
				   qlen(s->rq) < 8*tcb->mss){ 
1997/0327    
					tcb->flags |= FORCE; 
1998/0918    
				else if(tcb->acktimer.state != TimerON) 
					tcpgo(tpriv, &tcb->acktimer); 
1998/0925    
					if(tcb->acktimer.state == TimerON) 
						tcphalt(tpriv, &tcb->acktimer); 
				} else { 
					if(tcb->acktimer.state != TimerON) 
						tcpgo(tpriv, &tcb->acktimer); 
				} 
1997/0327    
 
				break; 
			case Finwait2: 
1998/0925/sys/src/9/ip/tcp.c:409,4221998/0927/sys/src/9/ip/tcp.c:409,419 (short | long)
1997/0327    
	} 
} 
 
/* 
 *  get remote sender going if it was flow controlled due to a closed window 
 */ 
static void 
1998/0313    
deltimer(Tcppriv *tpriv, Timer *t) 
1998/0927    
deltimer(Tcppriv *priv, Timer *t) 
1997/0327    
{ 
1998/0313    
	if(tpriv->timers == t) 
		tpriv->timers = t->next; 
1998/0927    
	if(priv->timers == t) 
		priv->timers = t->next; 
1997/0327    
	if(t->next) 
		t->next->prev = t->prev; 
	if(t->prev) 
1998/0925/sys/src/9/ip/tcp.c:465,4831998/0927/sys/src/9/ip/tcp.c:462,480
1997/0327    
{ 
	Timer *t, *tp, *timeo; 
1998/0313    
	Proto *tcp; 
	Tcppriv *tpriv; 
1998/0927    
	Tcppriv *priv; 
1998/0925    
	int loop; 
1997/0327    
 
1998/0313    
	tcp = a; 
	tpriv = tcp->priv; 
1998/0927    
	priv = tcp->priv; 
1998/0313    
 
1997/0327    
	for(;;) { 
1998/0313    
		tsleep(&tpriv->tcpr, return0, 0, MSPTICK); 
1998/0927    
		tsleep(&priv->tcpr, return0, 0, MSPTICK); 
1997/0327    
 
1998/0313    
		qlock(&tpriv->tl); 
1998/0927    
		qlock(&priv->tl); 
1997/0327    
		timeo = nil; 
1998/0925    
		loop = 0; 
1998/0313    
		for(t = tpriv->timers; t != nil; t = tp) { 
1998/0927    
		for(t = priv->timers; t != nil; t = tp) { 
1998/0925    
			if(loop++ > 10000) 
				panic("tcpackproc1"); 
1997/0327    
			tp = t->next; 
1998/0925/sys/src/9/ip/tcp.c:484,4901998/0927/sys/src/9/ip/tcp.c:481,487
1997/0327    
 			if(t->state == TimerON) { 
				t->count--; 
				if(t->count == 0) { 
1998/0313    
					deltimer(tpriv, t); 
1998/0927    
					deltimer(priv, t); 
1997/0327    
					t->state = TimerDONE; 
1998/0925    
					t->readynext = timeo; 
1997/0327    
					timeo = t; 
1998/0925/sys/src/9/ip/tcp.c:491,4971998/0927/sys/src/9/ip/tcp.c:488,494
1997/0327    
				} 
			} 
		} 
1998/0313    
		qunlock(&tpriv->tl); 
1998/0927    
		qunlock(&priv->tl); 
1997/0327    
 
1998/0925    
		loop = 0; 
		for(t = timeo; t != nil; t = t->readynext) { 
1998/0925/sys/src/9/ip/tcp.c:504,5381998/0927/sys/src/9/ip/tcp.c:501,535
1997/0327    
} 
 
void 
1998/0313    
tcpgo(Tcppriv *tpriv, Timer *t) 
1998/0927    
tcpgo(Tcppriv *priv, Timer *t) 
1997/0327    
{ 
	if(t == nil || t->start == 0) 
		return; 
 
1998/0313    
	qlock(&tpriv->tl); 
1998/0927    
	qlock(&priv->tl); 
1997/0327    
	t->count = t->start; 
	if(t->state != TimerON) { 
		t->state = TimerON; 
		t->prev = nil; 
1998/0313    
		t->next = tpriv->timers; 
1998/0927    
		t->next = priv->timers; 
1997/0327    
		if(t->next) 
			t->next->prev = t; 
1998/0313    
		tpriv->timers = t; 
1998/0927    
		priv->timers = t; 
1997/0327    
	} 
1998/0313    
	qunlock(&tpriv->tl); 
1998/0927    
	qunlock(&priv->tl); 
1997/0327    
} 
 
void 
1998/0313    
tcphalt(Tcppriv *tpriv, Timer *t) 
1998/0927    
tcphalt(Tcppriv *priv, Timer *t) 
1997/0327    
{ 
	if(t == nil) 
		return; 
 
1998/0313    
	qlock(&tpriv->tl); 
1998/0927    
	qlock(&priv->tl); 
1997/0327    
	if(t->state == TimerON) 
1998/0313    
		deltimer(tpriv, t); 
1998/0927    
		deltimer(priv, t); 
1997/0327    
	t->state = TimerOFF; 
1998/0313    
	qunlock(&tpriv->tl); 
1998/0927    
	qunlock(&priv->tl); 
1997/0327    
} 
 
int 
1998/0927/sys/src/9/ip/tcp.c:20,261998/1008/sys/src/9/ip/tcp.c:20,26 (short | long)
1997/0327    
	TimerON		= 1, 
	TimerDONE	= 2, 
	MAX_TIME 	= (1<<20),	/* Forever */ 
1998/0918    
	TCP_ACK		= 200,		/* Timed ack sequence in ms */ 
1998/1008    
	TCP_ACK		= 50,		/* Timed ack sequence in ms */ 
1997/0327    
 
	URG		= 0x20,		/* Data marked urgent */ 
	ACK		= 0x10,		/* Acknowledge is valid */ 
1998/0927/sys/src/9/ip/tcp.c:1417,14281998/1008/sys/src/9/ip/tcp.c:1417,1425
1998/0918    
				if(tcb->rcv.nxt - tcb->last_ack >= 2*tcb->mss && 
1998/0925    
				   qlen(s->rq) < 8*tcb->mss){ 
1997/0327    
					tcb->flags |= FORCE; 
1998/0925    
					if(tcb->acktimer.state == TimerON) 
						tcphalt(tpriv, &tcb->acktimer); 
				} else { 
					if(tcb->acktimer.state != TimerON) 
						tcpgo(tpriv, &tcb->acktimer); 
				} 
1998/1008    
				if(tcb->acktimer.state != TimerON) 
					tcpgo(tpriv, &tcb->acktimer); 
1997/0327    
 
				break; 
			case Finwait2: 
1998/0927/sys/src/9/ip/tcp.c:1556,15731998/1008/sys/src/9/ip/tcp.c:1553,1570
1997/0327    
			if(tcb->snd.wnd < usable) 
				usable = tcb->snd.wnd; 
			usable -= sent; 
                 
			/* 
			 *  hold small pieces in the hopes that more will come along. 
			 *  this is pessimal in synchronous communications so go ahead 
			 *  and send if: 
			 *   - all previous xmits are acked 
1998/1008    
			 *  and send if any of the following: 
			 *   - there's no unacked packets outstanding 
1997/0327    
			 *   - we've forced to send anyways 
			 *   - we've just gotten an ACK for a previous packet 
1998/1008    
			 *   - there's more than 5 bytes queued 
1997/0327    
			 */ 
			if(!first) 
			if(!(tcb->flags&(FORCE|ACKED))) 
			if((sndcnt-sent) < tcb->mss) 
1998/1008    
			if((sndcnt-sent) < 5) 
1997/0327    
				usable = 0; 
		} 
		tcb->flags &= ~ACKED; 
1998/1008/sys/src/9/ip/tcp.c:38,431998/1118/sys/src/9/ip/tcp.c:38,44 (short | long)
1997/0327    
	MSPTICK		= 50,		/* Milliseconds per timer tick */ 
	DEF_MSS		= 1024,		/* Default mean segment */ 
1998/0630    
	DEF_RTT		= 150,		/* Default round trip */ 
1998/1118    
	DEF_KAT		= 10000,	/* Default keep alive trip in ms */ 
1997/0327    
	TCP_LISTEN	= 0,		/* Listen connection */ 
	TCP_CONNECT	= 1,		/* Outgoing connection */ 
 
1998/1008/sys/src/9/ip/tcp.c:171,1811998/1118/sys/src/9/ip/tcp.c:172,182
1997/0327    
	Timer	timer;			/* Activity timer */ 
	Timer	acktimer;		/* Acknowledge timer */ 
	Timer	rtt_timer;		/* Round trip timer */ 
1998/1118    
	Timer	katimer;		/* keep alive timer */ 
1997/0327    
	ulong	rttseq;			/* Round trip sequence */ 
	int	srtt;			/* Shortened round trip */ 
	int	mdev;			/* Mean deviation of round trip */ 
	int	kacounter;		/* count down for keep alive */ 
	int	f2counter;		/* count down for finwait2 state */ 
	uint	sndsyntime;		/* time syn sent */ 
1998/0306    
 
	Tcphdr	protohdr;		/* prototype header */ 
1998/1008/sys/src/9/ip/tcp.c:237,2421998/1118/sys/src/9/ip/tcp.c:238,244
1997/0327    
void	tcpsndsyn(Tcpctl*); 
void	tcprcvwin(Conv*); 
void	tcpacktimer(Conv*); 
1998/1118    
void	tcpkeepalive(Conv*); 
1997/0327    
 
void 
1998/0306    
tcpsetstate(Conv *s, uchar newstate) 
1998/1008/sys/src/9/ip/tcp.c:554,5591998/1118/sys/src/9/ip/tcp.c:556,562
1998/0313    
	tcphalt(tpriv, &tcb->timer); 
	tcphalt(tpriv, &tcb->rtt_timer); 
1998/0925    
	tcphalt(tpriv, &tcb->acktimer); 
1998/1118    
	tcphalt(tpriv, &tcb->katimer); 
1997/0327    
 
	/* Flush reassembly queue; nothing more can arrive */ 
	for(rp = tcb->reseq; rp != nil; rp = rp1) { 
1998/1008/sys/src/9/ip/tcp.c:594,5991998/1118/sys/src/9/ip/tcp.c:597,606
1997/0327    
	tcb->acktimer.start = TCP_ACK / MSPTICK; 
	tcb->acktimer.func = tcpacktimer; 
	tcb->acktimer.arg = s; 
1998/1118    
	tcb->kacounter = 0; 
	tcb->katimer.start = DEF_KAT / MSPTICK; 
	tcb->katimer.func = tcpkeepalive; 
	tcb->katimer.arg = s; 
1998/0306    
 
	/* create a prototype(pseudo) header */ 
	if(ipcmp(s->laddr, IPnoaddr) == 0) 
1998/1008/sys/src/9/ip/tcp.c:1007,10141998/1118/sys/src/9/ip/tcp.c:1014,1019
1998/0313    
	tpriv = s->p->priv; 
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
 
	tcb->kacounter = MAXBACKOFF;	/* keep alive count down */ 
                 
	if(seq_gt(seg->ack, tcb->snd.nxt)) { 
		tcb->flags |= FORCE; 
		return; 
1998/1008/sys/src/9/ip/tcp.c:1224,12291998/1118/sys/src/9/ip/tcp.c:1229,1237
1997/0327    
	tcb = (Tcpctl*)s->ptcl; 
	qlock(tcb); 
 
1998/1118    
	if(tcb->kacounter > 0) 
		tcb->kacounter = MAXBACKOFF; 
 
1997/0327    
	switch(tcb->state) { 
	case Closed: 
1998/0313    
		sndrst(tcp, source, dest, length, &seg); 
1998/1008/sys/src/9/ip/tcp.c:1343,13511998/1118/sys/src/9/ip/tcp.c:1351,1359
1997/0327    
		case Finwait1: 
			update(s, &seg); 
			if(tcb->sndcnt == 0){ 
				tcb->f2counter = MAXBACKOFF; 
1998/1118    
				tcb->kacounter = MAXBACKOFF; 
1997/0327    
				tcpsetstate(s, Finwait2); 
				tcb->timer.start = MSL2 * (1000 / MSPTICK); 
1998/1118    
				tcb->katimer.start = MSL2 * (1000 / MSPTICK); 
1998/0313    
				tcpgo(tpriv, &tcb->timer); 
1997/0327    
			} 
			break; 
1998/1008/sys/src/9/ip/tcp.c:1686,16911998/1118/sys/src/9/ip/tcp.c:1694,1701
1997/0327    
		} 
 
1998/0313    
		tpriv->tstats.tcpOutSegs++; 
1998/1118    
		if(tcb->kacounter > 0) 
			tcpgo(tpriv, &tcb->katimer); 
1998/0313    
		ipoput(f, hbp, 0, s->ttl); 
1997/0327    
	} 
} 
1998/1008/sys/src/9/ip/tcp.c:1694,17001998/1118/sys/src/9/ip/tcp.c:1704,1710
1998/0306    
 *  the BSD convention (hack?) for keep alives.  resend last uchar acked. 
1997/0327    
 */ 
void 
tcpkeepalive(Conv *s) 
1998/1118    
tcpsendka(Conv *s) 
1997/0327    
{ 
	Tcp seg; 
	Tcpctl *tcb; 
1998/1008/sys/src/9/ip/tcp.c:1730,17361998/1118/sys/src/9/ip/tcp.c:1740,1787
1998/0313    
	ipoput(s->p->f, hbp, 0, s->ttl); 
1997/0327    
} 
 
1998/1118    
/* 
 *  if we've timed out, close the connection 
 *  otherwise, send a keepalive and restart the timer 
 */ 
1997/0327    
void 
1998/1118    
tcpkeepalive(Conv *s) 
{ 
	Tcpctl *tcb; 
 
	tcb = (Tcpctl*)s->ptcl; 
	if(--(tcb->kacounter) <= 0) 
		localclose(s, Etimedout); 
	else { 
		qlock(tcb); 
		tcpsendka(s); 
		qunlock(tcb); 
		tcpgo(s->p->priv, &tcb->katimer); 
	} 
} 
 
/* 
 *  start keepalive timer 
 */ 
char* 
tcpstartka(Conv *s, char **f, int n) 
{ 
	Tcpctl *tcb; 
	int x; 
 
	tcb = (Tcpctl*)s->ptcl; 
	if(n > 1){ 
		x = atoi(f[1]); 
		if(x >= MSPTICK) 
			tcb->katimer.start = x/MSPTICK; 
	} 
	tcb->kacounter = MAXBACKOFF; 
	tcpgo(s->p->priv, &tcb->katimer); 
 
	return nil; 
} 
 
void 
1997/0327    
tcprxmit(Conv *s) 
{ 
	Tcpctl *tcb; 
1998/1008/sys/src/9/ip/tcp.c:1782,17971998/1118/sys/src/9/ip/tcp.c:1833,1838
1997/0327    
		} 
		tcprxmit(s); 
		break; 
	case Finwait2: 
		if(--(tcb->f2counter) <= 0) 
			localclose(s, Etimedout); 
		else { 
			qlock(tcb); 
			tcpkeepalive(s); 
			qunlock(tcb); 
1998/0313    
			tcpgo(s->p->priv, &tcb->timer); 
1997/0327    
		} 
		break; 
	case Time_wait: 
		localclose(s, nil); 
		break; 
1998/1008/sys/src/9/ip/tcp.c:2001,20061998/1118/sys/src/9/ip/tcp.c:2042,2049
1997/0327    
{ 
	if(n == 1 && strcmp(f[0], "hangup") == 0) 
		return tcphangup(c); 
1998/1118    
	if(n >= 1 && strcmp(f[0], "keepalive") == 0) 
		return tcpstartka(c, f, n); 
1997/0327    
	return "unknown control request"; 
} 
 
1998/1118/sys/src/9/ip/tcp.c:567,5721998/1127/sys/src/9/ip/tcp.c:567,574 (short | long)
1997/0327    
 
	if(tcb->state == Syn_sent) 
1998/0313    
		Fsconnected(s, reason); 
1998/1127    
	if(s->state == Announced) 
		wakeup(&s->listenr); 
1997/0327    
 
	qhangup(s->rq, reason); 
	qhangup(s->wq, reason); 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)