Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/ip/rudp.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname ip/rudp.c 1998/0630
## diff -e /dev/null /n/emeliedump/1998/0630/sys/src/brazil/ip/rudp.c
0a

#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

#include	"ip.h"

#define DPRINT if(1)print

enum
{
	RUDP_PHDRSIZE	= 12,
	RUDP_HDRSIZE	= 36,
	RUDP_RHDRSIZE	= 16,
	RUDP_IPHDR	= 8,
	IP_RUDPPROTO	= 254,
	RUDP_USEAD6	= 36,
	RUDP_USEAD4	= 12,

	Rudprxms	= 200,
	Rudptickms	= 100,
	Rudpmaxxmit	= 1,

};

/*
 *  reliable header
 */
typedef struct Relhdr Relhdr;
struct Relhdr
{
	uchar	relseq[4];	/* id of this packet (or 0) */
	uchar	relsgen[4];	/* generation/time stamp */
	uchar	relack[4];	/* packet being acked (or 0) */
	uchar	relagen[4];	/* generation/time stamp */
};

typedef struct Rudphdr Rudphdr;
struct Rudphdr
{
	/* ip header */
	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	rudpproto;	/* Protocol */
	uchar	rudpplen[2];	/* Header plus data length */
	uchar	rudpsrc[4];	/* Ip source */
	uchar	rudpdst[4];	/* Ip destination */

	/* rudp header */
	uchar	rudpsport[2];	/* Source port */
	uchar	rudpdport[2];	/* Destination port */
	Relhdr	rhdr;		/* reliable header */
	uchar	rudplen[2];	/* data length */
	uchar	rudpcksum[2];	/* Checksum */
};


/*
 *  one state structure per destination
 */
typedef struct Reliable Reliable;
struct Reliable
{
	Reliable *next;

	uchar addr[IPaddrlen];	/* always V6 when put here */
	ushort	port;


	Block	*unacked;	/* unacked msg list */
	Block	*unackedtail;	/*  and its tail */

	int	timeout;	/* time since first unacked msg sent */
	int	xmits;		/* number of times first unacked msg sent */

	ulong	sndseq;		/* next packet to be sent */
	ulong	sndgen;		/*  and its generation */

	ulong	rcvseq;		/* last packet received */
	ulong	rcvgen;		/*  and its generation */

	ulong	acksent;	/* last ack sent */
	ulong	ackrcvd;	/* last msg for which ack was rcvd */
};



/* MIB II counters */
typedef struct Rudpstats Rudpstats;
struct Rudpstats
{
	ulong	rudpInDatagrams;
	ulong	rudpNoPorts;
	ulong	rudpInErrors;
	ulong	rudpOutDatagrams;
};

typedef struct Rudppriv Rudppriv;
struct Rudppriv
{


	/* MIB counters */
	Rudpstats	ustats;

	/* non-MIB stats */
	ulong		csumerr;		/* checksum errors */
	ulong		lenerr;			/* short packet */

};


static ulong generation = 0;
static Rendez rend;
/*
 *  protocol specific part of Conv
 */
typedef struct Rudpcb Rudpcb;
struct Rudpcb
{
	QLock;
	uchar	headers;
	Reliable *r;
};

/*
 * local functions 
 */
void	relsendack( Conv *, Reliable * );
int	reliput( Conv *, Block *, uchar *, ushort );
Reliable *relstate( Rudpcb *, uchar *, ushort );
void	relackproc( void * );
void	relackq( Reliable *, Block * );
void	relhangup( Conv *, Reliable * );
void	relrexmit( Conv *, Reliable * );

static char*
rudpconnect(Conv *c, char **argv, int argc)
{
	char *e;

	e = Fsstdconnect(c, argv, argc);
	Fsconnected(c, e);

	return e;
}


static int
rudpstate(Conv *c, char *state, int n)
{
	USED(c);
	return snprint(state, n, "%s", "Reliable UDP");
}

static char*
rudpannounce(Conv *c, char** argv, int argc)
{
	char *e;

	e = Fsstdannounce(c, argv, argc);
	if(e != nil)
		return e;
	Fsconnected(c, nil);

	return nil;
}

static void
rudpcreate(Conv *c)
{
	c->rq = qopen(64*1024, 1, 0, 0);
	c->wq = qopen(64*1024, 0, 0, 0);
}

static void
rudpclose(Conv *c)
{
	Rudpcb *ucb;
	Reliable *r, *nr;

	qclose(c->rq);
	qclose(c->wq);
	qclose(c->eq);
	ipmove(c->laddr, IPnoaddr);
	ipmove(c->raddr, IPnoaddr);
	c->lport = 0;
	c->rport = 0;

	ucb = (Rudpcb*)c->ptcl;
	ucb->headers = 0;
	qlock( ucb );
	for( r = ucb->r; r; r = nr ){
		nr = r->next;
		relhangup( c, r );
		free( r );
	}
	ucb->r = 0;

	qunlock( ucb );

	unlock(c);
}

void
rudpkick(Conv *c, int)
{
	Rudphdr *uh;
	ushort rport;
	uchar laddr[IPaddrlen], raddr[IPaddrlen];
	Block *bp;
	Rudpcb *ucb;
	Relhdr *rh;
	Reliable *r;
	int dlen, ptcllen;
	Rudppriv *upriv;
	Fs *f;

	upriv = c->p->priv;
	f = c->p->f;

	netlog(c->p->f, Logrudp, "rudp: kick\n");
	bp = qget(c->wq);
	if(bp == nil)
		return;

	ucb = (Rudpcb*)c->ptcl;
	switch(ucb->headers) {
	case 6:
		/* get user specified addresses */
		bp = pullupblock(bp, RUDP_USEAD6);
		if(bp == nil)
			return;
		ipmove(raddr, bp->rp);
		bp->rp += IPaddrlen;
		ipmove(laddr, bp->rp);
		bp->rp += IPaddrlen;
		/* pick interface closest to dest */
		if(ipforme(f, laddr) != Runi)
			findlocalip(f, laddr, raddr);
		rport = nhgets(bp->rp);

		bp->rp += 4;			/* Igonore local port */
		break;
	case 4:
		bp = pullupblock(bp, RUDP_USEAD4);
		if(bp == nil)
			return;
		v4tov6(raddr, bp->rp);
		bp->rp += IPv4addrlen;
		v4tov6(laddr, bp->rp);
		bp->rp += IPv4addrlen;
		if(ipforme(f, laddr) != Runi)
			findlocalip(f, laddr, raddr);
		rport = nhgets(bp->rp);

		bp->rp += 4;			/* Igonore local port */
		break;
	default:
		rport = 0;

		break;
	}

	dlen = blocklen(bp);

	/* Make space to fit rudp & ip header */
	bp = padblock(bp, RUDP_IPHDR+RUDP_HDRSIZE);
	if(bp == nil)
		return;

	uh = (Rudphdr *)(bp->rp);

	rh = &(uh->rhdr);

	ptcllen = dlen + (RUDP_HDRSIZE-RUDP_PHDRSIZE);
	uh->Unused = 0;
	uh->rudpproto = IP_RUDPPROTO;
	uh->frag[0] = 0;
	uh->frag[1] = 0;
	hnputs(uh->rudpplen, ptcllen);
	switch(ucb->headers){
	case 4:
	case 6:
		v6tov4(uh->rudpdst, raddr);
		hnputs(uh->rudpdport, rport);
		v6tov4(uh->rudpsrc, laddr);
		break;
	default:
		v6tov4(uh->rudpdst, c->raddr);
		hnputs(uh->rudpdport, c->rport);
		if(ipcmp(c->laddr, IPnoaddr) == 0)
			findlocalip(f, c->laddr, c->raddr);
		v6tov4(uh->rudpsrc, c->laddr);
		break;
	}
	hnputs(uh->rudpsport, c->lport);
	hnputs(uh->rudplen, ptcllen);
	uh->rudpcksum[0] = 0;
	uh->rudpcksum[1] = 0;


	qlock( ucb );
	r = relstate( ucb, raddr, rport );
	r->sndseq++;
	hnputl( rh->relseq, r->sndseq );
	hnputl( rh->relsgen, r->sndgen );

	hnputl( rh->relack, r->rcvseq );  /* ACK last rcvd packet */
	hnputl( rh->relagen, r->rcvgen );

	if(r->rcvseq < r->acksent)
		r->acksent = r->rcvseq;

	hnputs(uh->rudpcksum, ptclcsum(bp, RUDP_IPHDR, dlen+RUDP_HDRSIZE));

	relackq( r, bp );
	qunlock( ucb );

	upriv->ustats.rudpOutDatagrams++;



	DPRINT( "sent: %d/%d, %d/%d\n", 
		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen );

	ipoput(f, bp, 0, c->ttl);
}

