## diffname port/devnonet.c 1990/1210
## diff -e /dev/null /n/bootesdump/1990/1210/sys/src/9/port/devnonet.c
0a
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "errno.h"
#define DPRINT if(0)
#define NOW (MACHP(0)->ticks*MS2HZ)
static Noifc *noifc;
enum {
/*
* tuning parameters
*/
MSrexmit = 500, /* retranmission interval in ms */
MSack = 50, /* ms to sit on an ack */
/*
* relative or immutable
*/
Nsubdir = 5, /* entries in the nonet directory */
Nmask = Nnomsg - 1, /* mask for log(Nnomsg) bits */
};
/* predeclared */
static void hangup(Noconv*);
static Block* mkhdr(Noconv*, int);
static void listen(Chan*, Noifc*);
static void announce(Chan*, char*);
static void connect(Chan*, char*);
static void rcvack(Noconv*, int);
static void sendctlmsg(Noconv*, int, int);
static void sendmsg(Noconv*, Nomsg*);
static void startconv(Noconv*, int, char*, int);
static void queueack(Noconv*, int);
static void nonetiput(Queue*, Block*);
static void nonetoput(Queue*, Block*);
static void nonetstclose(Queue*);
static void nonetstopen(Queue*, Stream*);
extern Qinfo noetherinfo;
extern Qinfo nonetinfo;
/*
* nonet directory and subdirectory
*/
enum {
/*
* per conversation
*/
Naddrqid,
Nlistenqid,
Nraddrqid,
Nruserqid,
Nstatsqid,
Nchanqid,
/*
* per noifc
*/
Ncloneqid,
};
Dirtab *nonetdir;
Dirtab nosubdir[]={
"addr", {Naddrqid}, 0, 0600,
"listen", {Nlistenqid}, 0, 0600,
"raddr", {Nraddrqid}, 0, 0600,
"ruser", {Nruserqid}, 0, 0600,
"stats", {Nstatsqid}, 0, 0600,
};
/*
* Nonet conversation states (for Noconv.state)
*/
enum {
Cclosed,
Copen,
Cannounced,
Cconnected,
Cconnecting,
Chungup,
Cclosing,
};
/*
* nonet file system. most of the calls use dev.c to access the nonet
* directory and stream.c to access the nonet devices.
* create the nonet directory. the files are `clone' and stream
* directories '1' to '32' (or whatever conf.noconv is in decimal)
*/
void
nonetreset(void)
{
int i;
/*
* allocate the interfaces
*/
noifc = (Noifc *)ialloc(sizeof(Noifc) * conf.nnoifc, 0);
for(i = 0; i < conf.nnoconv; i++)
noifc[i].conv = (Noconv *)ialloc(sizeof(Noconv) * conf.nnoconv, 0);
/*
* create the directory.
*/
nonetdir = (Dirtab *)ialloc(sizeof(Dirtab) * (conf.nnoconv+1), 0);
/*
* the circuits
*/
for(i = 0; i < conf.nnoconv; i++) {
sprint(nonetdir[i].name, "%d", i);
nonetdir[i].qid.path = CHDIR|STREAMQID(i, Nchanqid);
nonetdir[i].qid.vers = 0;
nonetdir[i].length = 0;
nonetdir[i].perm = 0600;
}
/*
* the clone device
*/
strcpy(nonetdir[i].name, "clone");
nonetdir[i].qid.path = Ncloneqid;
nonetdir[i].qid.vers = 0;
nonetdir[i].length = 0;
nonetdir[i].perm = 0600;
}
void
nonetinit(void)
{
}
/*
* find an noifc and increment its count
*/
Chan*
nonetattach(char *spec)
{
Noifc *ifc;
Chan *c;
/*
* find an noifc with the same name
*/
if(*spec == 0)
spec = "nonet";
for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){
lock(ifc);
if(strcmp(spec, ifc->name)==0 && ifc->wq) {
ifc->ref++;
unlock(ifc);
break;
}
unlock(ifc);
}
if(ifc == &noifc[conf.nnoifc])
error(Enoifc);
c = devattach('n', spec);
c->dev = ifc - noifc;
return c;
}
/*
* up the reference count to the noifc
*/
Chan*
nonetclone(Chan *c, Chan *nc)
{
Noifc *ifc;
c = devclone(c, nc);
ifc = &noifc[c->dev];
lock(ifc);
ifc->ref++;
unlock(ifc);
return c;
}
int
nonetwalk(Chan *c, char *name)
{
if(c->qid.path == CHDIR)
return devwalk(c, name, nonetdir, conf.nnoconv+1, devgen);
else
return devwalk(c, name, nosubdir, Nsubdir, streamgen);
}
void
nonetstat(Chan *c, char *dp)
{
if(c->qid.path == CHDIR)
devstat(c, dp, nonetdir, conf.nnoconv+1, devgen);
else if(c->qid.path == Ncloneqid)
devstat(c, dp, nonetdir, 1, devgen);
else
devstat(c, dp, nosubdir, Nsubdir, streamgen);
}
/*
* opening a nonet device allocates a Noconv. Opening the `clone'
* device is a ``macro'' for finding a free Noconv and opening
* it's ctl file.
*/
Noconv *
nonetopenclone(Chan *c, Noifc *ifc)
{
Noconv *cp;
Noconv *ep;
ep = &ifc->conv[conf.nnoconv];
for(cp = &ifc->conv[0]; cp < ep; cp++){
if(cp->state == Cclosed && canqlock(cp)){
if(cp->state != Cclosed){
qunlock(cp);
continue;
}
c->qid.path = CHDIR|STREAMQID(cp-ifc->conv, Nchanqid);
devwalk(c, "ctl", 0, 0, streamgen);
streamopen(c, &nonetinfo);
qunlock(cp);
break;
}
}
if(cp == ep)
error(Enodev);;
return cp;
}
Chan*
nonetopen(Chan *c, int omode)
{
Stream *s;
Noconv *cp;
Noifc *ifc;
int line;
if(c->qid.path & CHDIR){
/*
* directories are read only
*/
if(omode != OREAD)
error(Ebadarg);
} else switch(STREAMTYPE(c->qid.path)){
case Ncloneqid:
/*
* get an unused device and open it's control file
*/
ifc = &noifc[c->dev];
cp = nonetopenclone(c, ifc);
break;
case Nlistenqid:
/*
* listen for a call and open the control file for the
* channel on which the call arrived.
*/
line = STREAMID(c->qid.path);
ifc = &noifc[c->dev];
if(ifc->conv[line].state != Cannounced)
error(Enoannounce);
listen(c, ifc);
break;
case Nraddrqid:
/*
* read only files
*/
if(omode != OREAD)
error(Ebadarg);
break;
default:
/*
* open whatever c points to
*/
streamopen(c, &nonetinfo);
break;
}
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
return c;
}
void
nonetcreate(Chan *c, char *name, int omode, ulong perm)
{
error(Eperm);
}
void
nonetclose(Chan *c)
{
Noifc *ifc;
/*
* real closing happens in nonetstclose
*/
if(c->qid.path != CHDIR)
streamclose(c);
/*
* let go of the multiplexor
*/
nonetfreeifc(&noifc[c->dev]);
}
long
nonetread(Chan *c, void *a, long n)
{
int t;
Noconv *cp;
char stats[256];
/*
* pass data/ctl reads onto the stream code
*/
t = STREAMTYPE(c->qid.path);
if(t >= Slowqid)
return streamread(c, a, n);
if(c->qid.path == CHDIR)
return devdirread(c, a, n, nonetdir, conf.nnoconv+1, devgen);
if(c->qid.path & CHDIR)
return devdirread(c, a, n, nosubdir, Nsubdir, streamgen);
cp = &noifc[c->dev].conv[STREAMID(c->qid.path)];
switch(t){
case Nraddrqid:
return stringread(c, a, n, cp->raddr);
case Naddrqid:
return stringread(c, a, n, cp->addr);
case Nruserqid:
return stringread(c, a, n, cp->ruser);
case Nstatsqid:
sprint(stats, "sent: %d\nrcved: %d\nrexmit: %d\nbad: %d\n",
cp->sent, cp->rcvd, cp->rexmit, cp->bad);
return stringread(c, a, n, stats);
}
error(Eperm);
}
long
nonetwrite(Chan *c, void *a, long n)
{
int t;
int m;
char buf[256];
char *field[5];
t = STREAMTYPE(c->qid.path);
/*
* get data dispatched as quickly as possible
*/
if(t == Sdataqid)
return streamwrite(c, a, n, 0);
/*
* easier to do here than in nonetoput
*/
if(t == Sctlqid){
strncpy(buf, a, sizeof buf);
m = getfields(buf, field, 5, ' ');
if(strcmp(field[0], "connect")==0){
if(m < 2)
error(Ebadarg);
connect(c, field[1]);
} else if(strcmp(field[0], "announce")==0){
announce(c, field[1]);
} else if(strcmp(field[0], "accept")==0){
/* ignore */;
} else if(strcmp(field[0], "reject")==0){
/* ignore */;
} else
return streamwrite(c, a, n, 0);
return n;
}
error(Eperm);
}
void
nonetremove(Chan *c)
{
error(Eperm);
}
void
nonetwstat(Chan *c, char *dp)
{
error(Eperm);
}
/*
* the device stream module definition
*/
Qinfo nonetinfo =
{
nonetiput,
nonetoput,
nonetstopen,
nonetstclose,
"nonet"
};
/*
* store the device end of the stream so that the multiplexor can
* send blocks upstream.
*/
static void
nonetstopen(Queue *q, Stream *s)
{
Noifc *ifc;
Noconv *cp;
ifc = &noifc[s->dev];
cp = &ifc->conv[s->id];
cp->s = s;
cp->ifc = ifc;
cp->rq = RD(q);
cp->state = Copen;
RD(q)->ptr = WR(q)->ptr = (void *)cp;
}
/*
* wait until a hangup is received.
* then send a hangup message (until one is received).
*/
static int
ishungup(void *a)
{
Noconv *cp;
cp = (Noconv *)a;
return cp->state == Chungup;
}
static void
nonetstclose(Queue *q)
{
Noconv *cp;
Nomsg *mp;
int i;
cp = (Noconv *)q->ptr;
if(waserror()){
cp->rcvcircuit = -1;
cp->state = Cclosed;
nexterror();
}
/*
* send hangup messages to the other side
* until it hangs up or we get tired.
*/
if(cp->state >= Cconnected){
sendctlmsg(cp, NO_HANGUP, 1);
for(i=0; i<10 && !ishungup(cp); i++){
sendctlmsg(cp, NO_HANGUP, 1);
tsleep(&cp->r, ishungup, cp, MSrexmit);
}
}
cp->rcvcircuit = -1;
cp->state = Cclosed;
poperror();
}
/*
* send all messages up stream. this should only be control messages
*/
static void
nonetiput(Queue *q, Block *bp)
{
Noconv *cp;
if(bp->type == M_HANGUP){
cp = (Noconv *)q->ptr;
cp->state = Chungup;
}
PUTNEXT(q, bp);
}
/*
* queue a block
*/
static int
windowopen(void *a)
{
Noconv *cp;
cp = (Noconv *)a;
return cp->out[cp->next].inuse == 0;
}
static int
acked(void *a)
{
Nomsg *mp;
mp = (Nomsg *)a;
return mp->acked;
}
static void
nonetoput(Queue *q, Block *bp)
{
Noconv *cp;
int next;
Nomsg *mp;
cp = (Noconv *)(q->ptr);
/*
* do all control functions
*/
if(bp->type != M_DATA){
freeb(bp);
error(Ebadctl);
}
/*
* collect till we see a delim
*/
qlock(&cp->mlock);
if(!putb(q, bp)){
qunlock(&cp->mlock);
return;
}
mp = 0;
if(waserror()){
if(mp){
if(mp->first){
freeb(mp->first);
mp->first = 0;
}
mp->inuse = 0;
} else
qunlock(&cp->mlock);
}
/*
* block till we get a buffer
*/
while(cp->out[cp->next].inuse)
sleep(&cp->r, windowopen, cp);
mp = &cp->out[cp->next];
mp->inuse = 1;
cp->next = (cp->next+1)%Nnomsg;
/*
* stick the message in a Nomsg structure
*/
mp->time = NOW + MSrexmit;
mp->first = q->first;
mp->last = q->last;
mp->len = q->len;
mp->mid ^= Nnomsg;
mp->acked = 0;
/*
* init the queue for new messages
*/
q->len = 0;
q->first = q->last = 0;
cp->sent++;
qunlock(&cp->mlock);
/*
* wait for acknowledgement
*/
while(!mp->acked && cp->state!=Chungup){
sendmsg(cp, mp);
tsleep(&mp->r, acked, mp, MSrexmit);
}
/*
* free buffer
*/
freeb(mp->first);
mp->first = 0;
mp->inuse = 0;
wakeup(&cp->r);
poperror();
}
/*
* start a new conversation. start an ack/retransmit process if
* none already exists for this circuit.
*/
void
startconv(Noconv *cp, int circuit, char *raddr, int state)
{
int i;
char name[32];
Noifc *ifc;
ifc = cp->ifc;
/*
* allocate the prototype header
*/
cp->media = allocb(ifc->hsize + NO_HDRSIZE);
cp->media->wptr += ifc->hsize + NO_HDRSIZE;
cp->hdr = (Nohdr *)(cp->media->rptr + ifc->hsize);
/*
* fill in the circuit number
*/
cp->hdr->flag = NO_NEWCALL|NO_ACKME;
cp->hdr->circuit[2] = circuit>>16;
cp->hdr->circuit[1] = circuit>>8;
cp->hdr->circuit[0] = circuit;
/*
* set the state variables
*/
cp->state = state;
for(i = 1; i < Nnomsg; i++){
cp->in[i].mid = i;
cp->in[i].acked = 0;
cp->in[i].rem = 0;
cp->out[i].mid = i | Nnomsg;
cp->out[i].acked = 1;
cp->out[i].rem = 0;
cp->out[i].inuse = 0;
}
cp->in[0].mid = Nnomsg;
cp->in[0].acked = 0;
cp->in[0].rem = 0;
cp->out[0].mid = 0;
cp->out[0].acked = 1;
cp->out[0].rem = 0;
cp->first = cp->next = 1;
cp->rexmit = cp->bad = cp->sent = cp->rcvd = cp->lastacked = 0;
/*
* used for demultiplexing
*/
cp->rcvcircuit = circuit ^ 1;
/*
* media dependent header
*/
(*ifc->connect)(cp, raddr);
/*
* status files
*/
strncpy(cp->raddr, raddr, sizeof(cp->raddr));
strcpy(cp->ruser, "none");
}
/*
* announce willingness to take calls
*/
static void
announce(Chan *c, char *addr)
{
Noconv *cp;
cp = (Noconv *)(c->stream->devq->ptr);
if(cp->state != Copen)
error(Einuse);
cp->state = Cannounced;
}
/*
* connect to the destination whose name is pointed to by bp->rptr.
*
* a service is separated from the destination system by a '!'
*/
static void
connect(Chan *c, char *addr)
{
Noifc *ifc;
Noconv *cp;
char *service;
char buf[2*NAMELEN+2];
cp = (Noconv *)(c->stream->devq->ptr);
if(cp->state != Copen)
error(Einuse);
ifc = cp->ifc;
service = strchr(addr, '!');
if(service){
*service++ = 0;
if(strchr(service, ' '))
error(Ebadctl);
if(strlen(service) > NAMELEN)
error(Ebadctl);
}
startconv(cp, 2*(cp - ifc->conv), addr, Cconnecting);
if(service){
/*
* send service name and user name
*/
cp->hdr->flag |= NO_SERVICE;
sprint(buf, "%s %s", service, u->p->pgrp->user);
c->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid);
streamwrite(c, buf, strlen(buf), 1);
c->qid.path = STREAMQID(STREAMID(c->qid.path), Sctlqid);
}
}
/*
* listen for a call. There can be many listeners, but only one can sleep
* on the circular queue at a time. ifc->listenl lets only one at a time into
* the sleep.
*/
static int
iscall(void *a)
{
Noifc *ifc;
ifc = (Noifc *)a;
return ifc->rptr != ifc->wptr;
}
static void
listen(Chan *c, Noifc *ifc)
{
Noconv *cp, *ep;
Nocall call;
int f;
char buf[2*NAMELEN+4];
char *user;
long n;
call.msg = 0;
if(waserror()){
if(call.msg)
freeb(call.msg);
qunlock(&ifc->listenl);
nexterror();
}
for(;;){
/*
* one listener at a time
*/
qlock(&ifc->listenl);
/*
* wait for a call
*/
sleep(&ifc->listenr, iscall, ifc);
call = ifc->call[ifc->rptr];
ifc->rptr = (ifc->rptr+1) % Nnocalls;
qunlock(&ifc->listenl);
/*
* make sure we aren't already using this circuit
*/
ep = &ifc->conv[conf.nnoconv];
for(cp = &ifc->conv[0]; cp < ep; cp++){
if(cp->state>Cannounced && call.circuit==cp->rcvcircuit
&& strcmp(call.raddr, cp->raddr)==0)
break;
}
if(cp != ep){
freeb(call.msg);
call.msg = 0;
continue;
}
/*
* get a free channel
*/
cp = nonetopenclone(c, ifc);
c->qid.path = STREAMQID(cp - ifc->conv, Sctlqid);
/*
* start the protocol and
* stuff the connect message into it
*/
f = ((Nohdr *)(call.msg->rptr))->flag;
startconv(cp, call.circuit, call.raddr, Cconnecting);
print("rcving %d byte message\n", call.msg->wptr - call.msg->rptr);
nonetrcvmsg(cp, call.msg);
call.msg = 0;
/*
* if a service and remote user were specified,
* grab them
*/
if(f & NO_SERVICE){
print("reading service\n");
c->qid.path = STREAMQID(cp - ifc->conv, Sdataqid);
n = streamread(c, buf, sizeof(buf));
c->qid.path = STREAMQID(cp - ifc->conv, Sctlqid);
print("read %d bytes\n", n);
if(n <= 0)
error(Ebadctl);
buf[n] = 0;
print("read %s\n", buf);
user = strchr(buf, ' ');
if(user){
*user++ = 0;
strncpy(cp->ruser, user, NAMELEN);
} else
strcpy(cp->ruser, "none");
strncpy(cp->addr, buf, NAMELEN);
}
break;
}
poperror();
}
/*
* send a hangup signal up the stream to get all line disciplines
* to cease and desist
*/
static void
hangup(Noconv *cp)
{
Block *bp;
Queue *q;
cp->state = Chungup;
bp = allocb(0);
bp->type = M_HANGUP;
q = cp->rq;
PUTNEXT(q, bp);
wakeup(&cp->r);
}
/*
* process a message acknowledgement. if the message
* has any xmit buffers queued, free them.
*/
static void
rcvack(Noconv *cp, int mid)
{
Nomsg *mp;
Block *bp;
int i;
mp = &cp->out[mid & Nmask];
/*
* if already acked, ignore
*/
if(mp->acked || mp->mid != mid)
return;
/*
* wakeup the sender
*/
mp->acked = 1;
wakeup(&mp->r);
cp->lastacked = mid;
}
/*
* queue an acknowledgement to be sent. ignore it if we already have Nnomsg
* acknowledgements queued.
*/
static void
queueack(Noconv *cp, int mid)
{
int next;
ulong now;
now = NOW;
next = (cp->anext + 1)&Nmask;
if(next != cp->afirst){
cp->ack[cp->anext] = mid;
cp->anext = next;
}
}
/*
* make a packet header
*/
Block *
mkhdr(Noconv *cp, int rem)
{
Block *bp;
Nohdr *hp;
bp = allocb(cp->ifc->hsize + NO_HDRSIZE + cp->ifc->mintu);
memcpy(bp->wptr, cp->media->rptr, cp->ifc->hsize + NO_HDRSIZE);
bp->wptr += cp->ifc->hsize + NO_HDRSIZE;
hp = (Nohdr *)(bp->rptr + cp->ifc->hsize);
hp->remain[1] = rem>>8;
hp->remain[0] = rem;
hp->sum[0] = hp->sum[1] = 0;
return bp;
}
/*
* transmit a message. this involves breaking a possibly multi-block message into
* a train of packets on the media.
*
* called by nonetoput(). the qlock(mp) synchronizes these two
* processes.
*/
static void
sendmsg(Noconv *cp, Nomsg *mp)
{
Noifc *ifc;
Queue *wq;
int msgrem;
int pktrem;
int n;
Block *bp, *pkt, *last;
uchar *rptr;
ifc = cp->ifc;
if(ifc == 0)
return;
wq = ifc->wq->next;
/*
* one transmitter at a time
*/
qlock(&cp->xlock);
if(waserror()){
qunlock(&cp->xlock);
return;
}
/*
* get the next acknowledge to use if the next queue up
* is not full.
*/
if(cp->afirst != cp->anext && cp->rq->next->len < 16*1024){
cp->hdr->ack = cp->ack[cp->afirst];
cp->afirst = (cp->afirst+1)&Nmask;
}
cp->hdr->mid = mp->mid;
if(ifc->mintu > mp->len) {
/*
* short message:
* copy the whole message into the header block
*/
last = pkt = mkhdr(cp, mp->len);
for(bp = mp->first; bp; bp = bp->next){
memcpy(pkt->wptr, bp->rptr, n = BLEN(bp));
pkt->wptr += n;
}
memset(pkt->wptr, 0, n = ifc->mintu - mp->len);
pkt->wptr += n;
} else {
/*
* long message:
* break up the message into noifc packets and send them.
* once around this loop for each non-header block generated.
*/
msgrem = mp->len;
pktrem = msgrem > ifc->maxtu ? ifc->maxtu : msgrem;
bp = mp->first;
if(bp)
rptr = bp->rptr;
last = pkt = mkhdr(cp, msgrem);
while(bp){
/*
* if pkt full, send and create new header block
*/
if(pktrem == 0){
nonetcksum(pkt, ifc->hsize);
last->flags |= S_DELIM;
(*wq->put)(wq, pkt);
last = pkt = mkhdr(cp, -msgrem);
pktrem = msgrem > ifc->maxtu ? ifc->maxtu : msgrem;
}
n = bp->wptr - rptr;
if(n > pktrem)
n = pktrem;
last = last->next = allocb(0);
last->rptr = rptr;
last->wptr = rptr = rptr + n;
msgrem -= n;
pktrem -= n;
if(rptr >= bp->wptr){
bp = bp->next;
if(bp)
rptr = bp->rptr;
}
}
}
nonetcksum(pkt, ifc->hsize);
last->flags |= S_DELIM;
(*wq->put)(wq, pkt);
mp->time = NOW + MSrexmit;
qunlock(&cp->xlock);
poperror();
}
/*
* send a control message (hangup or acknowledgement).
*/
static void
sendctlmsg(Noconv *cp, int flag, int new)
{
cp->ctl.len = 0;
cp->ctl.first = 0;
cp->ctl.acked = 0;
if(new)
cp->ctl.mid = Nnomsg^cp->out[cp->next].mid;
else
cp->ctl.mid = cp->lastacked;
cp->hdr->flag |= flag;
sendmsg(cp, &cp->ctl);
}
/*
* receive a message (called by the multiplexor; noetheriput, nofddiiput, ...)
*/
void
nonetrcvmsg(Noconv *cp, Block *bp)
{
Block *nbp;
Nohdr *h;
short r;
int c;
Nomsg *mp;
int f;
Queue *q;
q = cp->rq;
/*
* grab the packet header, push the pointer past the nonet header
*/
h = (Nohdr *)bp->rptr;
bp->rptr += NO_HDRSIZE;
mp = &cp->in[h->mid & Nmask];
r = (h->remain[1]<<8) | h->remain[0];
f = h->flag;
/*
* if a new call request comes in on a connected channel, hang up the call
*/
if(h->mid==0 && (f & NO_NEWCALL) && cp->state==Cconnected){
freeb(bp);
hangup(cp);
return;
}
/*
* ignore old messages and process the acknowledgement
*/
if(h->mid != mp->mid){
DPRINT("old msg %d instead of %d\n", h->mid, mp->mid);
if(r == 0){
rcvack(cp, h->ack);
if(f & NO_HANGUP)
hangup(cp);
} else {
if(r>0)
queueack(cp, h->mid);
cp->bad++;
}
freeb(bp);
return;
}
if(r>=0){
/*
* start of message packet
*/
if(mp->first){
DPRINT("mp->mid==%d mp->rem==%d buf r==%d\n", mp->mid, mp->rem, r);
cp->bad++;
freeb(bp);
return;
}
mp->rem = r;
} else {
/*
* a continuation
*/
if(-r != mp->rem) {
DPRINT("mp->mid==%d mp->rem==%d buf r==%d\n", mp->mid, mp->rem, r);
cp->bad++;
freeb(bp);
return;
}
}
/*
* take care of packets that were padded up
*/
mp->rem -= BLEN(bp);
if(mp->rem < 0){
if(-mp->rem <= BLEN(bp)){
bp->wptr += mp->rem;
mp->rem = 0;
} else
panic("nonetrcvmsg: short packet");
}
putb(mp, bp);
/*
* if the last chunk - pass it up the stream and wake any
* waiting process.
*
* if not, strip off the delimiter.
*/
if(mp->rem == 0){
rcvack(cp, h->ack);
if(f & NO_ACKME)
queueack(cp, h->mid);
mp->last->flags |= S_DELIM;
PUTNEXT(q, mp->first);
mp->first = mp->last = 0;
mp->len = 0;
cp->rcvd++;
/*
* cycle bufffer to next expected mid
*/
mp->mid ^= Nnomsg;
/*
* stop xmitting the NO_NEWCALL flag
*/
if(cp->state==Cconnecting && !(f & NO_NEWCALL))
cp->state = Cconnected;
} else
mp->last->flags &= ~S_DELIM;
}
/*
* noifc
*/
/*
* Create an ifc.
*/
Noifc *
nonetnewifc(Queue *q, Stream *s, int maxtu, int mintu, int hsize,
void (*connect)(Noconv *, char *))
{
Noifc *ifc;
int i;
for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){
if(ifc->ref == 0){
lock(ifc);
if(ifc->ref) {
/* someone was faster than us */
unlock(ifc);
continue;
}
RD(q)->ptr = WR(q)->ptr = (void *)ifc;
for(i = 0; i < conf.nnoconv; i++)
ifc->conv[i].rcvcircuit = -1;
ifc->maxtu = maxtu - hsize - NO_HDRSIZE;
ifc->mintu = mintu - hsize - NO_HDRSIZE;
ifc->hsize = hsize;
ifc->connect = connect;
ifc->name[0] = 0;
ifc->wq = WR(q);
ifc->ref = 1;
unlock(ifc);
return ifc;
}
}
error(Enoifc);
}
/*
* Free an noifc.
*/
void
nonetfreeifc(Noifc *ifc)
{
lock(ifc);
ifc->ref--;
if(ifc->ref == 0)
ifc->wq = 0;
unlock(ifc);
}
/*
* calculate the checksum of a list of blocks. ignore the first `offset' bytes.
*/
int
nonetcksum(Block *bp, int offset)
{
Block *nbp = bp;
uchar *ep, *p;
int n;
ulong s;
Nohdr *hp;
s = 0;
p = bp->rptr + offset;
n = bp->wptr - p;
hp = (Nohdr *)p;
hp->sum[0] = hp->sum[1] = 0;
for(;;){
ep = p+(n&~0x7);
while(p < ep) {
s = s + s + p[0];
s = s + s + p[1];
s = s + s + p[2];
s = s + s + p[3];
s = s + s + p[4];
s = s + s + p[5];
s = s + s + p[6];
s = s + s + p[7];
s = (s&0xffff) + (s>>16);
p += 8;
}
ep = p+(n&0x7);
while(p < ep) {
s = s + s + *p;
p++;
}
s = (s&0xffff) + (s>>16);
bp = bp->next;
if(bp == 0)
break;
p = bp->rptr;
n = BLEN(bp);
}
s = (s&0xffff) + (s>>16);
hp->sum[1] = s>>8;
hp->sum[0] = s;
return s & 0xffff;
}
.
## diffname port/devnonet.c 1990/1214
## diff -e /n/bootesdump/1990/1210/sys/src/9/port/devnonet.c /n/bootesdump/1990/1214/sys/src/9/port/devnonet.c
1192d
961a
SET(rptr);
.
871d
869d
255c
nonetopenclone(c, ifc);
.
239d
## diffname port/devnonet.c 1990/1229
## diff -e /n/bootesdump/1990/1214/sys/src/9/port/devnonet.c /n/bootesdump/1990/1229/sys/src/9/port/devnonet.c
1229a
}
nonettoggle()
{
pnonet ^= 1;
.
1042a
DPRINT("new call on connected channel\n");
.
105c
for(i = 0; i < conf.nnoifc; i++)
.
18c
MSrexmit = 500, /* retranmission interval in ms */
.
12a
int pnonet;
.
9c
#define DPRINT if(pnonet)print
.
## diffname port/devnonet.c 1990/1231
## diff -e /n/bootesdump/1990/1229/sys/src/9/port/devnonet.c /n/bootesdump/1990/1231/sys/src/9/port/devnonet.c
1061c
sendack(cp, h->mid);
.
1015a
* send an acknowledgement
*/
static void
sendack(Noconv *cp, int ack)
{
cp->ackmsg.len = 0;
cp->ackmsg.first = 0;
cp->ackmsg.acked = ack;
cp->ackmsg.mid = cp->lastacked;
sendmsg(cp, &cp->ctl);
}
/*
.
783a
print("call from %d %s\n", call.circuit, call.raddr);
.
707a
print("request sent\n");
.
706a
print("sending request\n");
.
39a
static void sendack(Noconv*, int);
.
## diffname port/devnonet.c 1991/0102
## diff -e /n/bootesdump/1990/1231/sys/src/9/port/devnonet.c /n/bootesdump/1991/0102/sys/src/9/port/devnonet.c
1077,1078c
if(r>0){
queueack(cp, h->mid);
sendctlmsg(cp, 0, 0);
}
.
1020,1032d
1016c
sendmsg(cp, &ctl);
.
1014c
ctl.mid = cp->lastacked;
.
1012c
ctl.mid = Nnomsg^cp->out[cp->next].mid;
.
1008,1010c
Nomsg ctl;
ctl.len = 0;
ctl.first = 0;
ctl.acked = 0;
.
924c
* one transmitter at a time for this connection
.
40d
## diffname port/devnonet.c 1991/0108
## diff -e /n/bootesdump/1991/0102/sys/src/9/port/devnonet.c /n/bootesdump/1991/0108/sys/src/9/port/devnonet.c
1244a
.
1240a
/*
* send acknowledges that need to be sent. this happens at 1/2
* the retransmission interval.
*/
static void
nonetkproc(void *arg)
{
Noifc *ifc;
Noconv *cp, *ep;
cp = 0;
ifc = 0;
if(waserror()){
if(ifc)
unlock(ifc);
if(cp)
qunlock(cp);
}
loop:
for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){
if(ifc->wq==0 || !canlock(ifc))
continue;
ep = ifc->conv + conf.nnoconv;
for(cp = ifc->conv; cp < ep; cp++){
if(cp->state==Cclosed || !canqlock(cp))
continue;
if(cp->afirst != cp->anext){
DPRINT("sending ack %d\n", cp->ack[cp->afirst]);
sendctlmsg(cp, 0, 0);
}
qunlock(cp);
}
unlock(ifc);
}
tsleep(&nonetkr, return0, 0, MSrexmit/2);
goto loop;
}
.
1067d
1065a
rcvack(cp, h->ack);
.
1059c
DPRINT("old msg %d instead of %d r==%d\n", h->mid, mp->mid, r);
.
805d
801d
797c
DPRINT("reading service\n");
.
788c
DPRINT("rcving %d byte message\n", call.msg->wptr - call.msg->rptr);
.
786c
DPRINT("call from %d %s\n", call.circuit, call.raddr);
.
709c
DPRINT("request sent\n");
.
707c
DPRINT("sending request\n");
.
578a
if(retries++ > 100)
errors("to many nonet rexmits");
.
575a
retries = 0;
.
513a
int retries;
.
470a
qunlock(cp);
.
468a
qlock(cp);
.
242a
if(!kstarted){
kproc("nonetack", nonetkproc, 0);
kstarted = 1;
}
.
166a
.
91a
* nonet kproc
*/
static int kstarted;
static Rendez nonetkr;
/*
.
40c
static void nonetkproc(void*);
.
19c
MSrexmit = 250, /* retranmission interval in ms */
.
## diffname port/devnonet.c 1991/0109
## diff -e /n/bootesdump/1991/0108/sys/src/9/port/devnonet.c /n/bootesdump/1991/0109/sys/src/9/port/devnonet.c
606d
597a
poperror();
.
596c
errors("too many nonet rexmits");
.
557,558c
}
qunlock(&cp->mlock);
nexterror();
.
## diffname port/devnonet.c 1991/0112
## diff -e /n/bootesdump/1991/0109/sys/src/9/port/devnonet.c /n/bootesdump/1991/0112/sys/src/9/port/devnonet.c
784c
if(cp->state>Cannounced && (call.circuit^1)==cp->rcvcircuit
.
## diffname port/devnonet.c 1991/01151
## diff -e /n/bootesdump/1991/0112/sys/src/9/port/devnonet.c /n/bootesdump/1991/01151/sys/src/9/port/devnonet.c
1297c
void
nonettoggle(void)
.
1284a
if(cp->state == Cclosed){
qunlock(cp);
continue;
}
/*
* resend the first message
*/
if(cp->first!=cp->next && cp->out[cp->first].time>=NOW){
if(cp->rexmit++ > 100){
print("hanging up\n");
hangup(cp);
} else
sendmsg(cp, &(cp->out[cp->first]));
}
/*
* resend an acknowledge
*/
.
1280a
/*
* loop through all active conversations
*/
.
1277a
/*
* loop through all active interfaces
*/
.
1108c
DPRINT("mp->mid==%d mp->rem==%d r==%d\n", mp->mid, mp->rem, r);
.
1097,1100c
DPRINT("mp->mid==%d mp->rem==%d r==%d\n", mp->mid, mp->rem, r);
freeb(mp->first);
mp->first = mp->last = 0;
mp->len = 0;
.
878a
freeb(mp->first);
mp->first = 0;
mp->inuse = 0;
/*
* advance first if this is the first
*/
if((mid&Nmask) == cp->first){
while(cp->first != cp->next){
if(cp->out[cp->first].acked == 0)
break;
cp->first = (cp->first+1) % Nnomsg;
}
}
.
877d
875a
cp->rexmit = 0;
.
874c
* free it
.
600,607d
592,598c
sendmsg(cp, mp);
qunlock(&cp->mlock);
.
590c
* send the message, the kproc will retry
.
587d
556a
mp->acked = 0;
if(((cp->first+1)%Nnomsg) == cp->next)
cp->first = cp->next;
.
551a
q->len = 0;
q->first = q->last = 0;
.
520c
return mp->inuse;
.
## diffname port/devnonet.c 1991/0118
## diff -e /n/bootesdump/1991/01151/sys/src/9/port/devnonet.c /n/bootesdump/1991/0118/sys/src/9/port/devnonet.c
1309,1310c
} else {
mp = &(cp->out[cp->first]);
sendmsg(cp, mp);
}
.
1305,1306c
if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){
if(cp->rexmit++ > 60){
.
1271a
Nomsg *mp;
.
1073c
if(cp->state != Csuperceded){
cp->state = Csuperceded;
hangup(cp);
}
.
1070c
if(h->mid==0 && (f & NO_NEWCALL)
&& (cp->state==Cconnected || cp->state==Csuperceded)){
.
1018d
1016a
if(cp->rexmit > 10)
mp->time = NOW + 10*MSrexmit;
else
mp->time = NOW + (cp->rexmit+1)*MSrexmit;
DPRINT("xmit %d %lud %lud\n", cp->rexmit, NOW, mp->time);
.
1013a
/*
* round up last packet to mintu
*/
if(n < ifc->mintu){
n = ifc->mintu - n;
last = last->next = allocb(n);
memset(last->wptr, 0, n);
last->wptr += n;
}
.
988a
n = 0;
.
974c
/*
* round up to mintu
*/
memset(pkt->wptr, 0, n = ifc->mintu-mp->len);
.
963a
/*
* package n blocks into m packets. make sure
* no packet is < mintu or > maxtu in length.
*/
.
473c
if(cp->state>=Cconnected && cp->state!=Csuperceded){
.
88a
Csuperceded,
.
## diffname port/devnonet.c 1991/0119
## diff -e /n/bootesdump/1991/0118/sys/src/9/port/devnonet.c /n/bootesdump/1991/0119/sys/src/9/port/devnonet.c
1347c
nosendctl(cp, 0, 0);
.
1338c
nosend(cp, mp);
.
1335c
nohangup(cp);
.
1294c
nokproc(void *arg)
.
1189a
.
1184a
/*
* hangup (after processing message)
*/
if(f & NO_RESET){
DPRINT("reset with message\n");
noreset(cp);
} else if(f & NO_HANGUP){
DPRINT("hangup with message\n");
nohangup(cp);
}
.
1183c
if(cp->state==Cconnecting && !(f&NO_NEWCALL))
.
1181c
* any NO_NEWCALL after this is another call
.
1168c
noqack(cp, h->mid);
.
1166c
cp->hdr->flag &= ~(NO_NEWCALL|NO_SERVICE);
norack(cp, h->ack);
.
1114,1115c
norack(cp, h->ack);
noqack(cp, h->mid);
.
1109,1111c
norack(cp, h->ack);
if(f & NO_RESET)
noreset(cp);
else if(f & NO_HANGUP)
nohangup(cp);
.
1096,1099c
noreset(cp);
.
1092,1093c
if((f&NO_NEWCALL) && cp->state==Cconnected){
.
1065a
*
* State Transition: (no NO_NEWCALL in msg) Cconnecting -> Cconnected
.
1061c
nosend(cp, &ctl);
.
1049c
nosendctl(Noconv *cp, int flag, int new)
.
1039d
1006c
last = pkt = nohdr(cp, -msgrem);
.
996c
last = pkt = nohdr(cp, msgrem);
.
974c
last = pkt = nohdr(cp, mp->len);
.
930c
nosend(Noconv *cp, Nomsg *mp)
.
926c
* called by nooput(). the qlock(mp) synchronizes these two
.
907c
nohdr(Noconv *cp, int rem)
.
892c
noqack(Noconv *cp, int mid)
.
851c
norack(Noconv *cp, int mid)
.
846a
* send a hangup signal up the stream to get all line disciplines
* to cease and desist. The Creset state makes any subsequent close not
* send hangup messages.
*
* State Transition: {Cconnected, Cconnecting} -> Creset
*/
static void
noreset(Noconv *cp)
{
Block *bp;
Queue *q;
switch(cp->state){
case Cconnected:
case Cconnecting:
cp->state = Creset;
bp = allocb(0);
bp->type = M_HANGUP;
q = cp->rq;
PUTNEXT(q, bp);
break;
}
wakeup(&cp->r);
}
/*
.
838,842c
switch(cp->state){
case Cconnected:
case Cconnecting:
cp->state = Chungup;
bp = allocb(0);
bp->type = M_HANGUP;
q = cp->rq;
PUTNEXT(q, bp);
break;
}
.
833c
nohangup(Noconv *cp)
.
830a
*
* State Transition: {Cconnected, Cconnecting} -> Chungup
.
798c
nostartconv(cp, call.circuit, call.raddr, Cconnecting);
.
739c
nolisten(Chan *c, Noifc *ifc)
.
728a
*
* State Transition: Cclosed -> Copen -> Cconnecting
.
720d
718d
709c
nostartconv(cp, 2*(cp - ifc->conv), addr, Cconnecting);
.
689c
noconnect(Chan *c, char *addr)
.
686a
*
* State Transition: Copen -> Cconnecting
.
673c
noannounce(Chan *c, char *addr)
.
670a
*
* State Transition: Copen -> Chungup
.
650c
cp->rexmit = cp->bad = cp->sent = cp->rcvd = 0;
cp->lastacked = Nnomsg|(Nnomsg-1);
.
607c
nostartconv(Noconv *cp, int circuit, char *raddr, int state)
.
597c
nosend(cp, mp);
.
524c
nooput(Queue *q, Block *bp)
.
493c
noiput(Queue *q, Block *bp)
.
490a
*
* State Transition: (on M_HANGUP) * -> Chungup
.
479a
break;
case Chungup:
/*
* ack any close
*/
nosendctl(cp, NO_HANGUP, 1);
break;
.
477c
nosendctl(cp, NO_HANGUP, 1);
.
474,475c
switch(cp->state){
case Cconnected:
/*
* send close till we get one back
*/
nosendctl(cp, NO_HANGUP, 1);
.
456c
noclose(Queue *q)
.
453c
switch(cp->state){
case Chungup:
case Creset:
case Cclosed:
return 1;
}
return 0;
.
445a
*
* State Transitions: * -> Cclosed
.
429c
noopen(Queue *q, Stream *s)
.
426a
*
* State Transition: Cclosed -> Copen
.
417,420c
noiput,
nooput,
noopen,
noclose,
.
387c
noannounce(c, field[1]);
.
385c
noconnect(c, field[1]);
.
377c
* easier to do here than in nooput
.
314c
* real closing happens in noclose
.
279c
nolisten(c, ifc);
.
252c
kproc("nonetack", nokproc, 0);
.
88,89c
Creset,
.
30,44c
static void nohangup(Noconv*);
static void noreset(Noconv*);
static Block* nohdr(Noconv*, int);
static void nolisten(Chan*, Noifc*);
static void noannounce(Chan*, char*);
static void noconnect(Chan*, char*);
static void norack(Noconv*, int);
static void nosendctl(Noconv*, int, int);
static void nosend(Noconv*, Nomsg*);
static void nostartconv(Noconv*, int, char*, int);
static void noqack(Noconv*, int);
static void nokproc(void*);
static void noiput(Queue*, Block*);
static void nooput(Queue*, Block*);
static void noclose(Queue*);
static void noopen(Queue*, Stream*);
.
## diffname port/devnonet.c 1991/0206
## diff -e /n/bootesdump/1991/0119/sys/src/9/port/devnonet.c /n/bootesdump/1991/0206/sys/src/9/port/devnonet.c
1418c
while(cp->afirst != cp->anext){
.
1416c
* get the acknowledges out
.
1412d
1409,1410c
} else
.
1407c
norack(cp, mp->mid);
.
1405a
mp = &(cp->out[cp->first]);
.
944a
wakeup(&cp->r);
.
943c
cp->first = MSUCC(cp->first);
.
934d
931a
mp->acked = 1;
.
930d
664d
621c
qunlock(cp);
.
619a
if(waserror()){
/* throw out the message */
freeb(mp->first);
mp->first = 0;
mp->acked = 0;
if(MSUCC(cp->first) == cp->next)
cp->first = cp->next;
qunlock(cp);
nexterror();
}
.
613c
q->len = q->nb = 0;
.
611c
* take the message out of the queue
.
601c
* point the output buffer to the message
.
597,598c
cp->next = MSUCC(cp->next);
qlock(cp);
qunlock(&cp->mlock);
poperror();
.
590,594c
while(!windowopen(cp))
.
575,586c
/* throw out the message */
while(bp = getb(q))
freeb(bp);
.
573c
/*
* block till we get an output buffer
*/
.
538,545d
536c
return MSUCC(cp->next) != cp->first;
.
506a
.
503a
/*
* we give up, ack any unacked messages
*/
for(i = cp->first; i != cp->next; i = MSUCC(i))
norack(cp, cp->out[i].mid);
.
10a
#define MSUCC(x) (((x)+1)%Nnomsg)
.
## diffname port/devnonet.c 1991/0207
## diff -e /n/bootesdump/1991/0206/sys/src/9/port/devnonet.c /n/bootesdump/1991/0207/sys/src/9/port/devnonet.c
1416c
while(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){
.
543c
i = cp->next - cp->first;
if(i>=0 && i<32)
return 1;
if(i<0 && Nnomsg+i<32)
return 1;
return 0;
.
540a
int i;
.
## diffname port/devnonet.c 1991/0209
## diff -e /n/bootesdump/1991/0207/sys/src/9/port/devnonet.c /n/bootesdump/1991/0209/sys/src/9/port/devnonet.c
1414c
noreset(cp);
.
1412c
if(cp->rexmit++ > 15){
.
1106,1107d
1025c
if(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){
.
1012,1021d
492c
nosendctl(cp, NO_HANGUP, 0);
.
## diffname port/devnonet.c 1991/0316
## diff -e /n/bootesdump/1991/0209/sys/src/9/port/devnonet.c /n/bootesdump/1991/0316/sys/src/9/port/devnonet.c
279c
errors("channel not announced");
.
## diffname port/devnonet.c 1991/0318
## diff -e /n/bootesdump/1991/0316/sys/src/9/port/devnonet.c /n/bootesdump/1991/0318/sys/src/9/port/devnonet.c
1094a
.
1032c
memmove(pkt->wptr, bp->rptr, n = BLEN(bp));
.
984a
.
979c
memmove(bp->wptr, cp->media->rptr, cp->ifc->hsize + NO_HDRSIZE);
.
## diffname port/devnonet.c 1991/0320
## diff -e /n/bootesdump/1991/0318/sys/src/9/port/devnonet.c /n/bootesdump/1991/0320/sys/src/9/port/devnonet.c
1150c
print("new call on connected channel\n");
.
465a
/*
* wait until a hangup is received.
* then send a hangup message (until one is received).
*
* State Transitions: * -> Cclosed
*/
.
446,451c
.
## diffname port/devnonet.c 1991/0328
## diff -e /n/bootesdump/1991/0320/sys/src/9/port/devnonet.c /n/bootesdump/1991/0328/sys/src/9/port/devnonet.c
1246,1249c
if(f & NO_HANGUP){
.
1164,1166c
if(f & NO_HANGUP)
.
1157a
* A new call request (maybe), treat it as a reset if seen on a
* connected, hungup, or reset channel.
*
* On a connecting channel, treat as a reset if this is an
* invalid message ID.
*/
if(f & NO_NEWCALL){
switch(cp->state){
case Cclosed:
case Copen:
case Cannounced:
case Creset:
panic("nonetrcvmsg %d %d\n", cp->rcvcircuit, cp - cp->ifc->conv);
case Chungup:
case Cconnected:
print("Nonet call on connected/hanging-up circ %d conv %d\n",
cp->rcvcircuit, cp - cp->ifc->conv);
freeb(bp);
noreset(cp);
return;
case Cconnecting:
if(h->mid != mp->mid){
print("Nonet call on connecting circ %d conv %d\n",
cp->rcvcircuit, cp - cp->ifc->conv);
freeb(bp);
noreset(cp);
return;
}
break;
}
}
/*
.
1153a
freeb(bp);
.
1150,1152c
if(f & NO_RESET){
print("reset received\n");
.
1148c
* Obey reset even if the message id is bogus
.
904c
cp->rcvcircuit = -1;
bp = allocb(0);
.
902a
case Chungup:
print("resetting connection\n");
.
892c
* State Transition: {Cconnected, Cconnecting, Chungup} -> Creset
.
888,890c
* Send a hangup signal up the stream to get all line disciplines
* to cease and desist. Disassociate this conversation from a circuit
* number. Any subsequent close of the conversation will
* not send hangup messages.
.
512a
if(cp->media){
freeb(cp->media);
cp->media = 0;
}
.
7a
#include "../port/nonet.h"
.
## diffname port/devnonet.c 1991/0411
## diff -e /n/bootesdump/1991/0328/sys/src/9/port/devnonet.c /n/bootesdump/1991/0411/sys/src/9/port/devnonet.c
363c
nonetwrite(Chan *c, void *a, long n, ulong offset)
.
357c
return stringread(c, a, n, stats, offset);
.
353c
return stringread(c, a, n, cp->ruser, offset);
.
351c
return stringread(c, a, n, cp->addr, offset);
.
349c
return stringread(c, a, n, cp->raddr, offset);
.
328c
nonetread(Chan *c, void *a, long n, ulong offset)
.
## diffname port/devnonet.c 1991/0412
## diff -e /n/bootesdump/1991/0411/sys/src/9/port/devnonet.c /n/bootesdump/1991/0412/sys/src/9/port/devnonet.c
211c
devstat(c, dp, &nonetdir[conf.nnoconv], 1, devgen);
.
## diffname port/devnonet.c 1991/0413
## diff -e /n/bootesdump/1991/0412/sys/src/9/port/devnonet.c /n/bootesdump/1991/0413/sys/src/9/port/devnonet.c
1430c
if(cp->state <= Copen){
.
1428c
if(cp->state<=Copen || !canqlock(cp))
.
682a
cp->afirst = cp->anext = 0;
.
85,91c
Cclosed= 0,
Copen= 1,
Cannounced= 2,
Cconnected= 3,
Cconnecting= 4,
Chungup= 5,
Creset= 6,
.
## diffname port/devnonet.c 1991/0419
## diff -e /n/bootesdump/1991/0413/sys/src/9/port/devnonet.c /n/bootesdump/1991/0419/sys/src/9/port/devnonet.c
204a
Chan*
nonetclwalk(Chan *c, char *name)
{
return devclwalk(c, name);
}
.
## diffname port/devnonet.c 1991/0427
## diff -e /n/bootesdump/1991/0419/sys/src/9/port/devnonet.c /n/bootesdump/1991/0427/sys/src/9/port/devnonet.c
205,210d
## diffname port/devnonet.c 1991/0502
## diff -e /n/bootesdump/1991/0427/sys/src/9/port/devnonet.c /n/bootesdump/1991/0502/sys/src/9/port/devnonet.c
1393c
s &= 0xffff;
switch(s){
case 0xac9f:
case 0xc1a4:
case 0xc41c:
case 0xc46d:
{ int i;
print("%lux s,", s);
for(bp = first; bp; bp = bp->next)
for(i = 0; i < BLEN(bp); i++)
print(" %ux", bp->rptr[i]);
}
}
return s;
.
1357a
Block *first;
.
553c
if(i<0 && Nnomsg+i<Window)
.
551c
if(i>=0 && i<Window)
.
542a
enum {
Window= 1,
};
.
## diffname port/devnonet.c 1991/0503
## diff -e /n/bootesdump/1991/0502/sys/src/9/port/devnonet.c /n/bootesdump/1991/0503/sys/src/9/port/devnonet.c
1398a
if(0)
.
## diffname port/devnonet.c 1991/0604
## diff -e /n/bootesdump/1991/0503/sys/src/9/port/devnonet.c /n/bootesdump/1991/0604/sys/src/9/port/devnonet.c
1463c
} else /**/
.
1460c
/* if(cp->rexmit++ > 15){
.
## diffname port/devnonet.c 1991/0606
## diff -e /n/bootesdump/1991/0604/sys/src/9/port/devnonet.c /n/bootesdump/1991/0606/sys/src/9/port/devnonet.c
1472c
nosendctl(cp, NO_NULL, 0);
.
1207c
if(h->mid!=mp->mid || (f&NO_NULL)){
.
## diffname port/devnonet.c 1991/0608
## diff -e /n/bootesdump/1991/0606/sys/src/9/port/devnonet.c /n/bootesdump/1991/0608/sys/src/9/port/devnonet.c
1472c
nosendctl(cp, /*NO_NULL*/0, 0);
.
1463c
} else
.
1460c
if(cp->rexmit++ > 15){
.
1268a
noqack(cp, h->mid);
.
1194c
DPRINT("Nonet call on connecting circ %d conv %d\n",
.
1187c
DPRINT("Nonet call on connected/hanging-up circ %d conv %d\n",
.
1184c
DPRINT("nonetrcvmsg %d %d\n", cp->rcvcircuit, cp - cp->ifc->conv);
freeb(bp);
return;
.
1165c
DPRINT("reset received\n");
.
915d
## diffname port/devnonet.c 1991/0904
## diff -e /n/bootesdump/1991/0608/sys/src/9/port/devnonet.c /n/bootesdump/1991/0904/sys/src/9/port/devnonet.c
951c
if(mp->first)
freeb(mp->first);
.
## diffname port/devnonet.c 1991/0925
## diff -e /n/bootesdump/1991/0904/sys/src/9/port/devnonet.c /n/bootesdump/1991/0925/sys/src/9/port/devnonet.c
638d
636d
626,634c
if(!waserror()){
nosend(cp, mp);
poperror();
.
## diffname port/devnonet.c 1991/0926
## diff -e /n/bootesdump/1991/0925/sys/src/9/port/devnonet.c /n/bootesdump/1991/0926/sys/src/9/port/devnonet.c
1473,1474d
1471c
tsleep(&nonetkr, return0, 0, MSrexmit/2);
.
1461,1469c
unlock(ifc);
.
1453,1459c
ep = ifc->conv + conf.nnoconv;
for(cp = ifc->conv; cp < ep; cp++){
if(cp->state<=Copen || !canqlock(cp))
continue;
if(cp->state <= Copen){
qunlock(cp);
continue;
}
/*
* resend the first message
*/
if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){
mp = &(cp->out[cp->first]);
if(cp->rexmit++ > 15){
norack(cp, mp->mid);
noreset(cp);
} else
nosend(cp, mp);
}
/*
* get the acknowledges out
*/
while(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){
DPRINT("sending ack %d\n", cp->ack[cp->afirst]);
nosendctl(cp, /*NO_NULL*/0, 0);
}
qunlock(cp);
.
1451c
* loop through all active conversations
.
1445,1449c
.
1441,1443c
for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){
if(ifc->wq==0 || !canlock(ifc))
.
1439c
* loop through all active interfaces
.
1430,1437c
for(;;){
.
616,620d
610,612c
mp->first = first;
mp->last = last;
mp->len = len;
.
592,594c
freeb(first);
.
588a
* take the collected message out of the queue
*/
first = q->first;
last = q->last;
len = q->len;
q->len = q->nb = 0;
q->first = q->last = 0;
if(len == 0){
freeb(first);
qunlock(&cp->mlock);
return;
}
/*
.
567c
Block *first, *last;
int len;
.
## diffname port/devnonet.c 1991/1101
## diff -e /n/bootesdump/1991/0926/sys/src/9/port/devnonet.c /n/bootesdump/1991/1101/sys/src/9/port/devnonet.c
1473,1474c
if(cp->sendack){
DPRINT("sending ack %d\n", cp->ack);
.
1271d
1031,1034c
cp->sendack = 0;
cp->hdr->ack = cp->ack;
.
975,981c
cp->ack = mid;
cp->sendack = 1;
.
687c
cp->ack = 0;
cp->sendack = 0;
.
22d
## diffname port/devnonet.c 1991/1105
## diff -e /n/bootesdump/1991/1101/sys/src/9/port/devnonet.c /n/bootesdump/1991/1105/sys/src/9/port/devnonet.c
760c
sprint(buf, "%s %s", service, u->p->user);
.
## diffname port/devnonet.c 1991/1112
## diff -e /n/bootesdump/1991/1105/sys/src/9/port/devnonet.c /n/bootesdump/1991/1112/sys/src/9/port/devnonet.c
1471c
nonetfreeifc(ifc);
.
1436a
lock(ifc);
if(ifc->wq==0){
unlock(ifc);
continue;
}
ifc->ref++;
unlock(ifc);
.
1435c
if(ifc->wq==0)
.
140c
nonetdir[i].perm = 0666;
.
130c
nonetdir[i].perm = 0777;
.
73,77c
"addr", {Naddrqid}, 0, 0666,
"listen", {Nlistenqid}, 0, 0666,
"raddr", {Nraddrqid}, 0, 0666,
"ruser", {Nruserqid}, 0, 0666,
"stats", {Nstatsqid}, 0, 0666,
.
## diffname port/devnonet.c 1991/1114
## diff -e /n/bootesdump/1991/1112/sys/src/9/port/devnonet.c /n/bootesdump/1991/1114/sys/src/9/port/devnonet.c
1480c
tsleep(&nonetkr, return0, 0, MSrexmit);
.
## diffname port/devnonet.c 1991/1115
## diff -e /n/bootesdump/1991/1114/sys/src/9/port/devnonet.c /n/bootesdump/1991/1115/sys/src/9/port/devnonet.c
1420a
USED(arg);
.
409a
USED(c, dp);
.
403a
USED(c);
.
356c
return stringread(a, n, stats, offset);
.
352c
return stringread(a, n, cp->ruser, offset);
.
350c
return stringread(a, n, cp->addr, offset);
.
348c
return stringread(a, n, cp->raddr, offset);
.
305a
USED(c, name, omode, perm);
.
## diffname port/devnonet.c 1991/1121
## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devnonet.c /n/bootesdump/1991/1121/sys/src/9/port/devnonet.c
1456c
if(cp->state != Cconnected && cp->state != Cconnecting){
.
1295c
return 0;
}
.
1293c
return r;
} else {
.
1291a
return -1;
.
1270a
r = mp->len;
.
1241c
return -1;
.
1219c
return -1;
.
1191,1197d
1189c
return -1;
.
1182c
return -1;
.
1164c
return -1;
.
1135c
int
.
849,868c
switch(nonetrcvmsg(cp, bp)){
case -1:
print("bad call message");
streamclose(c);
continue;
case 0:
if(f & NO_SERVICE){
streamclose(c);
print("bad call message");
continue;
}
break;
default:
if(f & NO_SERVICE){
c->qid.path = STREAMQID(cp - ifc->conv, Sdataqid);
n = streamread(c, buf, sizeof(buf));
c->qid.path = STREAMQID(cp - ifc->conv, Sctlqid);
if(n <= 0)
error(Ebadctl);
buf[n] = 0;
user = strchr(buf, ' ');
if(user){
*user++ = 0;
strncpy(cp->ruser, user, NAMELEN);
} else
strcpy(cp->ruser, "none");
strncpy(cp->addr, buf, NAMELEN);
}
break;
.
846,847c
bp = call.msg;
.
844d
793a
Block *bp;
.
521,522d
511a
qlock(cp);
.
508d
504,505c
switch(cp->state){
case Cconnecting:
case Cconnected:
/*
* send close till we get one back
*/
nosendctl(cp, NO_HANGUP, 1);
for(i=0; i<10 && !ishungup(cp); i++){
nosendctl(cp, NO_HANGUP, 0);
tsleep(&cp->r, ishungup, cp, MSrexmit);
}
break;
case Chungup:
/*
* ack any close
*/
nosendctl(cp, NO_HANGUP, 1);
break;
}
poperror();
.
502c
* send hangup messages to the other side
* until it hangs up or we get tired.
.
494,500c
while(!isempty(cp))
tsleep(&cp->r, isempty, cp, MSrexmit);
.
492c
* wait till we have nothing to transmit
.
479,490c
if(!waserror()){
.
464,469c
static int
isempty(void *a)
{
Noconv *cp;
cp = (Noconv *)a;
switch(cp->state){
case Cconnecting:
case Cconnected:
return cp->first == cp->next;
default:
return 1;
}
}
.
449c
/*
* wait until a hangup is received.
* then send a hangup message (until one is received).
*
* State Transitions: * -> Cclosed
*/
.
315,318c
if(c->stream)
.
## diffname port/devnonet.c 1992/0111
## diff -e /n/bootesdump/1991/1121/sys/src/9/port/devnonet.c /n/bootesdump/1992/0111/sys/src/9/port/devnonet.c
7c
#include "../port/error.h"
.
## diffname port/devnonet.c 1992/0113
## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devnonet.c /n/bootesdump/1992/0113/sys/src/9/port/devnonet.c
279c
error(Enolisten);
.
241c
error(Enodev);
.
## diffname port/devnonet.c 1992/0129
## diff -e /n/bootesdump/1992/0113/sys/src/9/port/devnonet.c /n/bootesdump/1992/0129/sys/src/9/port/devnonet.c
379c
if(n > sizeof buf - 1)
n = sizeof buf - 1;
strncpy(buf, a, n);
buf[n] = '\0';
.
## diffname port/devnonet.c 1992/0219 # deleted
## diff -e /n/bootesdump/1992/0129/sys/src/9/port/devnonet.c /n/bootesdump/1992/0219/sys/src/9/port/devnonet.c
1,1513d
|