void
rudpiput(Proto *rudp, uchar *ia, Block *bp)
{
	int len, olen, ottl;
	Rudphdr *uh;
	Conv *c, **p;
	Rudpcb *ucb;
	uchar raddr[IPaddrlen], laddr[IPaddrlen];
	ushort rport, lport;
	Rudppriv *upriv;
	Fs *f;

	upriv = rudp->priv;
	f = rudp->f;

	upriv->ustats.rudpInDatagrams++;

	uh = (Rudphdr*)(bp->rp);

	/* Put back pseudo header for checksum 
	 * (remember old values for icmpnoconv()) 
	 */
	ottl = uh->Unused;
	uh->Unused = 0;
	len = nhgets(uh->rudplen);
	olen = nhgets(uh->rudpplen);
	hnputs(uh->rudpplen, len);

	v4tov6(raddr, uh->rudpsrc);
	v4tov6(laddr, uh->rudpdst);
	lport = nhgets(uh->rudpdport);
	rport = nhgets(uh->rudpsport);



	if(nhgets(uh->rudpcksum)) {
		if(ptclcsum(bp, RUDP_IPHDR, len+RUDP_PHDRSIZE)) {
			upriv->ustats.rudpInErrors++;
			netlog(f, Logrudp, "rudp: checksum error %I\n", raddr);
			DPRINT("rudp: checksum error %I\n", raddr);
			freeblist(bp);
			return;
		}
	}

	/* Look for a conversation structure for this port */
	c = nil;
	for(p = rudp->conv; *p; p++) {
		c = *p;
		if(c->inuse == 0)
			continue;
		if(c->lport == lport && (c->rport == 0 || c->rport == rport))
			break;
	}

	if(*p == nil) {
		upriv->ustats.rudpNoPorts++;
		netlog(f, Logrudp, "rudp: no conv %I!%d -> %I!%d\n", raddr, rport,
			laddr, lport);
		DPRINT( "rudp: no conv %I!%d -> %I!%d\n", raddr, rport,
			laddr, lport);
		uh->Unused = ottl;
		hnputs(uh->rudpplen, olen);
		icmpnoconv(f, bp);
		freeblist(bp);
		return;
	}

	ucb = (Rudpcb*)c->ptcl;

	qlock( ucb );
	if( reliput( c, bp, raddr, rport ) < 0 ){
		qunlock( ucb );
		freeb( bp );
		return;
	}

	/*
	 * Trim the packet down to data size
	 */

	len -= (RUDP_HDRSIZE-RUDP_PHDRSIZE);
	bp = trimblock(bp, RUDP_IPHDR+RUDP_HDRSIZE, len);
	if(bp == nil){
		netlog(f, Logrudp, "rudp: len err %I.%d -> %I.%d\n", 
			raddr, rport, laddr, lport);
		DPRINT( "rudp: len err %I.%d -> %I.%d\n", 
			raddr, rport, laddr, lport);
		upriv->lenerr++;
		return;
	}

	netlog(f, Logrudpmsg, "rudp: %I.%d -> %I.%d l %d\n", 
		raddr, rport, laddr, lport, len);



	switch(ucb->headers){
	case 6:
		/* pass the src address */
		bp = padblock(bp, RUDP_USEAD6);
		ipmove(bp->rp, raddr);
		if(ipforme(f, laddr) == Runi)
			ipmove(bp->rp+IPaddrlen, laddr);
		else
			ipmove(bp->rp+IPaddrlen, ia);
		hnputs(bp->rp+2*IPaddrlen, rport);
		hnputs(bp->rp+2*IPaddrlen+2, lport);
		break;
	case 4:
		/* pass the src address */
		bp = padblock(bp, RUDP_USEAD4);
		v6tov4(bp->rp, raddr);
		if(ipforme(f, laddr) == Runi)
			v6tov4(bp->rp+IPv4addrlen, laddr);
		else
			v6tov4(bp->rp+IPv4addrlen, ia);
		hnputs(bp->rp + 2*IPv4addrlen, rport);
		hnputs(bp->rp + 2*IPv4addrlen + 2, lport);
		break;
	default:
		/* connection oriented rudp */
		if(c->raddr == 0){
			/* save the src address in the conversation */
		 	ipmove(c->raddr, raddr);
			c->rport = rport;

			/* reply with the same ip address (if not broadcast) */
			if(ipforme(f, laddr) == Runi)
				ipmove(c->laddr, laddr);
			else
				v4tov6(c->laddr, ia);
		}
		break;
	}
	if(bp->next)
		bp = concatblock(bp);

	if(qfull(c->rq)){
		netlog(f, Logrudp, "rudp: qfull %I.%d -> %I.%d\n", raddr, rport,
			laddr, lport);
		freeblist(bp);
	}
	else
		qpass(c->rq, bp);
	
	qunlock( ucb );
}

char*
rudpctl(Conv *c, char **f, int n)
{
	Rudpcb *ucb;

	ucb = (Rudpcb*)c->ptcl;
	if(n == 1){
		if(strcmp(f[0], "headers4") == 0){
			ucb->headers = 4;
			return nil;
		} else if(strcmp(f[0], "headers") == 0){
			ucb->headers = 6;
			return nil;
		}
	}
	return "unknown control request";
}

void
rudpadvise(Proto *rudp, Block *bp, char *msg)
{
	Rudphdr *h;
	uchar source[IPaddrlen], dest[IPaddrlen];
	ushort psource, pdest;
	Conv *s, **p;

	h = (Rudphdr*)(bp->rp);

	v4tov6(dest, h->rudpdst);
	v4tov6(source, h->rudpsrc);
	psource = nhgets(h->rudpsport);
	pdest = nhgets(h->rudpdport);

	/* Look for a connection */
	for(p = rudp->conv; *p; p++) {
		s = *p;
		if(s->rport == pdest)
		if(s->lport == psource)
		if(ipcmp(s->raddr, dest) == 0)
		if(ipcmp(s->laddr, source) == 0){
			qhangup(s->rq, msg);
			qhangup(s->wq, msg);
			break;
		}
	}
	freeblist(bp);
}

int
rudpstats(Proto *rudp, char *buf, int len)
{
	Rudppriv *upriv;

	upriv = rudp->priv;
	return snprint(buf, len, "%d %d %d %d\n",
		upriv->ustats.rudpInDatagrams,
		upriv->ustats.rudpNoPorts,
		upriv->ustats.rudpInErrors,
		upriv->ustats.rudpOutDatagrams);
}

void
rudpinit(Fs *fs)
{

	Proto *rudp;

	rudp = smalloc(sizeof(Proto));
	rudp->priv = smalloc(sizeof(Rudppriv));
	rudp->name = "rudp";
	rudp->kick = rudpkick;
	rudp->connect = rudpconnect;
	rudp->announce = rudpannounce;
	rudp->ctl = rudpctl;
	rudp->state = rudpstate;
	rudp->create = rudpcreate;
	rudp->close = rudpclose;
	rudp->rcv = rudpiput;
	rudp->advise = rudpadvise;
	rudp->stats = rudpstats;
	rudp->ipproto = IP_RUDPPROTO;
	rudp->nc = 16;
	rudp->ptclsize = sizeof(Rudpcb);

	Fsproto(fs, rudp);

	kproc( "relackproc", relackproc, rudp );
	
}

/*********************************************/
/* Here starts the reliable helper functions */
/*********************************************/
/*
 *  Enqueue a copy of an unacked block for possible retransmissions
 */
void
relackq(Reliable *r, Block *bp)
{
	Block *np;

	np = copyblock(bp, blocklen(bp));
	if(r->unacked)
		r->unackedtail->list = np;
	else {
		/* restart timer */
		r->timeout = 0;
		r->xmits = 1;
		r->unacked = np;
	}
	r->unackedtail = np;
	np->list = nil;
}

/*
 *  retransmit unacked blocks
 */
void
relackproc(void *a)
{
	Rudpcb *ucb;
	Proto *rudp;
	Reliable *r;
	Conv **s, *c;

	rudp = (Proto *)a;
loop:
	tsleep(&rend, return0, 0, Rudptickms);

	for(s = rudp->conv; *s; s++) {
		c = *s;
		ucb = (Rudpcb*)c->ptcl;
		qlock( ucb );

		for(r = ucb->r; r; r = r->next){

			if(r->unacked != nil){
				r->timeout += Rudptickms;
				if(r->timeout > Rudprxms*r->xmits)
					relrexmit(c, r);
			}
			if(r->acksent < r->rcvseq)
				relsendack(c, r);
		}
		qunlock( ucb );
	}
	goto loop;
}

/*
 *  get the state record for a conversation
 */
Reliable*
relstate(Rudpcb *ucb, uchar *addr, ushort port)
{
	Reliable *r, **l;


	l = &ucb->r;
	for(r = *l; r; r = *l){
		if( memcmp( addr, r->addr, IPaddrlen) == 0 && 
		    port == r->port)
			break;
		l = &r->next;
	}

	/* no state for this addr/port, create some */
	if(r == nil){
		DPRINT( "new state %d\n", generation );
		if(generation == 0)
			generation = TK2SEC(MACHP(0)->ticks);
		r = smalloc( sizeof( Reliable ) );
		*l = r;
		memmove( r->addr, addr, IPaddrlen);
		r->port = port;
		r->unacked = 0;
		r->sndgen = generation++;
		r->sndseq = 0;
		r->ackrcvd = 0;
		r->rcvgen = 0;
		r->rcvseq = 0;
		r->acksent = 0;
		r->xmits = 0;
		r->timeout = 0;
	}

	return r;
}


/* 
 *  process a rcvd reliable packet. return -1 if not to be passed to user process,
 *  0 therwise.
 */
int
reliput(Conv *c, Block *bp, uchar *addr, ushort port)
{
	Block *nbp;
	Rudpcb *ucb;
	Rudphdr *uh;
	Reliable *r;
	Relhdr *rh;
	ulong seq, ack, sgen, agen, ackreal;



	/* get fields */
	uh = (Rudphdr *)(bp->rp);
	rh = &(uh->rhdr);
	seq = nhgetl(rh->relseq);
	sgen = nhgetl(rh->relsgen);
	ack = nhgetl(rh->relack);
	agen = nhgetl(rh->relagen);



	ucb = (Rudpcb*)c->ptcl;
	r = relstate(ucb, addr, port);
	

	DPRINT("rcvd %d/%d, %d/%d, r->sndgen = %d, r->ackrcvd = %d\n", 
		seq, sgen, ack, agen, r->sndgen, r->ackrcvd);

	/* dequeue acked packets */
	if(ack && agen == r->sndgen){
		DPRINT( "Here\n" );
		ackreal = 0;
		while(r->unacked != nil && ack > r->ackrcvd){
			nbp = r->unacked;
			r->unacked = nbp->list;
			DPRINT("%d/%d acked\n", ack, agen);
			freeb(nbp);
			r->ackrcvd++;
			ackreal = 1;
		}

		/*
		 *  retransmit next packet if the acked packet
		 *  was transmitted more than once
		 */
		if(ackreal && r->unacked != nil){
			r->timeout = 0;
			if(r->xmits > 1){
				r->xmits = 1;
				relrexmit(c, r);
			}
		}
		
	}

	/* make sure we're not talking to a new remote side */
	if(r->rcvgen != sgen){
		if(seq != 1)
			return -1;


		/* new connection */
		if(r->rcvgen != 0){
			DPRINT("new con r->rcvgen = %d, sgen = %d\n", r->rcvgen, sgen);
			relhangup(c, r);
		}
		r->rcvgen = sgen;
	}

	/* no message */
	if(seq == 0)
		return -1;

	/* refuse out of order delivery */
	if(seq != r->rcvseq + 1){
		DPRINT("out of sequence %d not %d\n", seq, r->rcvseq + 1);
		return -1;
	}
	r->rcvseq = seq;

	return 0;
}

void
relsendack(Conv *c, Reliable *r)
{
	Rudphdr *uh;
	Block *bp;
	Relhdr *rh;
	int ptcllen;
	Fs *f;

	bp = allocb(RUDP_IPHDR + RUDP_HDRSIZE);
	if(bp == nil)
		return;
	bp->wp += RUDP_IPHDR + RUDP_HDRSIZE;
	f = c->p->f;
	uh = (Rudphdr *)(bp->rp);
	rh = &(uh->rhdr);

	ptcllen = (RUDP_HDRSIZE-RUDP_PHDRSIZE);
	uh->Unused = 0;
	uh->rudpproto = IP_RUDPPROTO;
	uh->frag[0] = 0;
	uh->frag[1] = 0;
	hnputs(uh->rudpplen, ptcllen);



	v6tov4( uh->rudpdst, r->addr );
	hnputs(uh->rudpdport, r->port);
	hnputs(uh->rudpsport, c->lport);
	if(ipcmp(c->laddr, IPnoaddr) == 0)
		findlocalip(f, c->laddr, c->raddr);
	v6tov4(uh->rudpsrc, c->laddr);
	hnputs(uh->rudplen, ptcllen);



	hnputl(rh->relsgen, r->sndgen);
	hnputl(rh->relseq, 0);
	hnputl(rh->relagen, r->rcvgen);
	hnputl(rh->relack, r->rcvseq);

	if(r->acksent < r->rcvseq)
		r->acksent = r->rcvseq;

	uh->rudpcksum[0] = 0;
	uh->rudpcksum[1] = 0;
	hnputs(uh->rudpcksum, ptclcsum(bp, RUDP_IPHDR, RUDP_HDRSIZE));

	DPRINT( "sendack: %d/%d, %d/%d\n", 0, r->sndgen, r->rcvseq, r->rcvgen );
	ipoput(f, bp, 0, c->ttl);
}

/*
 *  called with ucb locked (and c locked if user initiated close)
 */
void
relhangup( Conv *, Reliable *r )
{
	Block *bp;

	/*
	 *  dump any unacked outgoing messages
	 */
	for(bp = r->unacked; bp != nil; bp = r->unacked){
		r->unacked = bp->list;
		bp->list = nil;
		freeb(bp);
	}

	r->rcvgen = 0;
	r->rcvseq = 0;
	r->acksent = 0;
	r->sndgen = generation++;
	r->sndseq = 0;
	r->ackrcvd = 0;
	r->xmits = 0;
	r->timeout = 0;
}

/*
 *  called with ucb locked
 */
void
relrexmit(Conv *c, Reliable *r)
{
	Block *np;
	Fs *f;
	f = c->p->f;
	r->timeout = 0;
	if(r->xmits++ > Rudpmaxxmit){
		relhangup(c, r);
		return;
	}

	np = copyblock(r->unacked, blocklen(r->unacked));
	//DPRINT("rxmit r->ackrvcd+1 = %d\n", r->ackrcvd+1);
	ipoput(f, np, 0, c->ttl);
}
.
## diffname ip/rudp.c 1998/0726
## diff -e /n/emeliedump/1998/0630/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/0726/sys/src/brazil/ip/rudp.c
859c
	DPRINT("rxmit r->ackrvcd+1 = %d\n", r->ackrcvd+1);
.
857a
	upriv->rxmits++;
.
850a

	upriv = c->p->priv;
.
848a
	Rudppriv *upriv;
.
755a
		upriv->orders++;
.
753a
	if( DEBUG && ++drop == drop_rate ){
		DPRINT( "drop pkt on purpose\n" );
		drop = 0;
		return -1;
	}

.
716c
			DPRINT("%d/%d acked, r->sndgen = %d\n", 
			       ack, agen, r->sndgen);
.
711d
706,707c
	DPRINT("rcvd %d/%d, %d/%d, r->sndgen = %d\n", 
		seq, sgen, ack, agen, r->sndgen);
.
703c
	r = relstate(ucb, addr, port, "input" );
.
701c
	upriv = c->p->priv;
.
684a
	Rudppriv *upriv;
.
656a
		DPRINT( "from %s new state %d for %I!%d\n", 
		        from, generation, addr, port );
.
654d
643a

.
639c
relstate(Rudpcb *ucb, uchar *addr, ushort port, char *from )
.
630c
		qunlock(ucb);
.
620,621c
		for(r = ucb->r; r; r = r->next) {
.
618c
		qlock(ucb);
.
613c
	tsleep(&upriv->vous, return0, 0, Rudptickms);
.
611a
	upriv = rudp->priv;

.
609a
	Rudppriv *upriv;
.
572c
	kproc("relackproc", relackproc, rudp);
.
544c
		upriv->ustats.rudpOutDatagrams,
		upriv->rxmits,
		upriv->orders);
.
540c
	return snprint(buf, len, "%d %d %d %d %d %d\n",
.
374a
			upriv->csumerr++;
.
331,332c
	DPRINT( "sent: %d/%d, %d/%d, r->sndgen = %d\n", 
		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen, r->sndgen );
.
311c
	r = relstate( ucb, raddr, rport, "kick" );
.
282a

.
267c
		ipmove( raddr, c->raddr );
		ipmove( laddr, c->laddr );
		rport = c->rport;
.
160c
	return snprint(state, n, "%s", "Reliable UDP V0.1");
.
138c
Reliable *relstate( Rudpcb *, uchar *, ushort, char *from );
.
121a

/* Used only for debugging */
static ushort drop = 0;
static ushort drop_rate = 10;

.
114,115c
	ulong	csumerr;		/* checksum errors */
	ulong	lenerr;			/* short packet */
	ulong	rxmits;			/* # of retransmissions */
	ulong	orders;			/* # of out of order pkts */
.
109d
107a
	Rendez	vous;
.
25c
	Rudpmaxxmit	= 10,
.
11c
#define DEBUG	0
#define DPRINT if(DEBUG)print
.
## diffname ip/rudp.c 1998/0728
## diff -e /n/emeliedump/1998/0726/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/0728/sys/src/brazil/ip/rudp.c
846c
relhangup(Conv *, Reliable *r)
.
838c
	DPRINT("sendack: %d/%d, %d/%d\n", 0, r->sndgen, r->rcvseq, r->rcvgen);
.
834,836c
	uh->udpcksum[0] = 0;
	uh->udpcksum[1] = 0;
	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, UDP_RHDRSIZE));
.
824,825d
821,822c
	v6tov4(uh->udpsrc, c->laddr);
	hnputs(uh->udplen, ptcllen);
.
814,818c
	v6tov4(uh->udpdst, r->addr);
	hnputs(uh->udpdport, r->port);
	hnputs(uh->udpsport, c->lport);
.
812c
	hnputs(uh->udpplen, ptcllen);
.
809c
	uh->udpproto = IP_UDPPROTO;
.
807c
	ptcllen = (UDP_RHDRSIZE-UDP_PHDRSIZE);
.
804,805c
	uh = (Udphdr *)(bp->rp);
	rh = (Rudphdr*)uh;
.
802c
	bp->wp += UDP_IPHDR + UDP_RHDRSIZE;
.
799c
	bp = allocb(UDP_IPHDR + UDP_RHDRSIZE);
.
795c
	Rudphdr *rh;
.
793c
	Udphdr *uh;
.
773,774c
	if(DEBUG && ++drop == drop_rate){
		DPRINT("drop pkt on purpose\n");
.
722c
	r = relstate(ucb, addr, port, "input");
.
712,713c
	uh = (Udphdr*)(bp->rp);
	rh = (Rudphdr*)uh;
.
706c
	Rudphdr *rh;
.
704c
	Udphdr *uh;
.
677c
		memmove(r->addr, addr, IPaddrlen);
.
673,675c
		DPRINT("from %s new state %d for %I!%d\n", 
		        from, generation, addr, port);
		r = smalloc(sizeof(Reliable));
.
663c
		if(memcmp(addr, r->addr, IPaddrlen) == 0 && 
.
659,660d
655c
relstate(Rudpcb *ucb, uchar *addr, ushort port, char *from)
.
580c
	rudp->ipproto = IP_UDPPROTO;
.
526,529c
	v4tov6(dest, h->udpdst);
	v4tov6(source, h->udpsrc);
	psource = nhgets(h->udpsport);
	pdest = nhgets(h->udpdport);
.
524c
	h = (Udphdr*)(bp->rp);
.
519c
	Udphdr *h;
.
495c
	qunlock(ucb);
.
460c
		bp = padblock(bp, UDP_USEAD4);
.
449c
		bp = padblock(bp, UDP_USEAD6);
.
444,445d
435c
		DPRINT("rudp: len err %I.%d -> %I.%d\n", 
.
430,431c
	len -= (UDP_RHDRSIZE-UDP_PHDRSIZE);
	bp = trimblock(bp, UDP_IPHDR+UDP_RHDRSIZE, len);
.
419,422c
	qlock(ucb);
	if(reliput(c, bp, raddr, rport) < 0){
		qunlock(ucb);
		freeb(bp);
.
411c
		hnputs(uh->udpplen, olen);
.
408c
		DPRINT("rudp: no conv %I!%d -> %I!%d\n", raddr, rport,
.
400,401c
		if(c->lport == lport){
			ucb = (Rudpcb*)c->ptcl;

			/* with headers turned on, descriminate only on local port */
			if(ucb->headers)
				break;

			/* otherwise discriminate on lport, rport, and raddr */
			if(c->rport == 0 || c->rport == rport)
			if(ipisbm(c->raddr) || ipcmp(c->raddr, IPnoaddr) == 0
			   || ipcmp(c->raddr, raddr) == 0)
				break;
		}
.
381,384c
	if(nhgets(uh->udpcksum)) {
		if(ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE)) {
.
376,379c
	v4tov6(raddr, uh->udpsrc);
	v4tov6(laddr, uh->udpdst);
	lport = nhgets(uh->udpdport);
	rport = nhgets(uh->udpsport);
.
372,374c
	len = nhgets(uh->udplen);
	olen = nhgets(uh->udpplen);
	hnputs(uh->udpplen, len);
.
365c
	uh = (Udphdr*)(bp->rp);
.
352c
	Udphdr *uh;
.
341,344d
339a
	DPRINT("sent: %d/%d, %d/%d, r->sndgen = %d\n", 
		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen, r->sndgen);
.
335,336c
	relackq(r, bp);
	qunlock(ucb);
.
333c
	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, dlen+UDP_RHDRSIZE));
.
327,328c
	hnputl(rh->relack, r->rcvseq);  /* ACK last rcvd packet */
	hnputl(rh->relagen, r->rcvgen);
.
324,325c
	hnputl(rh->relseq, r->sndseq);
	hnputl(rh->relsgen, r->sndgen);
.
320,322c
	qlock(ucb);
	r = relstate(ucb, raddr, rport, "kick");
.
315,318c
	hnputs(uh->udpsport, c->lport);
	hnputs(uh->udplen, ptcllen);
	uh->udpcksum[0] = 0;
	uh->udpcksum[1] = 0;
.
312c
		v6tov4(uh->udpsrc, c->laddr);
.
308,309c
		v6tov4(uh->udpdst, c->raddr);
		hnputs(uh->udpdport, c->rport);
.
303,305c
		v6tov4(uh->udpdst, raddr);
		hnputs(uh->udpdport, rport);
		v6tov4(uh->udpsrc, laddr);
.
299c
	hnputs(uh->udpplen, ptcllen);
.
296c
	uh->udpproto = IP_UDPPROTO;
.
293,294c
	ptcllen = dlen + (UDP_RHDRSIZE-UDP_PHDRSIZE);
.
291c
	rh = (Rudphdr*)uh;
.
289c
	uh = (Udphdr *)(bp->rp);
.
285c
	bp = padblock(bp, UDP_IPHDR+UDP_RHDRSIZE);
.
275,276c
		ipmove(raddr, c->raddr);
		ipmove(laddr, c->laddr);
.
261c
		bp = pullupblock(bp, UDP_USEAD4);
.
246c
		bp = pullupblock(bp, UDP_USEAD6);
.
228c
	Rudphdr *rh;
.
223c
	Udphdr *uh;
.
215c
	qunlock(ucb);
.
210,211c
		relhangup(c, r);
		free(r);
.
207,208c
	qlock(ucb);
	for(r = ucb->r; r; r = nr){
.
144,150c
void	relsendack(Conv *, Reliable *);
int	reliput(Conv *, Block *, uchar *, ushort);
Reliable *relstate(Rudpcb *, uchar *, ushort, char *from);
void	relackproc(void *);
void	relackq(Reliable *, Block *);
void	relhangup(Conv *, Reliable *);
void	relrexmit(Conv *, Reliable *);
.
77d
58,62c
	uchar	relseq[4];	/* id of this packet (or 0) */
	uchar	relsgen[4];	/* generation/time stamp */
	uchar	relack[4];	/* packet being acked (or 0) */
	uchar	relagen[4];	/* generation/time stamp */
.
56a
	/* pseudo header starts here */
	uchar	Unused;
	uchar	udpproto;	/* Protocol */
	uchar	udpplen[2];	/* Header plus data length */
	uchar	udpsrc[4];	/* Ip source */
	uchar	udpdst[4];	/* Ip destination */

	/* udp header */
	uchar	udpsport[2];	/* Source port */
	uchar	udpdport[2];	/* Destination port */
	uchar	udplen[2];	/* data length (includes rudp header) */
	uchar	udpcksum[2];	/* Checksum */

.
51,55d
36,39c
	/* ip header */
	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 */

	/* pseudo header starts here */
	uchar	Unused;
	uchar	udpproto;	/* Protocol */
	uchar	udpplen[2];	/* Header plus data length */
	uchar	udpsrc[4];	/* Ip source */
	uchar	udpdst[4];	/* Ip destination */

	/* udp header */
	uchar	udpsport[2];	/* Source port */
	uchar	udpdport[2];	/* Destination port */
	uchar	udplen[2];	/* data length */
	uchar	udpcksum[2];	/* Checksum */
.
30,34c
typedef struct Udphdr Udphdr;
struct Udphdr
.
16,22c
	UDP_HDRSIZE	= 20,	/* pseudo header + udp header */
	UDP_PHDRSIZE	= 12,	/* pseudo header */
	UDP_RHDRSIZE	= 36,	/* pseudo header + udp header + rudp header */
	UDP_IPHDR	= 8,	/* ip header */
	IP_UDPPROTO	= 254,
	UDP_USEAD6	= 36,
	UDP_USEAD4	= 12,
.
1c
/*
 *  This protocol is compatible with UDP's packet format.
 *  It could be done over UDP if need be.
 */
.
## diffname ip/rudp.c 1998/0731
## diff -e /n/emeliedump/1998/0728/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/0731/sys/src/brazil/ip/rudp.c
730,731d
694c
			generation = rand();
.
495c
		if(ipcmp(c->raddr, IPnoaddr) == 0){
.
## diffname ip/rudp.c 1998/0801
## diff -e /n/emeliedump/1998/0731/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/0801/sys/src/brazil/ip/rudp.c
882a
	wakeup(&r->vous);
.
802c
		DPRINT("out of sequence %d not %d\n", seq, NEXTSEQ(r->rcvseq));
.
800c
	if(seq != NEXTSEQ(r->rcvseq)){
.
789,790c
	/* no message or input queue full */
	if(seq == 0 || qfull(c->rq))
.
780d
760a
		/* flow control */
		if(UNACKED(r) < Maxunacked/8 && r->blocked)
			wakeup(&r->vous);

.
757c
			r->ackrcvd = NEXTSEQ(r->ackrcvd);
.
751c
		while(r->unacked != nil && INSEQ(ack, r->ackrcvd, r->sndseq)){
.
739d
667c
			if(r->acksent != r->rcvseq)
.
362a

	/* flow control of sorts */
	qlock(&r->lock);
	if(UNACKED(r) > Maxunacked){
		r->blocked = 1;
		sleep(&r->vous, flow, r);
		r->blocked = 0;
	}
	qunlock(&r->lock);
.
349c
	if(r->rcvseq != r->acksent)
.
342c
	r->sndseq = NEXTSEQ(r->sndseq);
.
240a
int
flow(Reliable *r)
{
	return UNACKED(r) <= Maxunacked;
}

.
188,189c
	Rudpcb *ucb;
	Reliable *r;
	int m;

	m = snprint(state, n, "%s", c->inuse?"Open":"Closed");
	ucb = (Rudpcb*)c->ptcl;
	qlock(ucb);
	for(r = ucb->r; r; r = r->next)
		m += snprint(state+m, n-m, " %I/%d", r->addr, UNACKED(r));
	qunlock(ucb);
	return m;
.
112a

	/* flow control */
	QLock	lock;
	Rendez	vous;
	int	blocked;
.
96c
	uchar	addr[IPaddrlen];	/* always V6 when put here */
.
30c
	Maxunacked	= 100,
.
16a
#define SEQDIFF(a,b) ( (a)>=(b)?\
			(a)-(b):\
			0xffffffffUL-((b)-(a)) )
#define INSEQ(a,start,end) ( (start)<=(end)?\
				((a)>(start)&&(a)<=(end)):\
				((a)>(start)||(a)<=(end)) )
#define UNACKED(r) SEQDIFF(r->sndseq, r->ackrcvd)
#define NEXTSEQ(a) ( (a)+1 == 0 ? 1 : (a)+1 )

.
## diffname ip/rudp.c 1998/0825
## diff -e /n/emeliedump/1998/0801/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/0825/sys/src/brazil/ip/rudp.c
946c
	DPRINT("rxmit r->ackrvcd+1 = %lud\n", r->ackrcvd+1);
.
894c
	DPRINT("sendack: %lud/%lud, %lud/%lud\n", 0L, r->sndgen, r->rcvseq, r->rcvgen);
.
842c
		DPRINT("out of sequence %lud not %lud\n", seq, NEXTSEQ(r->rcvseq));
.
823c
			DPRINT("new con r->rcvgen = %lud, sgen = %lud\n", r->rcvgen, sgen);
.
791c
			DPRINT("%lud/%lud acked, r->sndgen = %lud\n", 
.
782c
	DPRINT("rcvd %lud/%lud, %lud/%lud, r->sndgen = %lud\n", 
.
733c
		DPRINT("from %s new state %lud for %I!%ud\n", 
.
614c
	return snprint(buf, len, "%lud %lud %lud %lud %lud %lud\n",
.
388,389c
	DPRINT("sent: %lud/%lud, %lud/%lud\n", 
		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen);
.
210c
		m += snprint(state+m, n-m, " %I/%ld", r->addr, UNACKED(r));
.
## diffname ip/rudp.c 1998/0924
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/0924/sys/src/brazil/ip/rudp.c
647,649d
219a
	rudpstartackproc(c->p);
.
191a
	rudpstartackproc(c->p);
.
186a
static void
rudpstartackproc(Proto *rudp)
{
	Rudppriv *rpriv;
	char kpname[NAMELEN];

	rpriv = rudp->priv;
	if(rpriv->ackprocstarted == 0){
		qlock(&rpriv->apl);
		if(rpriv->ackprocstarted == 0){
			sprint(kpname, "#I%drudpack", rudp->f->dev);
			kproc(kpname, relackproc, rudp);
			rpriv->ackprocstarted = 1;
		}
		qunlock(&rpriv->apl);
	}
}

.
154a
	/* keeping track of the ack kproc */
	int	ackprocstarted;
	QLock	apl;
.
## diffname ip/rudp.c 1998/1117
## diff -e /n/emeliedump/1998/0924/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/1117/sys/src/brazil/ip/rudp.c
860a
		relsendack(c, r);	/* tell him we got it already */
.
37c
	Rudptickms	= 50,
.
## diffname ip/rudp.c 1998/1118
## diff -e /n/emeliedump/1998/1117/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/1118/sys/src/brazil/ip/rudp.c
968c
	doipoput(c, f, np, 0, c->ttl);
.
926a
	n = snprint(hup, sizeof(hup), "hangup %I!%d", r->addr, r->port);
	qproduce(c->eq, hup, n);

.
925a
	char hup[ERRLEN];
.
924a
	int n;
.
923c
relhangup(Conv *c, Reliable *r)
.
916c
	doipoput(c, f, bp, 0, c->ttl);
.
853,858d
836,848d
804a
	/* make sure we're not talking to a new remote side */
	if(r->rcvgen != sgen){
		if(seq != 1)
			return -1;

		/* new connection */
		if(r->rcvgen != 0){
			DPRINT("new con r->rcvgen = %lud, sgen = %lud\n", r->rcvgen, sgen);
			relhangup(c, r);
		}
		r->rcvgen = sgen;
	}

.
595a
		} else if(strcmp(f[0], "randdrop") == 0){
			ucb->randdrop = 1;
			return nil;
.
414c
	doipoput(c, f, bp, 0, c->ttl);
.
286a
/*
 *  randomly don't send packets
 */
static void
doipoput(Conv *c, Fs *f, Block *bp, int x, int ttl)
{
	Rudpcb *ucb;

	ucb = (Rudpcb*)c->ptcl;
	if(ucb->randdrop && nrand(10) == 1)
		freeblist(bp);
	else
		ipoput(f, bp, x, ttl);
}

.
275a
		if(r->acksent != r->rcvseq)
			relsendack(c, r);
.
273a
	ucb->randdrop = 0;
.
272d
263a
	/* force out any delayed acks */
	ucb = (Rudpcb*)c->ptcl;
	qlock(ucb);
	for(r = ucb->r; r; r = r->next){
		if(r->acksent != r->rcvseq)
			relsendack(c, r);
	}
	qunlock(ucb);

.
175a
	uchar	randdrop;
.
164,167d
## diffname ip/rudp.c 1998/1124
## diff -e /n/emeliedump/1998/1118/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/1124/sys/src/brazil/ip/rudp.c
830a
	/* if acking an incorrect generation, ignore */
	if(ack && agen != r->sndgen)
		return -1;

.
## diffname ip/rudp.c 1998/1127
## diff -e /n/emeliedump/1998/1124/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/1127/sys/src/brazil/ip/rudp.c
837c
		if(seq != 0 && seq != 1)
.
777c
		while(generation == 0)
.
## diffname ip/rudp.c 1998/1230
## diff -e /n/emeliedump/1998/1127/sys/src/brazil/ip/rudp.c /n/emeliedump/1998/1230/sys/src/brazil/ip/rudp.c
624c
	return rudpunknown;
.
612,622c
	if(n < 1)
		return rudpunknown;

	if(strcmp(f[0], "headers4") == 0){
		ucb->headers = 4;
		return nil;
	} else if(strcmp(f[0], "headers") == 0){
		ucb->headers = 6;
		return nil;
	} else if(strcmp(f[0], "randdrop") == 0){
		x = 10;		/* default is 10% */
		if(n > 1)
			x = atoi(f[1]);
		if(x > 100 || x < 0)
			return "illegal rudp drop rate";
		ucb->randdrop = x;
		return nil;
.
609a
	int x;
.
605a
static char *rudpunknown = "unknown rudp ctl request";

.
304c
	if(ucb->randdrop && nrand(100) < ucb->randdrop)
.
## diffname ip/rudp.c 1999/0302
## diff -e /n/emeliedump/1998/1230/sys/src/brazil/ip/rudp.c /n/emeliedump/1999/0302/sys/src/brazil/ip/rudp.c
529a
	qunlock(rudp);

.
528d
514a
		qunlock(rudp);
.
492a
	qlock(rudp);

.
292c
	qunlock(c);
.
## diffname ip/rudp.c 1999/0320
## diff -e /n/emeliedump/1999/0302/sys/src/brazil/ip/rudp.c /n/emeliedump/1999/0320/sys/src/brazil/ip/rudp.c
312a
	Reliable *r = v;

.
311c
flow(void *v)
.
## diffname ip/rudp.c 1999/0817
## diff -e /n/emeliedump/1999/0320/sys/src/brazil/ip/rudp.c /n/emeliedump/1999/0817/sys/src/brazil/ip/rudp.c
1012c
	doipoput(c, f, np, 0, c->ttl, c->tos);
.
955c
	doipoput(c, f, bp, 0, c->ttl, c->tos);
.
439c
	doipoput(c, f, bp, 0, c->ttl, c->tos);
.
307c
		ipoput(f, bp, x, ttl, tos);
.
299c
doipoput(Conv *c, Fs *f, Block *bp, int x, int ttl, int tos)
.
## diffname ip/rudp.c 2000/0317
## diff -e /n/emeliedump/1999/0817/sys/src/brazil/ip/rudp.c /n/emeliedump/2000/0317/sys/src/9/ip/rudp.c
982a
	if(generation == Hangupgen)
		generation++;
.
957a

.
942c
	if(hangup)
		hnputl(rh->relsgen, Hangupgen);
	else
		hnputl(rh->relsgen, r->sndgen);
.
911c
relsendack(Conv *c, Reliable *r, int hangup)
.
907c
	rv = 0;
out:
	relput(r);
	qunlock(ucb);
	return rv;
.
903c
		goto out;
.
900c
		relsendack(c, r, 0);	/* tell him we got it already */
.
896c
		goto out;
.
853c
			goto out;
.
849a
	/* Look for a hangup */
	if(sgen == Hangupgen) {
		if(agen == r->sndgen)
			relforget(c, addr, port, 0);
		goto out;
	}

.
848c
		goto out;
.
841d
839a
	qlock(ucb);
.
828a
	int rv = -1;
.
814a
void
relforget(Conv *c, uchar *ip, int port, int originator)
{
	Rudpcb *ucb;
	Reliable *r, **l;

	ucb = (Rudpcb*)c->ptcl;

	l = &ucb->r;
	for(r = *l; r; r = *l){
		if(ipcmp(ip, r->addr) == 0 && port == r->port){
			*l = r->next;
			if(originator)
				relsendack(c, r, 1);
			relhangup(c, r);
			relput(r);	/* remove from the list */
			break;
		}
		l = &r->next;
	}
}

.
813a
void
relput(Reliable *r)
{
	if(decref(r) == 0)
		free(r);
}
.
810c
	incref(r);
.
808a
		r->ref = 0;
		incref(r);	/* one reference for being in the list */
.
800a
		if(generation == Hangupgen)
			generation++;
.
767c
				relsendack(c, r, 0);
.
629a
	} else if(strcmp(f[0], "hangup") == 0){
		if(n < 3)
			return "bad syntax";
		parseip(ip, f[1]);
		x = atoi(f[2]);
		qlock(ucb);
		relforget(c, ip, x, 1);
		qunlock(ucb);
		return nil;
.
617a
	uchar ip[IPaddrlen];
.
448c
	relput(r);
	qunlock(ucb);
.
442d
432d
283c
			relsendack(c, r, 0);
.
266c
			relsendack(c, r, 0);
.
181a
void	relput(Reliable *);
void	relforget(Conv *, uchar *, int, int);
.
179c
void	relsendack(Conv *, Reliable *, int);
.
124d
102a
	Ref;

.
41a
#define Hangupgen	0xffffffff	/* used only in hangup messages */

.
39a

.
## diffname ip/rudp.c 2000/0328
## diff -e /n/emeliedump/2000/0317/sys/src/9/ip/rudp.c /n/emeliedump/2000/0328/sys/src/9/ip/rudp.c
453d
451a
	qunlock(&r->lock);
.
446a
	qlock(&r->lock);
.
437a
	qunlock(ucb);
.
128a
	QLock	lock;
.
## diffname ip/rudp.c 2000/0403
## diff -e /n/emeliedump/2000/0328/sys/src/9/ip/rudp.c /n/emeliedump/2000/0403/sys/src/9/ip/rudp.c
968d
891d
867a
 *
 *  called with ucb locked.
.
842a
/*
 *  forget a Reliable state
 */
.
830a

		*l = r;
.
815d
813a

.
455a

.
293c
		relput(r);
.
## diffname ip/rudp.c 2000/0605
## diff -e /n/emeliedump/2000/0403/sys/src/9/ip/rudp.c /n/emeliedump/2000/0605/sys/src/9/ip/rudp.c
834a

.
812a

.
610c
	if(qfull(c->rq)) {
.
557c
	if(bp == nil) {
.
457a
	poperror();
.
456a
	qunlock(&r->lock);
.
455d
447a
	if(waserror()) {
		relput(r);
		qunlock(&r->lock);
		nexterror();
	}

.
298d
190,192c
void	relackq(Reliable *, Block*);
void	relhangup(Conv *, Reliable*);
void	relrexmit(Conv *, Reliable*);
void	relput(Reliable*);
.
184,188c
void	relsendack(Conv*, Reliable*, int);
int	reliput(Conv*, Block*, uchar*, ushort);
Reliable *relstate(Rudpcb*, uchar*, ushort, char*);
void	relput(Reliable*);
void	relforget(Conv *, uchar*, int, int);
.
## diffname ip/rudp.c 2000/1220
## diff -e /n/emeliedump/2000/0605/sys/src/9/ip/rudp.c /n/emeliedump/2000/1220/sys/src/9/ip/rudp.c
299d
## diffname ip/rudp.c 2001/0301
## diff -e /n/emeliedump/2000/1220/sys/src/9/ip/rudp.c /n/emeliedump/2001/0301/sys/src/9/ip/rudp.c
546d
538,539d
536c
		qunlock(rudp);
		netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
.
512,534c
	c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
	if(c == nil){
		/* no converstation found */
.
471c
	Conv *c;
.
268a
	upriv = c->p->priv;
	iphtrem(&upriv->ht, c);

.
267a
	Rudppriv *upriv;
.
251a
	iphtadd(&upriv->ht, c);
.
246a
	upriv = c->p->priv;
.
245a
	Rudppriv *upriv;
.
220a
	iphtadd(&upriv->ht, c);
.
217a
	upriv = c->p->priv;
.
216a
	Rudppriv *upriv;
.
149a
	Ipht	ht;
.
## diffname ip/rudp.c 2001/0306
## diff -e /n/emeliedump/2001/0301/sys/src/9/ip/rudp.c /n/emeliedump/2001/0306/sys/src/9/ip/rudp.c
336c
rudpkick(Conv *c)
.
## diffname ip/rudp.c 2001/0623
## diff -e /n/emeliedump/2001/0306/sys/src/9/ip/rudp.c /n/emeliedump/2001/0623/sys/src/9/ip/rudp.c
598c
				v4tov6(c->laddr, ifc->lifc->local);
.
583c
			v6tov4(bp->rp+IPv4addrlen, ifc->lifc->local);
.
572c
			ipmove(bp->rp+IPaddrlen, ifc->lifc->local);
.
478c
rudpiput(Proto *rudp, Ipifc *ifc, Block *bp)
.
## diffname ip/rudp.c 2001/0918
## diff -e /n/emeliedump/2001/0623/sys/src/9/ip/rudp.c /n/emeliedump/2001/0918/sys/src/9/ip/rudp.c
1035c
	char hup[ERRMAX];
.
200c
	char kpname[KNAMELEN];
.
## diffname ip/rudp.c 2002/0507
## diff -e /n/emeliedump/2001/0918/sys/src/9/ip/rudp.c /n/emeliedump/2002/0507/sys/src/9/ip/rudp.c
989a
	uh->vihl = IP_VER4;
.
404a
	uh->vihl = IP_VER4;
.
324c
		ipoput4(f, bp, x, ttl, tos);
.
## diffname ip/rudp.c 2002/0711
## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/rudp.c /n/emeliedump/2002/0711/sys/src/9/ip/rudp.c
266c
	c->rq = qopen(64*1024, Qmsg, 0, 0);
.
## diffname ip/rudp.c 2002/0712
## diff -e /n/emeliedump/2002/0711/sys/src/9/ip/rudp.c /n/emeliedump/2002/0712/sys/src/9/ip/rudp.c
711d
337a
	Conv *c = x;
.
336c
rudpkick(void *x)
.
267c
	c->wq = qopen(64*1024, Qkick, rudpkick, c);
.
194a
void	rudpkick(void *x);
.
## diffname ip/rudp.c 2003/0308
## diff -e /n/emeliedump/2002/0712/sys/src/9/ip/rudp.c /n/emeliedump/2003/0308/sys/src/9/ip/rudp.c
325c
		ipoput4(f, bp, x, ttl, tos, nil);
.
## diffname ip/rudp.c 2003/0407
## diff -e /n/emeliedump/2003/0308/sys/src/9/ip/rudp.c /n/emeliedump/2003/0407/sys/src/9/ip/rudp.c
769c
	tsleep(&up->sleep, return0, 0, Rudptickms);
.
149d
## diffname ip/rudp.c 2003/0409
## diff -e /n/emeliedump/2003/0407/sys/src/9/ip/rudp.c /n/emeliedump/2003/0409/sys/src/9/ip/rudp.c
765d
762d
## diffname ip/rudp.c 2003/0419
## diff -e /n/emeliedump/2003/0409/sys/src/9/ip/rudp.c /n/emeliedump/2003/0419/sys/src/9/ip/rudp.c
631,632c
	if(strcmp(f[0], "headers++4") == 0){
		ucb->headers = 7;
.
578,588d
570,576c
		p = bp->rp;
		ipmove(p, raddr); p += IPaddrlen;
		ipmove(p, ipforme(f, laddr)==Runi ? laddr : ifc->lifc->local); p += IPaddrlen;
		hnputs(p, rport); p += 2;
		hnputs(p, lport);
.
566a
	case 7:
		/* pass the src address */
		bp = padblock(bp, UDP_USEAD7);
		p = bp->rp;
		ipmove(p, raddr); p += IPaddrlen;
		ipmove(p, laddr); p += IPaddrlen;
		ipmove(p, ifc->lifc->local); p += IPaddrlen;
		hnputs(p, rport); p += 2;
		hnputs(p, lport);
		break;
.
489a
	uchar *p;
.
418a
	case 7:
.
417d
380,383c
		ipmove(raddr, bp->rp);
		bp->rp += IPaddrlen;
		ipmove(laddr, bp->rp);
		bp->rp += IPaddrlen;
		/* pick interface closest to dest */
.
376,377c
	case 6:
		/* get user specified addresses */
		bp = pullupblock(bp, UDP_USEAD6);
.
373,374c
		bp->rp += 2+2;			/* Ignore local port */
.
371a
		bp->rp += IPaddrlen;		/* Ignore ifc address */
.
362c
		bp = pullupblock(bp, UDP_USEAD7);
.
360c
	case 7:
.
32a
	UDP_USEAD7	= 52,
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.