## diffname port/devdk.c 1990/0312
## diff -e /dev/null /n/bootesdump/1990/0312/sys/src/9/mips/devdk.c
0a
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "errno.h"
#define NOW (MACHP(0)->ticks)
#define DPRINT if(0)
enum {
/*
* configuration parameters
*/
Ndk = 2, /* max dks */
/*
* relative or immutable
*/
Nline = 256, /* max lines per dk */
Ndir = Nline + 1, /* entries in the dk directory */
Nsubdir = 5, /* entries in the sub directory */
};
typedef struct Dkmsg Dkmsg;
typedef struct Line Line;
typedef struct Dk Dk;
/*
* types of possible dkcalls
*/
enum {
Dial,
Announce,
Redial
};
/*
* format of messages to/from the datakit controller on the common
* signalling line
*/
struct Dkmsg {
uchar type;
uchar srv;
uchar param0l;
uchar param0h;
uchar param1l;
uchar param1h;
uchar param2l;
uchar param2h;
uchar param3l;
uchar param3h;
uchar param4l;
uchar param4h;
};
/*
* message codes (T_xxx == dialin.type, D_xxx == dialin.srv)
*/
#define T_SRV 1 /* service request */
#define D_SERV 1 /* (host to dkmux) announce a service */
#define D_DIAL 2 /* (host to dkmux) connect to a service */
#define D_XINIT 7 /* (dkmux to host) line has been spliced */
#define T_REPLY 2 /* reply to T_SRV/D_SERV or T_SRV/D_DIAL */
#define D_OK 1 /* not used */
#define D_OPEN 2 /* (dkmux to host) connection established */
#define D_FAIL 3 /* (dkmux to host) connection failed */
#define T_CHG 3 /* linege the status of a connection */
#define D_CLOSE 1 /* close the connection */
#define D_ISCLOSED 2 /* (dkmux to host) confirm a close */
#define D_CLOSEALL 3 /* (dkmux to host) close all connections */
#define D_REDIAL 6 /* (host to dkmux) redial a call */
#define T_ALIVE 4 /* (host to dkmux) keep alive message */
#define D_CONTINUE 0 /* host has not died since last msg */
#define D_RESTART 1 /* host has restarted */
#define D_MAXCHAN 2 /* request maximum line number */
#define T_RESTART 8 /* (dkmux to host) datakit restarted */
/*
* macros for cracking/forming the window negotiation parameter
*/
#define MIN(x,y) (x < y ? x : y)
#define W_WINDOW(o,d,t) ((o<<8) | (d<<4) | t | 0100000)
#define W_VALID(x) ((x) & 0100000)
#define W_ORIG(x) (((x)>>8) & 017)
#define W_DEST(x) (((x)>>4) & 017)
#define W_TRAF(x) ((x) & 017)
#define W_DESTMAX(x,y) (W_WINDOW(W_ORIG(x),MIN(W_DEST(x),y),W_TRAF(x)))
#define W_LIMIT(x,y) (W_WINDOW(MIN(W_ORIG(x),y),MIN(W_DEST(x),y),W_TRAF(x)))
#define W_VALUE(x) (1<<((x)+4))
#define WS_2K 7
/*
* one per datakit line
*/
struct Line {
QLock;
Rendez r; /* wait here for dial */
int state; /* dial state */
int err; /* dialing error (if non zero) */
int window; /* negotiated window */
int timestamp; /* timestamp of last call received on this line */
int calltolive; /* multiple of 15 seconds for dialing state to last */
Queue *rq;
char addr[64];
char raddr[64];
char ruser[32];
char other[64];
Dk *dp; /* interface contianing this line */
};
/*
* a dkmux dk. one exists for every stream that a
* dkmux line disilpline is pushed onto.
*/
struct Dk {
QLock;
int ref;
char name[64]; /* dk name */
Queue *wq; /* dk output queue */
int lines; /* number of lines */
int ncsc; /* csc line number */
Chan *csc; /* common signalling line */
Line line[Nline];
};
static Dk dk[Ndk];
/*
* conversation states (for Line.state)
*/
typedef enum {
Lclosed=0,
Lopened, /* opened but no call out */
Lconnected, /* opened and a call set up on htis line */
Lrclose, /* remote end has closed down */
Llclose, /* local end has closed down */
Ldialing, /* dialing a new call */
Llistening, /* this line listening for calls */
Lackwait, /* incoming call waiting for ack/nak */
Laccepting, /* waiting for user to accept or reject the call */
} Lstate;
/*
* datakit error to errno
*/
enum {
DKok,
DKbusy,
DKnetotl,
DKdestotl,
DKbadnet,
DKnetbusy,
DKinuse,
DKreject,
};
int dkerr[]={
[DKok]Egreg,
[DKbusy]Einuse, /* destination busy */
[DKnetotl]Enetotl, /* network not answering */
[DKdestotl]Edestotl, /* destination not answering */
[DKbadnet]Ebadnet, /* unassigned destination */
[DKnetbusy]Enetbusy, /* network overload */
[DKinuse]Einuse, /* server already exists */
[DKreject]Erejected /* call rejected by destination */
};
#define DKERRS sizeof(dkerr)/sizeof(int)
/*
* imported
*/
extern Qinfo urpinfo;
/*
* predeclared
*/
Chan* dkattach(char*);
static void dkmuxconfig(Dk*, Block*);
static int dkmesg(Dk*, int, int, int, int);
static void dkcsckproc(void*);
static int dklisten(Chan*);
static void dkanswer(Chan*, int, int);
static void dkwindow(Chan*);
static void dkcall(int, Chan*, char*, char*, char*);
static void dktimer(void*);
static void dkchgmesg(Dk*, Dkmsg*, int);
static void dkreplymesg(Dk*, Dkmsg*, int);
Chan* dkopen(Chan*, int);
/*
* the datakit multiplexor stream module definition
*/
static void dkmuxopen(Queue *, Stream *);
static void dkmuxclose(Queue *);
static void dkmuxoput(Queue *, Block *);
static void dkmuxiput(Queue *, Block *);
Qinfo dkmuxinfo = { dkmuxiput, dkmuxoput, dkmuxopen, dkmuxclose, "dkmux" };
/*
* a new dkmux. find a free dk structure and assign it to this queue.
*/
static void
dkmuxopen(Queue *q, Stream *s)
{
Dk *dp;
int i;
for(dp = dk; dp < &dk[Ndk]; dp++){
if(dp->wq == 0){
qlock(dp);
if(dp->wq) {
/* someone was faster than us */
qunlock(dp);
continue;
}
q->ptr = q->other->ptr = (void *)dp;
dp->csc = 0;
dp->ncsc = 4;
dp->lines = 16;
dp->name[0] = 0;
dp->wq = WR(q);
qunlock(dp);
return;
}
}
error(0, Enoifc);
}
/*
* close down a dkmux
*/
static void
dkmuxclose(Queue *q)
{
Dk *dp;
dp = (Dk *)q->ptr;
qlock(dp);
if(dp->csc)
close(dp->csc);
dp->wq = 0;
qunlock(dp);
}
/*
* handle configuration
*/
static void
dkmuxoput(Queue *q, Block *bp)
{
Dk *dp;
dp = (Dk *)q->ptr;
if(bp->type != M_DATA){
if(streamparse("config", bp))
dkmuxconfig(dp, bp);
else
PUTNEXT(q, bp);
return;
}
PUTNEXT(q, bp);
}
/*
* gather a message and send it up the appropriate stream
*
* The first two bytes of each message contains the channel
* number, low order byte first.
*
* Simplifying assumption: one put == one message && the channel number
* is in the first block. If this isn't true, demultiplexing will not
* work.
*/
static void
dkmuxiput(Queue *q, Block *bp)
{
Dk *dp;
Line *lp;
int line;
dp = (Dk *)q->ptr;
if(bp->type != M_DATA){
PUTNEXT(q, bp);
return;
}
line = *bp->rptr++ | (*bp->rptr++<<8);
if(line<0 || line>=dp->lines){
print("dkmuxiput bad line %d\n", line);
freeb(bp);
return;
}
lp = &dp->line[line];
if(canqlock(lp)){
if(lp->rq)
PUTNEXT(lp->rq, bp);
else{
print("dkmuxiput unopened line %d\n", line);
freeb(bp);
}
qunlock(lp);
} else {
print("dkmuxiput unopened line %d\n", line);
freeb(bp);
}
}
/*
* the datakit line stream module definition
*/
static void dkstopen(Queue *, Stream *);
static void dkstclose(Queue *);
static void dkoput(Queue *, Block *);
static void dkiput(Queue *, Block *);
Qinfo dkinfo = { dkiput, dkoput, dkstopen, dkstclose, "dk" };
/*
* open and save a pointer to the conversation
*/
static void
dkstopen(Queue *q, Stream *s)
{
Dk *dp;
Line *lp;
dp = &dk[s->dev];
q->other->ptr = q->ptr = lp = &dp->line[s->id];
lp->dp = dp;
lp->rq = q;
}
/*
* close down a datakit conversation
*/
static void
dkstclose(Queue *q)
{
Dk *dp;
Line *lp;
lp = (Line *)q->ptr;
dp = lp->dp;
/*
* shake hands with dk
*/
switch(lp->state){
case Lclosed:
case Llclose:
break;
case Lrclose:
dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0);
lp->state = Lclosed;
break;
case Lackwait:
dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0);
lp->state = Llclose;
break;
case Llistening:
dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0);
lp->state = Llclose;
break;
case Lconnected:
dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0);
lp->state = Llclose;
break;
case Lopened:
lp->state = Lclosed;
}
qlock(lp);
lp->rq = 0;
qunlock(lp);
}
/*
* this is only called by hangup
*/
static void
dkiput(Queue *q, Block *bp)
{
PUTNEXT(q, bp);
}
/*
* we assume that each put is a message.
*
* add a 2 byte channel number to the start of each message
*/
static void
dkoput(Queue *q, Block *bp)
{
Line *lp;
Dk *dp;
int line;
if(bp->type != M_DATA){
freeb(bp);
error(0, Ebadarg);
}
lp = (Line *)q->ptr;
dp = lp->dp;
line = lp - dp->line;
if(bp->base && bp->rptr - bp->base >= 2)
bp->rptr -= 2;
bp->rptr[0] = line;
bp->rptr[1] = line>>8;
PUTNEXT(dp->wq, bp);
}
/*
* configure a datakit multiplexor. this takes 3 arguments separated
* by spaces:
* the line number of the common signalling channel (must be > 0)
* the number of lines in the device (optional)
* the name of the dk (optional)
*
* we can configure only once
*/
static void
dkmuxconfig(Dk *dp, Block *bp)
{
Chan *c;
char *fields[3];
int n;
char buf[64];
static int dktimeron;
if(dp->csc != 0){
freeb(bp);
error(0, Ebadarg);
}
/*
* parse
*/
n = getfields((char *)bp->rptr, fields, 3, ' ');
switch(n){
case 3:
strncpy(dp->name, fields[2], sizeof(dp->name));
case 2:
dp->lines = strtoul(fields[1], 0, 0);
case 1:
dp->ncsc = strtoul(fields[0], 0, 0);
break;
default:
freeb(bp);
error(0, Ebadarg);
}
freeb(bp);
if(dp->ncsc <= 0 || dp->lines <= dp->ncsc){
dp->lines = 16;
error(0, Ebadarg);
}
/*
* open a stream for the csc and push urp onto it
*/
c = 0;
if(waserror()){
if(c)
close(c);
nexterror();
}
c = dkattach(dp->name);
c->qid = STREAMQID(dp->ncsc, Sdataqid);
dkopen(c, ORDWR);
dp->csc = c;
/*
* start a process to deal with it
*/
sprint(buf, "**csckproc%d**", dp->ncsc);
kproc(buf, dkcsckproc, dp);
poperror();
/*
* start a keepalive process if one doesn't exist
*/
if(dktimeron == 0){
dktimeron = 1;
kproc("**dktimer**", dktimer, 0);
}
}
/*
* qid's
*/
enum {
/*
* per line
*/
Daddrqid,
Dlistenqid,
Draddrqid,
Duserqid,
Dotherqid,
Dlineqid,
/*
* per device
*/
Dcloneqid,
};
/*
* the dk directory
*/
Dirtab dkdir[Ndir];
/*
* the per stream directory structure
*/
Dirtab dksubdir[]={
"addr", Daddrqid, 0, 0600,
"listen", Dlistenqid, 0, 0600,
"other", Dotherqid, 0, 0600,
"raddr", Draddrqid, 0, 0600,
"ruser", Duserqid, 0, 0600,
};
/*
* dk file system. most of the calls use dev.c to access the dk
* directory and stream.c to access the dk devices.
*/
void
dkreset(void)
{
}
/*
* create the dk directory. the files are `clone' and stream
* directories '1' to '32' (or whatever Nline is in decimal)
*/
void
dkinit(void)
{
int i;
/*
* create the directory.
*/
/*
* the circuits
*/
for(i = 1; i < Nline; i++) {
sprint(dkdir[i].name, "%d", i);
dkdir[i].qid = CHDIR|STREAMQID(i, Dlineqid);
dkdir[i].length = 0;
dkdir[i].perm = 0600;
}
/*
* the clone device
*/
strcpy(dkdir[0].name, "clone");
dkdir[0].qid = Dcloneqid;
dkdir[0].length = 0;
dkdir[0].perm = 0600;
}
Chan*
dkattach(char *spec)
{
Chan *c;
Dk *dp;
/*
* find a multiplexor with the same name
*/
for(dp = dk; dp < &dk[Ndk]; dp++){
qlock(dp);
if(dp->wq && strcmp(spec, dp->name)==0) {
dp->ref++;
qunlock(dp);
break;
}
qunlock(dp);
}
if(dp == &dk[Ndk])
error(0, Enoifc);
c = devattach('k', spec);
c->dev = dp - dk;
return c;
}
Chan*
dkclone(Chan *c, Chan *nc)
{
Dk *dp;
dp = &dk[c->dev];
qlock(dp);
dp->ref++;
qunlock(dp);
return devclone(c, nc);
}
int
dkwalk(Chan *c, char *name)
{
if(c->qid == CHDIR)
return devwalk(c, name, dkdir, dk[c->dev].lines, devgen);
else
return devwalk(c, name, dksubdir, Nsubdir, streamgen);
}
void
dkstat(Chan *c, char *dp)
{
if(c->qid == CHDIR)
devstat(c, dp, dkdir, dk[c->dev].lines, devgen);
else
devstat(c, dp, dksubdir, Nsubdir, streamgen);
}
/*
* opening a dk device allocates a Line. Opening the `clone'
* device is a ``macro'' for finding a free Line and opening
* it's ctl file.
*
* opening the `listen' sub device is a macro for listening for
* a new call. Lile `clone' the ctl file of the new channel is
* returned.
*/
Chan*
dkopen(Chan *c, int omode)
{
extern Qinfo dkinfo;
Stream *s;
Line *lp, *end;
Dk *dp;
int line;
if(c->qid == Dcloneqid){
/*
* get an unused device and open it's control file
*/
dp = &dk[c->dev];
end = &dp->line[dp->lines];
for(lp = &dp->line[dp->ncsc+1]; lp < end; lp++){
if(lp->state == Lclosed && canqlock(lp)){
if(lp->state != Lclosed){
qunlock(lp);
continue;
}
c->qid = STREAMQID(lp-dp->line, Sctlqid);
qunlock(lp);
break;
}
}
if(lp == end)
error(0, Enodev);
streamopen(c, &dkinfo);
pushq(c->stream, &urpinfo);
} else if(STREAMTYPE(c->qid) == Dlistenqid){
/*
* listen for a call and open the control file for the
* channel on which the call arrived.
*/
line = dklisten(c);
c->qid = STREAMQID(line, Sctlqid);
streamopen(c, &dkinfo);
pushq(c->stream, &urpinfo);
dkwindow(c);
} else if(c->qid != CHDIR){
/*
* open whatever c points to, make sure it has an urp
*/
streamopen(c, &dkinfo);
if(strcmp(c->stream->procq->next->info->name, "urp")!=0)
pushq(c->stream, &urpinfo);
}
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
return c;
}
void
dkcreate(Chan *c, char *name, int omode, ulong perm)
{
error(0, Eperm);
}
void
dkclose(Chan *c)
{
Dk *dp;
/* real closing happens in lancestclose */
if(c->qid != CHDIR)
streamclose(c);
dp = &dk[c->dev];
qlock(dp);
dp->ref--;
qunlock(dp);
}
long
dkread(Chan *c, void *a, long n)
{
int t;
Line *lp;
t = STREAMTYPE(c->qid);
if(t>=Slowqid || t==Dlineqid)
return streamread(c, a, n);
if(c->qid == CHDIR)
return devdirread(c, a, n, dkdir, dk[c->dev].lines, devgen);
lp = &dk[c->dev].line[STREAMID(c->qid)];
switch(t){
case Daddrqid:
return stringread(c, a, n, lp->addr);
case Draddrqid:
return stringread(c, a, n, lp->raddr);
case Duserqid:
return stringread(c, a, n, lp->ruser);
}
error(0, Eperm);
}
long
dkwrite(Chan *c, void *a, long n)
{
int t;
char buf[256];
char *field[5];
int m;
t = STREAMTYPE(c->qid);
/*
* get data dispatched as quickly as possible
*/
if(t == Sdataqid)
return streamwrite(c, a, n, 0);
/*
* easier to do here than in dkoput
*/
if(t == Sctlqid){
strncpy(buf, a, sizeof buf);
m = getfields(buf, field, 5, ' ');
if(strcmp(field[0], "connect")==0){
if(m < 2)
error(0, Ebadarg);
dkcall(Dial, c, field[1], 0, 0);
} else if(strcmp(field[0], "announce")==0){
if(m < 2)
error(0, Ebadarg);
dkcall(Announce, c, field[1], 0, 0);
} else if(strcmp(field[0], "redial")==0){
if(m < 4)
error(0, Ebadarg);
dkcall(Redial, c, field[1], field[2], field[3]);
} else if(strcmp(field[0], "accept")==0){
if(m < 2)
error(0, Ebadarg);
dkanswer(c, strtoul(field[1], 0, 0), 0);
} else if(strcmp(field[0], "reject")==0){
if(m < 3)
error(0, Ebadarg);
dkanswer(c, strtoul(field[1], 0, 0), strtoul(field[2], 0, 0));
} else
return streamwrite(c, a, n, 0);
return n;
}
if(t >= Slowqid)
return streamwrite(c, a, n, 0);
error(0, Eperm);
}
void
dkremove(Chan *c)
{
error(0, Eperm);
}
void
dkwstat(Chan *c, char *dp)
{
error(0, Eperm);
}
void
dkerrstr(Error *e, char *buf)
{
rooterrstr(e, buf);
}
void
dkuserstr(Error *e, char *buf)
{
extern consuserstr(Error *, char *);
consuserstr(e, buf);
}
/*
* send a message to the datakit on the common signaling line
*/
static int
dkmesg(Dk *dp, int type, int srv, int p0, int p1)
{
Dkmsg d;
Block *bp;
if(dp->csc == 0)
return -1;
if(waserror())
return -1;
d.type = type;
d.srv = srv;
d.param0l = p0;
d.param0h = p0>>8;
d.param1l = p1;
d.param1h = p1>>8;
d.param2l = 0;
d.param2h = 0;
d.param3l = 0;
d.param3h = 0;
d.param4l = 0;
d.param4h = 0;
streamwrite(dp->csc, (char *)&d, sizeof(Dkmsg), 1);
poperror();
return 0;
}
/*
* call out on a datakit
*/
static int
calldone(void *a)
{
Line *lp;
lp = (Line *)a;
return lp->state != Ldialing;
}
static void
dkcall(int type, Chan *c, char *addr, char *nuser, char *machine)
{
char dialstr[66];
int line;
char dialtone;
int t_val, d_val;
Dk *dp;
Line *lp;
Chan *dc;
line = STREAMID(c->qid);
dp = &dk[c->dev];
lp = &dp->line[line];
/*
* only dial on virgin lines
*/
if(lp->state != Lclosed)
error(0, Ebadarg);
DPRINT("dkcall(line=%d, type=%d, dest=%s)\n", line, type, addr);
/*
* build dial string (guard against new lines)
*/
if(strchr(addr, '\n'))
error(0, Ebadarg);
if(strlen(addr)+strlen(u->p->pgrp->user)+2 >= sizeof(dialstr))
error(0, Ebadarg);
strcpy(dialstr, addr);
switch(type){
case Dial:
t_val = T_SRV;
d_val = D_DIAL;
strcat(dialstr, "\n");
strcat(dialstr, u->p->pgrp->user);
strcat(dialstr, "\n");
break;
case Announce:
t_val = T_SRV;
d_val = D_SERV;
break;
case Redial:
t_val = T_CHG;
d_val = D_REDIAL;
strcat(dialstr, "\n");
strcat(dialstr, nuser);
strcat(dialstr, "\n");
strcat(dialstr, machine);
strcat(dialstr, "\n");
break;
}
/*
* open the data file
*/
dc = dkattach(dp->name);
if(waserror()){
close(dc);
nexterror();
}
dc->qid = STREAMQID(line, Sdataqid);
dkopen(dc, ORDWR);
lp->calltolive = 4;
lp->state = Ldialing;
/*
* tell the controller we want to make a call
*/
DPRINT("dialout\n");
dkmesg(dp, t_val, d_val, line, W_WINDOW(WS_2K,WS_2K,2));
/*
* if redial, wait for a dial tone (otherwise we might send
* the dialstr to the previous other end and not the controller)
*/
if(type==Redial){
if(streamread(dc, &dialtone, 1L) != 1L){
lp->state = Lconnected;
error(0, Ebadarg);
}
}
/*
* make the call
*/
DPRINT("dialstr %s\n", dialstr);
streamwrite(dc, dialstr, (long)strlen(dialstr), 1);
close(dc);
poperror();
/*
* redial's never get a reply, assume it worked
*/
if(type == Redial) {
lp->state = Lconnected;
return;
}
/*
* wait for a reply
*/
DPRINT("reply wait\n");
sleep(&lp->r, calldone, lp);
/*
* if there was an error, translate it to a plan 9
* errno and report it to the user.
*/
DPRINT("got reply %d\n", lp->state);
if(lp->state != Lconnected) {
if(lp->err >= DKERRS)
error(0, dkerr[0]);
else
error(0, dkerr[lp->err]);
}
/*
* linege state if serving
*/
if(type == D_SERV){
lp->state = Llistening;
}
DPRINT("connected!\n");
/*
* decode the window size
*/
if (W_VALID(lp->window)){
/*
* a 1127 window negotiation
*/
lp->window = W_VALUE(W_DEST(lp->window));
} else if(lp->window>2 && lp->window<31){
/*
* a generic window negotiation
*/
lp->window = 1<<lp->window;
} else
lp->window = 0;
/*
* tag the connection
*/
strncpy(lp->addr, addr, sizeof(lp->addr)-1);
strncpy(lp->raddr, addr, sizeof(lp->raddr)-1);
/*
* reset the protocol
*/
dkwindow(c);
}
/*
* listen for a call, reflavor the
*/
static int
dklisten(Chan *c)
{
char dialstr[512];
char *line[12];
char *field[8];
Line *lp;
Dk *dp;
int n, lineno, ts, window;
Chan *dc;
dp = &dk[c->dev];
/*
* open the data file
*/
dc = dkattach(dp->name);
if(waserror()){
close(dc);
nexterror();
}
dc->qid = STREAMQID(STREAMID(c->qid), Sdataqid);
dkopen(dc, ORDWR);
/*
* wait for a call in
*/
for(;;){
/*
* read the dialstring and null terminate it
*/
n = streamread(dc, dialstr, sizeof(dialstr)-1);
DPRINT("returns %d\n", n);
if(n <= 0)
error(0, Eio);
dialstr[n] = 0;
DPRINT("dialstr = %s\n", dialstr);
/*
* break the dial string into lines
*/
n = getfields(dialstr, line, 12, '\n');
if (n < 2) {
DPRINT("bad dialstr from dk (1 line)\n");
error(0, Eio);
}
/*
* line 0 is `line.tstamp.traffic[.urpparms.window]'
*/
window = 0;
switch(getfields(line[0], field, 5, '.')){
case 5:
/*
* generic way of passing window
*/
window = strtoul(field[4], 0, 0);
if(window > 0 && window <31)
window = 1<<window;
else
window = 0;
/*
* intentional fall through
*/
case 3:
/*
* 1127 way of passing window
*/
if(window == 0){
window = strtoul(field[2], 0, 0);
if(W_VALID(window))
window = W_VALUE(W_ORIG(window));
else
window = 0;
}
break;
default:
print("bad message from dk(bad first line)\n");
continue;
}
lineno = strtoul(field[0], 0, 0);
if(lineno >= dp->lines){
print("dklisten: illegal line %d\n", lineno);
continue;
}
lp = &dp->line[lineno];
ts = strtoul(field[1], 0, 0);
/*
* this could be a duplicate request
*/
if(ts == lp->timestamp){
print("dklisten: repeat timestamp %d\n", lineno);
continue;
}
/*
* take care of glare (datakit picked an inuse channel
* for the call to come in on).
*/
if(!canqlock(lp)){
print("DKbusy1\n");
dkanswer(c, lineno, DKbusy);
continue;
} else {
if(lp->state != Lclosed){
qunlock(lp);
print("DKbusy2 %ux\n", lp->state);
dkanswer(c, lineno, DKbusy);
continue;
}
}
lp->window = window;
/*
* Line 1 is `my-dk-name.service[.more-things]'.
* Special characters are escaped by '\'s.
*/
strncpy(lp->addr, line[1], sizeof(lp->addr)-1);
/*
* the rest is variable length
*/
switch(n) {
case 2:
/* no more lines */
lp->ruser[0] = 0;
lp->raddr[0] = 0;
break;
case 3:
/* line 2 is `source.user.param1.param2' */
getfields(line[2], field, 3, '.');
strncpy(lp->raddr, field[0], sizeof(lp->raddr)-1);
strncpy(lp->ruser, field[1], sizeof(lp->ruser)-1);
break;
case 4:
/* line 2 is `user.param1.param2' */
getfields(line[2], field, 2, '.');
strncpy(lp->ruser, field[0], sizeof(lp->ruser)-1);
/* line 3 is `source.node.mod.line' */
strncpy(lp->raddr, line[3], sizeof(lp->raddr)-1);
break;
default:
print("bad message from dk(>4 line)\n");
qunlock(lp);
error(0, Ebadarg);
}
sprint(lp->other, "w(%d)", W_TRAF(lp->window));
DPRINT("src(%s)user(%s)dest(%s)other(%s)\n", lp->raddr, lp->ruser,
lp->addr, lp->other);
lp->timestamp = ts;
lp->state = Lconnected;
qunlock(lp);
close(dc);
poperror();
DPRINT("dklisten returns %d\n", lineno);
return lineno;
}
}
/*
* answer a call
*/
static void
dkanswer(Chan *c, int line, int code)
{
char reply[64];
Dk *dp;
Chan *dc;
Line *lp;
dp = &dk[c->dev];
lp = &dp->line[line];
/*
* open the data file (c is a control file)
*/
dc = dkattach(dp->name);
if(waserror()){
close(dc);
nexterror();
}
dc->qid = STREAMQID(STREAMID(c->qid), Sdataqid);
dkopen(dc, ORDWR);
/*
* send the reply
*/
sprint(reply, "%ud.%ud.%ud", line, lp->timestamp, code);
DPRINT("dkanswer %s\n", reply);
streamwrite(dc, reply, strlen(reply), 1);
close(dc);
poperror();
}
/*
* set the window size and reset the protocol
*/
static void
dkwindow(Chan *c)
{
char buf[64];
long wins;
Line *lp;
lp = &dk[c->dev].line[STREAMID(c->qid)];
if(lp->window == 0)
lp->window = 64;
sprint(buf, "init %d %d", lp->window, Streamhi);
streamwrite(c, buf, strlen(buf), 1);
}
/*
* hangup a datakit connection
*/
static void
dkhangup(Line *lp)
{
Block *bp;
qlock(lp);
if(lp->rq){
bp = allocb(0);
bp->type = M_HANGUP;
PUTNEXT(lp->rq, bp);
}
qunlock(lp);
}
/*
* A process which listens to all input on a csc line
*/
static void
dkcsckproc(void *a)
{
long n;
Dk *dp;
Dkmsg d;
int line;
int i;
dp = (Dk *)a;
/*
* loop forever listening
*/
for(;;){
n = streamread(dp->csc, (char *)&d, (long)sizeof(d));
if(n != sizeof(d)){
print("strange csc message %d\n", n);
continue;
}
line = (d.param0h<<8) + d.param0l;
/* print("t(%d)s(%d)l(%d)\n", d.type, d.srv, line); /**/
switch (d.type) {
case T_CHG: /* controller wants to close a line */
dkchgmesg(dp, &d, line);
break;
case T_REPLY: /* reply to a dial request */
dkreplymesg(dp, &d, line);
break;
case T_SRV: /* ignore it, it's useless */
print("dksrvmesg(%d)\n", line);
break;
case T_RESTART: /* datakit reboot */
print("dk restart\n");
if(line >=0 && line<dp->lines){
print("maxlines=%d\n", line+1);
dp->lines=line+1;
}
break;
default:
DPRINT("unrecognized csc message %o(%o)\n", d.type, line);
break;
}
}
}
/*
* datakit requests or confirms closing a line
*/
static void
dkchgmesg(Dk *dp, Dkmsg *dialp, int line)
{
Line *lp;
if (line <= 0 || line >= dp->lines) {
/* tell controller this line is not in use */
dkmesg(dp, T_CHG, D_CLOSE, line, 0);
return;
}
lp = &dp->line[line];
switch (dialp->srv) {
case D_CLOSE: /* remote shutdown */
switch (lp->state) {
case Ldialing:
/* simulate a failed connection */
dkreplymesg(dp, (Dkmsg *)0, line);
lp->state = Lrclose;
break;
case Lrclose:
case Lconnected:
case Llistening:
case Lackwait:
dkhangup(lp);
lp->state = Lrclose;
break;
case Lopened:
dkmesg(dp, T_CHG, D_CLOSE, line, 0);
break;
case Llclose:
case Lclosed:
dkhangup(lp);
dkmesg(dp, T_CHG, D_CLOSE, line, 0);
lp->state = Lclosed;
break;
}
break;
case D_ISCLOSED: /* acknowledging a local shutdown */
switch (lp->state) {
case Llclose:
case Lclosed:
lp->state = Lclosed;
break;
case Lrclose:
case Lconnected:
case Llistening:
case Lackwait:
break;
}
break;
default:
print("unrecognized T_CHG\n");
}
}
/*
* datakit replies to a dialout. capture reply code and traffic parameters
*/
static void
dkreplymesg(Dk *dp, Dkmsg *dialp, int line)
{
Proc *p;
Line *lp;
DPRINT("dkreplymesg(%d)\n", line);
if(line < 0 || line >= dp->lines)
return;
lp=&dp->line[line];
if(lp->state != Ldialing)
return;
if(dialp){
/*
* a reply from the dk
*/
lp->state = (dialp->srv==D_OPEN) ? Lconnected : Lrclose;
lp->err = (dialp->param1h<<8) + dialp->param1l;
lp->window = lp->err;
DPRINT("dkreplymesg: %d\n", lp->state);
} else {
/*
* a local abort
*/
lp->state = Lrclose;
lp->err = 0;
}
if(lp->state==Lrclose){
dkhangup(lp);
}
wakeup(&lp->r);
}
/*
* 15-second timer for all interfaces
*/
static Rendez dkt;
static int
fuckit(void *a)
{
return 0;
}
static void
dktimer(void *a)
{
int dki, i;
Dk *dp;
Line *lp;
waserror();
for(;;){
/*
* loop through the active dks
*/
for(dki=0; dki<Ndk; dki++){
dp = &dk[dki];
if(dp->csc==0)
continue;
/*
* send keep alive
*/
dkmesg(dp, T_ALIVE, D_CONTINUE, 0, 0);
/*
* remind controller of dead lines and
* timeout calls that take to long
*/
for (i=0; i<dp->lines; i++){
lp = &dp->line[i];
switch(lp->state){
case Llclose:
dkmesg(dp, T_CHG, D_CLOSE, i, 0);
break;
case Ldialing:
if(lp->calltolive==0 || --lp->calltolive!=0)
break;
dkreplymesg(dp, (Dkmsg *)0, i);
break;
}
}
}
tsleep(&dkt, fuckit, 0, 7500);
}
}
.
## diffname port/devdk.c 1990/0315
## diff -e /n/bootesdump/1990/0312/sys/src/9/mips/devdk.c /n/bootesdump/1990/0315/sys/src/9/mips/devdk.c
1121c
DPRINT("DKbusy2 %ux\n", lp->state);
.
1115c
DPRINT("DKbusy1\n");
.
593d
413a
else
panic("dkoput");
.
304c
DPRINT("dkmuxiput unopened line %d\n", line);
.
299c
DPRINT("dkmuxiput unopened line %d\n", line);
.
289c
DPRINT("dkmuxiput bad line %d\n", line);
.
287c
line = bp->rptr[0] | (bp->rptr[1]<<8);
bp->rptr += 2;
.
115c
* dkmux line discipline is pushed onto.
.
## diffname port/devdk.c 1990/0319
## diff -e /n/bootesdump/1990/0315/sys/src/9/mips/devdk.c /n/bootesdump/1990/0319/sys/src/9/mips/devdk.c
784,786d
727c
switch(STREAMTYPE(c->qid)){
.
725a
if(c->qid & CHDIR){
if(c->qid == CHDIR)
return devdirread(c, a, n, dkdir, dk[c->dev].lines, devgen);
else
return devdirread(c, a, n, dksubdir, Nsubdir, streamgen);
}
.
723,724d
720,721c
if(c->stream)
.
717d
705c
if(c->stream)
.
684a
break;
.
679a
* read only files
*/
if(omode != OREAD)
error(0, Ebadarg);
break;
default:
/*
.
678c
break;
case Daddrqid:
case Draddrqid:
case Duserqid:
case Dotherqid:
.
668c
break;
case Dlistenqid:
.
648a
* directories are read only
*/
if(omode != OREAD)
error(0, Ebadarg);
} else switch(STREAMTYPE(c->qid)){
case Dcloneqid:
/*
.
647c
if(c->qid & CHDIR){
.
## diffname port/devdk.c 1990/0321
## diff -e /n/bootesdump/1990/0319/sys/src/9/mips/devdk.c /n/bootesdump/1990/0321/sys/src/9/mips/devdk.c
540a
newqinfo(&dkmuxinfo);
newqinfo(&urpinfo);
.
## diffname port/devdk.c 1990/0403
## diff -e /n/bootesdump/1990/0321/sys/src/9/mips/devdk.c /n/bootesdump/1990/0403/sys/src/9/mips/devdk.c
1130a
if(lp->state != Lconnected)
dkanswer(c, lineno, DKbusy);
.
## diffname port/devdk.c 1990/0509
## diff -e /n/bootesdump/1990/0403/sys/src/9/mips/devdk.c /n/bootesdump/1990/0509/sys/src/9/mips/devdk.c
420c
if(QFULL(dp->wq->next)){
print("dk wq full\n");
freeb(bp);
} else
PUTNEXT(dp->wq, bp);
.
## diffname port/devdk.c 1990/0511
## diff -e /n/bootesdump/1990/0509/sys/src/9/mips/devdk.c /n/bootesdump/1990/0511/sys/src/9/mips/devdk.c
1204a
panic("dklisten terminates strangely\n");
.
902c
if(lp->state != Lopened)
.
730c
/* real closing happens in dkstclose */
.
680a
qunlock(lp);
.
673d
331a
if(lp->state == Lclosed)
lp->state = Lopened;
.
## diffname port/devdk.c 1990/0617
## diff -e /n/bootesdump/1990/0511/sys/src/9/mips/devdk.c /n/bootesdump/1990/0617/sys/src/9/mips/devdk.c
1291a
/*
* tell datakit we've rebooted. It should close all channels.
*/
dkmesg(dp, T_ALIVE, D_RESTART, 0, 0); /* do this on mips but not 68020 */
dkmesg(dp, T_CHG, D_CLOSEALL, 0, 0);
.
1087a
print("bad dialstr %d '%s'\n", n, dialstr);
.
1078a
}
.
1077a
{print("bad n\n");
.
1006c
* change state if serving
.
69c
#define T_CHG 3 /* change the status of a connection */
.
## diffname port/devdk.c 1990/0707
## diff -e /n/bootesdump/1990/0617/sys/src/9/mips/devdk.c /n/bootesdump/1990/0707/sys/src/9/mips/devdk.c
1299c
if(dp->restart)
dkmesg(dp, T_ALIVE, D_RESTART, 0, 0);
.
916a
bang = strchr(dialstr, '!');
if(bang){
dot = strchr(dialstr, '.');
if(dot==0 || dot > bang)
*bang = '.';
}
.
910c
* build dial string
* - guard against new lines
* - change ! into . to delimit service
.
895a
char *bang, *dot;
.
458c
if(strcmp(fields[2], "restart")!=0)
dp->restart = 0;
.
456a
case 4:
strncpy(dp->name, fields[3], sizeof(dp->name));
.
455c
dp->restart = 1;
n = getfields((char *)bp->rptr, fields, 4, ' ');
.
442c
char *fields[4];
.
433a
* the word `restart' or `norestart' (optional/default==restart)
.
430c
* configure a datakit multiplexor. this takes 4 arguments separated
.
125a
int restart;
.
## diffname port/devdk.c 1990/0717
## diff -e /n/bootesdump/1990/0707/sys/src/9/mips/devdk.c /n/bootesdump/1990/0717/sys/src/9/mips/devdk.c
554c
urpreset();
.
## diffname port/devdk.c 1990/0722
## diff -e /n/bootesdump/1990/0717/sys/src/9/mips/devdk.c /n/bootesdump/1990/0722/sys/src/9/mips/devdk.c
596a
if(*spec == 0)
spec = "dk";
.
595c
* find a multiplexor with the same name (default dk)
.
506c
kproc("dktimer", dktimer, 0);
.
497c
sprint(buf, "csckproc%d", dp->ncsc);
.
458a
strcpy(dp->name, "dk");
.
## diffname port/devdk.c 1990/0830
## diff -e /n/bootesdump/1990/0722/sys/src/9/mips/devdk.c /n/bootesdump/1990/0830/sys/src/9/mips/devdk.c
418,419c
else {
print("dkoput l %d b %ux r %ux w %ux\n", line, bp->base, bp->rptr,
bp->wptr);
freeb(bp);
return;
}
.
## diffname port/devdk.c 1990/0911
## diff -e /n/bootesdump/1990/0830/sys/src/9/mips/devdk.c /n/bootesdump/1990/0911/sys/src/9/mips/devdk.c
1487c
while(waserror())
print("dktimer: error\n");
.
1322a
}
DPRINT("dkcsckproc: closeall %s\n", dp->name);
.
1321c
if(dp->restart) {
DPRINT("dkcsckproc: restart %s\n", dp->name);
.
980c
dkmesg(dp, t_val, d_val, line, W_WINDOW(dp->urpwindow,dp->urpwindow,2));
.
870a
}
.
869c
if(waserror()){
print("dkmesg: error\n");
.
559d
502c
sprint(buf, "csc.%s.%d", dp->name, dp->ncsc);
.
483a
DPRINT("dkmuxconfig: ncsc=%d, lines=%d, restart=%d, name=\"%s\"\n",
dp->ncsc, dp->lines, dp->restart, dp->name);
.
464a
case 5:
dp->urpwindow = strtoul(fields[4], 0, 0);
.
463a
dp->urpwindow = WS_2K;
.
462c
n = getfields((char *)bp->rptr, fields, 5, ' ');
.
448c
char *fields[5];
.
440c
* the name of the dk (default==dk)
* the urp window size (default==WS_2K)
.
435c
* configure a datakit multiplexor. this takes 5 arguments separated
.
416,423c
bp = padb(bp, 2);
.
398c
* add a 2 byte channel number to the start of each message,
* low order byte first.
.
126a
int urpwindow;
.
11a
#define NOW (MACHP(0)->ticks)
.
9,10c
#define DPRINT if(0) /*kprint*/
.
## diffname port/devdk.c 1990/0925
## diff -e /n/bootesdump/1990/0911/sys/src/9/mips/devdk.c /n/bootesdump/1990/0925/sys/src/9/mips/devdk.c
1115d
1105d
1103d
## diffname port/devdk.c 1990/1004
## diff -e /n/bootesdump/1990/0925/sys/src/9/mips/devdk.c /n/bootesdump/1990/1004/sys/src/9/mips/devdk.c
1317,1326d
501a
* tell datakit we've rebooted. It should close all channels.
*/
if(dp->restart) {
DPRINT("dkmuxconfig: restart %s\n", dp->name);
dkmesg(dp, T_ALIVE, D_RESTART, 0, 0);
}
/*
.
## diffname port/devdk.c 1990/1011
## diff -e /n/bootesdump/1990/1004/sys/src/9/mips/devdk.c /n/bootesdump/1990/1011/sys/src/9/mips/devdk.c
424c
/* print("dk wq full\n");/**/
.
## diffname port/devdk.c 1990/1018
## diff -e /n/bootesdump/1990/1011/sys/src/9/mips/devdk.c /n/bootesdump/1990/1018/sys/src/9/mips/devdk.c
423,427c
FLOWCTL(dp->wq);
PUTNEXT(dp->wq, bp);
.
121c
char name[64]; /* dk name */
.
## diffname port/devdk.c 1990/1022
## diff -e /n/bootesdump/1990/1018/sys/src/9/mips/devdk.c /n/bootesdump/1990/1022/sys/src/9/mips/devdk.c
1506c
for (i=dp->ncsc+1; i<dp->lines; i++){
.
1423a
case D_CLOSEALL:
for(line = dp->ncsc+1; line < dp->lines; line++){
lp = &dp->line[line];
switch (lp->state) {
case Ldialing:
/* simulate a failed connection */
dkreplymesg(dp, (Dkmsg *)0, line);
lp->state = Lrclose;
break;
case Lrclose:
case Lconnected:
case Llistening:
case Lackwait:
dkhangup(lp);
lp->state = Lrclose;
break;
case Lopened:
break;
case Llclose:
case Lclosed:
lp->state = Lclosed;
break;
}
}
break;
.
1409a
if (line <= 0 || line >= dp->lines) {
/* tell controller this line is not in use */
dkmesg(dp, T_CHG, D_CLOSE, line, 0);
return;
}
lp = &dp->line[line];
.
1379a
if (line <= 0 || line >= dp->lines) {
/* tell controller this line is not in use */
dkmesg(dp, T_CHG, D_CLOSE, line, 0);
return;
}
lp = &dp->line[line];
.
1371,1376d
224a
for(lp = dp->line; lp < &dp->line[Nline]; lp++)
if(lp->state != 0)
panic("dkmuxopen l %d s %lux", lp-dp->line, lp->state);
.
208a
Line *lp;
.
## diffname port/devdk.c 1990/1024
## diff -e /n/bootesdump/1990/1022/sys/src/9/mips/devdk.c /n/bootesdump/1990/1024/sys/src/9/mips/devdk.c
226,228d
209d
## diffname port/devdk.c 1990/1101
## diff -e /n/bootesdump/1990/1024/sys/src/9/mips/devdk.c /n/bootesdump/1990/1101/sys/src/9/mips/devdk.c
1557c
tsleep(&dp->timer, return0, 0, 7500);
.
1548,1554c
dkreplymesg(dp, (Dkmsg *)0, i);
break;
.
1538,1546c
case Ldialing:
if(lp->calltolive==0 || --lp->calltolive!=0)
.
1533,1536c
/*
* remind controller of dead lines and
* timeout calls that take to long
*/
for (i=dp->ncsc+1; i<dp->lines; i++){
lp = &dp->line[i];
switch(lp->state){
case Llclose:
dkmesg(c, T_CHG, D_CLOSE, i, 0);
break;
.
1528,1531c
dkmesg(c, T_ALIVE, D_CONTINUE, 0, 0);
.
1526c
* send keep alive
.
1524a
if(dp->opened==0)
error(0, Ehungup);
.
1523a
case Ldialing:
dkreplymesg(dp, (Dkmsg *)0, i);
break;
}
}
if(c)
close(c);
return;
}
/*
* open csc
*/
dp = (Dk *)a;
c = dkopenline(dp, dp->ncsc);
.
1521,1522c
c = 0;
if(waserror()){
/*
* hang up any calls waiting for the dk
*/
for (i=dp->ncsc+1; i<dp->lines; i++){
lp = &dp->line[i];
switch(lp->state){
case Llclose:
lp->state = Lclosed;
break;
.
1519a
Chan *c;
.
1508,1513d
1506c
* send a I'm alive message every 7.5 seconds and remind the dk of
* any closed channels it hasn't acknowledged.
.
1446a
dkhangup(lp);
.
1445d
1430a
/*
* datakit wants us to close all lines
*/
.
1412c
dkmesg(c, T_CHG, D_CLOSE, line, 0);
.
1403c
dkmesg(c, T_CHG, D_CLOSE, line, 0);
.
1397c
dkmesg(c, T_CHG, D_CLOSE, line, 0);
.
1376c
dkmesg(c, T_CHG, D_CLOSE, line, 0);
.
1367c
dkchgmesg(Chan *c, Dk *dp, Dkmsg *dialp, int line)
.
1353d
1349,1351c
if(line >=0 && line<dp->lines)
.
1337c
dkchgmesg(dp->csc, dp, &d, line);
.
1328a
if(n == 0)
error(0, Ehungup);
.
1322a
if(waserror()){
close(dp->csc);
return;
}
.
1321c
dp = a;
.
1319d
1095,1096d
1090c
dc = dkopenline(dp, STREAMID(c->qid));
.
988c
csc = dkopenline(dp, dp->ncsc);
dkmesg(csc, t_val, d_val, line, W_WINDOW(dp->urpwindow,dp->urpwindow,2));
close(csc);
csc = 0;
.
980a
/*
* open the data file
*/
dc = dkopenline(dp, line);
.
978,979d
975c
if(csc)
close(csc);
if(dc)
close(dc);
.
973c
dc = 0;
csc = 0;
.
971c
* close temporary channels on error
.
918c
.
916a
Chan *csc;
.
891c
streamwrite(c, (char *)&d, sizeof(Dkmsg), 1);
.
873,874d
871d
868c
dkmesg(Chan *c, int type, int srv, int p0, int p1)
.
864a
* open the common signalling channel
*/
static Chan*
dkopenline(Dk *dp, int line)
{
Chan *c;
c = 0;
if(waserror()){
if(c)
close(c);
nexterror();
}
c = dkattach(dp->name);
c->qid = STREAMQID(line, Sdataqid);
dkopen(c, ORDWR);
poperror();
return c;
}
/*
.
754,758d
749,751d
701d
698a
lp->state = Lopened;
qunlock(lp);
.
685d
681a
dp = &dk[c->dev];
.
629,634d
610,620c
dp = dkalloc(spec);
/*
* return the new channel
*/
.
516,519c
sprint(buf, "timer.%s.%d", dp->name, dp->ncsc);
kproc(buf, dktimer, dp);
.
514c
* start a keepalive process
.
511d
507c
* start a process to listen to csc messages
.
502,503c
DPRINT("dktimer: restart %s\n", dp->name);
dkmesg(dp->csc, T_ALIVE, D_RESTART, 0, 0);
.
499a
* do this here to get it done before trying to open a channel.
.
498a
* open csc here so that boot, dktimer, and dkcsckproc aren't
* all fighting for it at once.
*/
dp->csc = dkopenline(dp, dp->ncsc);
/*
.
493,496c
dp->ncsc = ncsc;
dp->lines = lines;
dp->restart = restart;
dp->urpwindow = window;
dp->s = RD(q)->ptr;
q->ptr = q->other->ptr = dp;
dp->opened = 1;
dp->wq = WR(q);
unlock(dp);
.
487,491c
dp = dkalloc(name);
lock(dp);
if(dp->opened){
unlock(dp);
error(0, Ebadarg);
.
485c
* set up
.
480,482d
477,478c
if(ncsc <= 0 || lines <= ncsc)
.
470c
ncsc = strtoul(fields[0], 0, 0);
.
468c
lines = strtoul(fields[1], 0, 0);
.
466c
restart = 0;
.
463c
strncpy(name, fields[3], sizeof(name));
.
461c
window = strtoul(fields[4], 0, 0);
.
457,458d
455d
452a
* defaults
*/
ncsc = 1;
restart = 1;
lines = 16;
window = WS_2K;
strcpy(name, "dk");
/*
.
449c
error(0, Egreg);
.
447c
if(WR(q)->ptr){
.
445c
char name[NAMELEN];
int lines;
int ncsc;
int restart;
int window;
.
441c
Dk *dp;
.
439c
dkmuxconfig(Queue *q, Block *bp)
.
382a
out:
.
381a
poperror();
close(c);
.
378,380d
375c
dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0);
.
370c
dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0);
.
365c
dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0);
.
360c
dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0);
.
358a
c = 0;
if(waserror()){
lp->state = Lclosed;
if(c)
close(c);
goto out;
}
c = dkopenline(dp, dp->ncsc);
/*
* shake hands with dk
*/
switch(lp->state){
.
357c
case Lopened:
lp->state = Lclosed;
goto out;
}
.
353a
if(lp->rq == 0){
lp->state = Lclosed;
return;
}
/*
* decrement ref count on mux'd line
*/
streamexit(dp->s, 0);
/*
* these states don't need the datakit
*/
.
352c
* if we never got going, we're done
.
346a
Chan *c;
.
336a
lp->rq = q;
.
334,335c
lock(dp);
if(dp->opened==0 || streamenter(dp->s)<0){
unlock(dp);
error(0, Ehungup);
}
unlock(dp);
if(lp->state==Lclosed)
.
283a
/*
* not configured yet
*/
if(q->other->ptr == 0){
freeb(bp);
return;
}
.
275c
* work.
.
259c
dkmuxconfig(q, bp);
.
254,256d
240,245c
dp = WR(q)->ptr;
if(dp == 0)
return;
/*
* disallow new dkstopens() on this line.
* the lock syncs with dkstopen().
*/
lock(dp);
dp->opened = 0;
unlock(dp);
/*
* hang up all datakit connections
*/
for(i=dp->ncsc; i < dp->lines; i++)
dkhangup(&dp->line[i]);
/*
* wakeup the timer so it can die
*/
wakeup(&dp->timer);
.
238a
int i;
.
232a
* a new dkmux. find a free dk structure and assign it to this queue.
* when we get though here dp->s is meaningful and the name is set to "/".
*/
static void
dkmuxopen(Queue *q, Stream *s)
{
RD(q)->ptr = s;
WR(q)->ptr = 0;
}
/*
.
229c
if(freep == 0){
unlock(&dklock);
error(0, Enoifc);
}
dp = freep;
dp->opened = 0;
dp->s = 0;
dp->ncsc = 1;
strncpy(dp->name, name, sizeof(freep->name));
unlock(&dklock);
return dp;
.
227a
if(dp->name[0] == 0)
freep = dp;
.
212,226c
if(strcmp(name, dp->name) == 0){
unlock(&dklock);
return dp;
.
210a
lock(&dklock);
freep = 0;
.
209c
Dk *freep;
.
203,206c
* Look for a dk struct with a name. If none exists, create one.
*/
static Dk *
dkalloc(char *name)
.
191a
static void dkhangup(Line*);
.
189c
static void dkchgmesg(Chan*, Dk*, Dkmsg*, int);
.
181,182c
static void dkmuxconfig(Queue*, Block*);
static Chan* dkopenline(Dk*, int);
static int dkmesg(Chan*, int, int, int, int);
.
130a
static Lock dklock;
.
128a
Rendez timer;
.
125c
Chan *csc;
.
122a
Stream *s;
.
119,120c
Lock;
int opened;
.
## diffname port/devdk.c 1990/1104
## diff -e /n/bootesdump/1990/1101/sys/src/9/mips/devdk.c /n/bootesdump/1990/1104/sys/src/9/mips/devdk.c
382d
379a
lp->rq = q;
.
## diffname port/devdk.c 1990/1113
## diff -e /n/bootesdump/1990/1104/sys/src/9/mips/devdk.c /n/bootesdump/1990/1113/sys/src/9/mips/devdk.c
360c
Qinfo dkinfo =
{
dkiput,
dkoput,
dkstopen,
dkstclose,
"dk"
};
.
205c
Qinfo dkmuxinfo =
{
dkmuxiput,
dkmuxoput,
dkmuxopen,
dkmuxclose,
"dkmux"
};
.
## diffname port/devdk.c 1990/11161
## diff -e /n/bootesdump/1990/1113/sys/src/9/mips/devdk.c /n/bootesdump/1990/11161/sys/src/9/mips/devdk.c
1670a
DPRINT("keep alive\n");
.
9c
#define DPRINT if(0) print
.
## diffname port/devdk.c 1990/11211
## diff -e /n/bootesdump/1990/11161/sys/src/9/mips/devdk.c /n/bootesdump/1990/11211/sys/src/9/mips/devdk.c
1666c
error(Ehungup);
.
1447c
error(Ehungup);
.
1398c
lp = &dk[c->dev].line[STREAMID(c->qid.path)];
.
1375c
dc->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid);
.
1335c
error(Ebadarg);
.
1231c
error(Eio);
.
1221c
error(Eio);
.
1205c
dc = dkopenline(dp, STREAMID(c->qid.path));
.
1147c
error(dkerr[lp->err]);
.
1145c
error(dkerr[0]);
.
1112c
error(Ebadarg);
.
1045c
error(Ebadarg);
.
1043c
error(Ebadarg);
.
1033c
error(Ebadarg);
.
1025c
line = STREAMID(c->qid.path);
.
965c
c->qid.path = STREAMQID(line, Sdataqid);
.
936,949d
933c
error(Eperm);
.
927c
error(Eperm);
.
921c
error(Eperm);
.
914c
error(Ebadarg);
.
910c
error(Ebadarg);
.
906c
error(Ebadarg);
.
902c
error(Ebadarg);
.
898c
error(Ebadarg);
.
882c
t = STREAMTYPE(c->qid.path);
.
871c
error(Eperm);
.
862,863c
lp = &dk[c->dev].line[STREAMID(c->qid.path)];
switch(STREAMTYPE(c->qid.path)){
.
855,856c
if(c->qid.path & CHDIR){
if(c->qid.path == CHDIR)
.
837c
error(Eperm);
.
816c
error(Ebadarg);
.
803c
c->qid.path = STREAMQID(line, Sctlqid);
.
791c
error(Enodev);
.
786c
c->qid.path = STREAMQID(lp-dp->line, Sctlqid);
.
772,773c
error(Ebadarg);
} else switch(STREAMTYPE(c->qid.path)){
.
767c
if(c->qid.path & CHDIR){
.
743c
if(c->qid.path == CHDIR)
.
734c
if(c->qid.path == CHDIR)
.
699c
dkdir[0].qid.path = Dcloneqid;
dkdir[0].qid.vers = 0;
.
690c
dkdir[i].qid.path = CHDIR|STREAMQID(i, Dlineqid);
dkdir[i].qid.vers = 0;
.
656,660c
"addr", {Daddrqid}, 0, 0600,
"listen", {Dlistenqid}, 0, 0600,
"other", {Dotherqid}, 0, 0600,
"raddr", {Draddrqid}, 0, 0600,
"ruser", {Duserqid}, 0, 0600,
.
587c
error(Ebadarg);
.
578c
error(Ebadarg);
.
574c
error(Ebadarg);
.
543c
error(Egreg);
.
502c
error(Ebadarg);
.
391c
error(Ehungup);
.
235c
error(Enoifc);
.
## diffname port/devdk.c 1990/1126
## diff -e /n/bootesdump/1990/11211/sys/src/9/mips/devdk.c /n/bootesdump/1990/1126/sys/src/9/mips/devdk.c
779c
* get an unused device and open its control file
.
746a
else if(c->qid.path == Dcloneqid)
devstat(c, dp, dkdir, 1, devgen);
.
## diffname port/devdk.c 1990/1202
## diff -e /n/bootesdump/1990/1126/sys/src/9/mips/devdk.c /n/bootesdump/1990/1202/sys/src/9/mips/devdk.c
1566a
dp->allclosedp = 1;
wakeup(&dp->rallclosed);
.
624a
/*
* wait for closeall in response to D_RESTART
*/
if(dp->restart)
tsleep(&dp->rallclosed, allclosed, dp, 10000);
.
615,620d
605a
* start a process to listen to csc messages
*/
sprint(buf, "csc.%s.%d", dp->name, dp->ncsc);
kproc(buf, dkcsckproc, dp);
/*
* wait for first possible closeall (may not come)
*/
tsleep(&dp->rallclosed, allclosed, dp, 2000);
/*
.
527a
static int
allclosed(void *arg)
{
Dk *dp;
dp = arg;
return dp->allclosedp;
}
.
130a
Rendez rallclosed;
int allclosedp; /* true once a closeall has been seen */
.
## diffname port/devdk.c 1990/1210
## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/devdk.c /n/bootesdump/1990/1210/sys/src/9/port/devdk.c
1588,1589c
dp->closeall = 1;
wakeup(&dp->closeallr);
.
640,645d
632a
tsleep(&dp->closeallr, haveca, dp, 5000); /* wait for restart closeall */
.
631a
dp->closeall = 0;
.
622,626d
619a
tsleep(&dp->closeallr, haveca, dp, 5000); /* wait for initial closeall */
.
612a
dp->closeall = 0;
.
536c
return dp->closeall;
.
531c
haveca(void *arg)
.
131,132c
int closeall; /* set when we receive a closeall message */
Rendez closeallr; /* wait here for a closeall */
.
## diffname port/devdk.c 1990/1214
## diff -e /n/bootesdump/1990/1210/sys/src/9/port/devdk.c /n/bootesdump/1990/1214/sys/src/9/port/devdk.c
1667d
1641a
dp = (Dk *)a;
.
1107d
1105a
poperror();
.
1104a
if(waserror()){
close(csc);
nexterror();
}
.
1092,1096d
1086,1089c
close(dc);
.
1083,1084c
dc = dkopenline(dp, line);
.
1081c
* open the data file
.
1077a
default:
t_val = 0;
d_val = 0;
panic("bad dial type");
.
## diffname port/devdk.c 1991/0411
## diff -e /n/bootesdump/1990/1214/sys/src/9/port/devdk.c /n/bootesdump/1991/0411/sys/src/9/port/devdk.c
893c
dkwrite(Chan *c, void *a, long n, ulong offset)
.
887c
return stringread(c, a, n, lp->ruser, offset);
.
885c
return stringread(c, a, n, lp->raddr, offset);
.
883c
return stringread(c, a, n, lp->addr, offset);
.
866c
dkread(Chan *c, void *a, long n, ulong offset)
.
## diffname port/devdk.c 1991/0419
## diff -e /n/bootesdump/1991/0411/sys/src/9/port/devdk.c /n/bootesdump/1991/0419/sys/src/9/port/devdk.c
755a
Chan*
dkclwalk(Chan *c, char *name)
{
return devclwalk(c, name);
}
.
## diffname port/devdk.c 1991/0427
## diff -e /n/bootesdump/1991/0419/sys/src/9/port/devdk.c /n/bootesdump/1991/0427/sys/src/9/port/devdk.c
756,761d
## diffname port/devdk.c 1991/0706
## diff -e /n/bootesdump/1991/0427/sys/src/9/port/devdk.c /n/bootesdump/1991/0706/sys/src/9/port/devdk.c
1476c
print("unrecognized csc message %o.%o(%o)\n",
d.type, d.srv, line);
.
770c
* its ctl file.
.
## diffname port/devdk.c 1991/0723
## diff -e /n/bootesdump/1991/0706/sys/src/9/port/devdk.c /n/bootesdump/1991/0723/sys/src/9/port/devdk.c
1467c
/* print("dksrvmesg(%d)\n", line); /**/
.
## diffname port/devdk.c 1991/0828
## diff -e /n/bootesdump/1991/0723/sys/src/9/port/devdk.c /n/bootesdump/1991/0828/sys/src/9/port/devdk.c
1472c
dp->lines = line+1;
.
## diffname port/devdk.c 1991/1105
## diff -e /n/bootesdump/1991/0828/sys/src/9/port/devdk.c /n/bootesdump/1991/1105/sys/src/9/port/devdk.c
1062c
strcat(dialstr, u->p->user);
.
1048c
if(strlen(addr)+strlen(u->p->user)+2 >= sizeof(dialstr))
.
## diffname port/devdk.c 1991/1107
## diff -e /n/bootesdump/1991/1105/sys/src/9/port/devdk.c /n/bootesdump/1991/1107/sys/src/9/port/devdk.c
1685c
lp = dp->linep[i];
.
1661a
freeb(dp->alloc);
.
1649c
lp = dp->linep[i];
.
1604c
lp = dp->linep[line];
.
1555c
lp = dp->linep[line];
.
1535c
lp = dp->linep[line];
.
1499c
lp = dp->linep[line];
.
1401c
lp = dk[c->dev].linep[STREAMID(c->qid.path)];
.
1368c
lp = dp->linep[line];
.
1341,1343c
DPRINT("src(%s)user(%s)dest(%s)w(%d)\n", lp->raddr, lp->ruser,
lp->addr, W_TRAF(lp->window));
.
1275c
lp = dp->linep[lineno];
.
1031c
lp = dp->linep[line];
.
880c
lp = dk[c->dev].linep[STREAMID(c->qid.path)];
.
829d
810,811d
808c
if(line == dp->lines)
.
804c
c->qid.path = STREAMQID(line, Sctlqid);
lp->state = Lopened;
qunlock(lp);
.
797,798c
for(line = dp->ncsc+1; line < dp->lines; line++){
lp = dp->linep[line];
.
781c
Line *lp;
.
731c
dp = dkalloc(spec, 0, 0);
.
683a
dk = (Dk*)ialloc(conf.dkif*sizeof(Dk), 0);
.
672d
652d
599,600d
593c
dp = dkalloc(name, ncsc, lines);
.
509c
line = lp->lineno;
.
467c
dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0);
.
462c
dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0);
.
457c
dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0);
.
452c
dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0);
.
388c
q->other->ptr = q->ptr = lp = dp->linep[s->id];
.
347c
lp = dp->linep[line];
.
284c
dkhangup(dp->linep[i]);
.
243a
/*
* allocate memory for line structures
*/
n = sizeof(Line*)*dp->lines;
bp = allocb(n);
if(bp->lim - bp->base < n){
unlock(&dklock);
errors("too many lines");
}
dp->linep = (Line **)bp->base;
bp->wptr += n;
dp->alloc = bp;
for(i = 0; i < n; i++){
if(bp->lim - bp->wptr < sizeof(Line)){
bp = allocb(sizeof(Line)*n);
bp->next = dp->alloc;
dp->alloc = bp;
}
dp->linep[i] = (Line*)bp->wptr;
dp->linep[i]->lineno = i;
bp->wptr += sizeof(Line);
}
.
242c
dp->ncsc = ncsc;
dp->lines = lines;
.
238a
if(lines == 0)
errors("unknown dk interface");
/*
* init the structures
*/
.
227c
for(dp = dk; dp < &dk[conf.dkif]; dp++){
.
223a
Block *bp;
int i, n;
.
220c
dkalloc(char *name, int ncsc, int lines)
.
134c
static Dk *dk;
.
132a
Block *alloc;
.
127c
Line **linep;
.
110d
99a
int lineno;
.
15,19d
## diffname port/devdk.c 1991/1108
## diff -e /n/bootesdump/1991/1107/sys/src/9/port/devdk.c /n/bootesdump/1991/1108/sys/src/9/port/devdk.c
1480c
DPRINT("t(%d)s(%d)l(%d)\n", d.type, d.srv, line);
.
1466a
DPRINT("dkcsckproc: %d\n", dp->ncsc);
.
1002a
* return the contents of the info files
*/
void
dkfilladdr(Chan *c, char *buf, int len)
{
strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->addr, len);
}
void
dkfillraddr(Chan *c, char *buf, int len)
{
strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->raddr, len);
}
void
dkfillruser(Chan *c, char *buf, int len)
{
strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->ruser, len);
}
/*
.
980a
* return the number of an unused line (reserve it)
*/
static int
dkcloneline(Chan *c)
{
Line *lp;
Dk *dp;
int line;
dp = &dk[c->dev];
/*
* get an unused device and open its control file
*/
for(line = dp->ncsc+1; line < dp->lines; line++){
lp = dp->linep[line];
if(lp->state == Lclosed && canqlock(lp)){
if(lp->state != Lclosed){
qunlock(lp);
continue;
}
lp->state = Lopened;
qunlock(lp);
return lp->lineno;
}
}
error(Enodev);
}
/*
.
894,915c
return netread(c, a, n, offset, &dk[c->dev].net);
.
806,875c
return netopen(c, omode, &dk[c->dev].net);
.
794,802d
786,791c
netstat(c, dp, &dk[c->dev].net);
.
777,780c
return netwalk(c, name, &dk[c->dev].net);
.
721,744d
714,717d
669,706d
273c
/*
* fill in the network structure
*/
dp->net.name = dp->name;
dp->net.nconv = dp->lines+1;
dp->net.devp = &dkinfo;
dp->net.protop = &urpinfo;
dp->net.listen = dklisten;
dp->net.clone = dkcloneline;
dp->net.ninfo = 3;
dp->net.info[0].name = "addr";
dp->net.info[0].fill = dkfilladdr;
dp->net.info[1].name = "raddr";
dp->net.info[1].fill = dkfillraddr;
dp->net.info[2].name = "ruser";
dp->net.info[2].fill = dkfillruser;
.
271a
n -= sizeof(Line);
.
265a
memset(bp->base, 0, bp->lim-bp->base);
.
263c
n = sizeof(Line)*(dp->lines);
for(i = 1; i <= dp->lines; i++){
.
259a
memset(bp->base, 0, bp->lim-bp->base);
.
254c
n = sizeof(Line*)*(dp->lines+1);
.
239a
}
.
238c
if(lines == 0){
unlock(&dklock);
.
222a
Line *lp;
.
197a
* for standard network interface (net.c)
*/
static int dkcloneline(Chan*);
static int dklisten(Chan*);
static void dkfilladdr(Chan*, char*, int);
static void dkfillraddr(Chan*, char*, int);
static void dkfillruser(Chan*, char*, int);
extern Qinfo dkinfo;
/*
.
187d
127a
Network net;
.
13,21d
## diffname port/devdk.c 1991/1114
## diff -e /n/bootesdump/1991/1108/sys/src/9/port/devdk.c /n/bootesdump/1991/1114/sys/src/9/port/devdk.c
270c
for(i = 0; i <= dp->lines; i++){
.
## diffname port/devdk.c 1991/1115
## diff -e /n/bootesdump/1991/1114/sys/src/9/port/devdk.c /n/bootesdump/1991/1115/sys/src/9/port/devdk.c
1272a
/* listener becomes owner */
netown(&dp->net, lp->lineno, dp->prot[from].owner, 0);
.
1130a
from = STREAMID(c->qid.path);
.
1127a
int from;
.
854a
/* current user becomes owner */
netown(&dp->net, lp->lineno, u->p->user, 0);
.
830c
netwstat(c, dp, &dk[c->dev].net);
.
698a
for(i = 0; i < conf.dkif; i++)
dk[i].prot = (Netprot*)ialloc(conf.nurp*sizeof(Netprot), 0);
.
697a
int i;
.
532a
netdisown(&dp->net, lp->lineno);
.
291a
dp->net.prot = dp->prot;
.
287c
dp->net.nconv = dp->lines;
.
270c
for(i = 0; i < dp->lines; i++){
.
259c
n = sizeof(Line*)*(dp->lines);
.
119a
Netprot *prot;
.
16a
enum {
Maxlines = 256,
};
.
## diffname port/devdk.c 1991/1116
## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devdk.c /n/bootesdump/1991/1116/sys/src/9/port/devdk.c
1613,1616c
c = dkopencsc(dp);
.
1040c
csc = dkopencsc(dp);
.
898a
* open the common signalling channel
*/
static Chan*
dkopencsc(Dk *dp)
{
qlock(dp);
if(dp->csc == 0)
dp->csc = dkopenline(dp, dp->ncsc);
else
incref(dp->csc);
qunlock(dp);
return dp->csc;
}
/*
.
876,878d
675c
dkopencsc(dp);
.
540a
if(lp->lineno == dp->ncsc)
dp->csc = 0;
netdisown(&dp->net, lp->lineno);
.
539d
507c
c = dkopencsc(dp);
.
181a
static Chan* dkopencsc(Dk*);
.
126c
Block *alloc; /* blocks containing Line structs */
.
116c
int lines; /* number of lines */
.
114d
110a
.
108a
QLock;
Chan *csc;
.
## diffname port/devdk.c 1991/1120
## diff -e /n/bootesdump/1991/1116/sys/src/9/port/devdk.c /n/bootesdump/1991/1120/sys/src/9/port/devdk.c
1628d
547a
lock(dp);
dp->ref--;
if(dp->ref == 0)
freeb(dp->alloc);
unlock(dp);
.
456a
dp->ref++;
.
336a
dp->name[0] = 0;
.
243c
if(dp->name[0] == 0 && dp->ref == 0)
.
112a
int ref;
.
## diffname port/devdk.c 1991/1122
## diff -e /n/bootesdump/1991/1120/sys/src/9/port/devdk.c /n/bootesdump/1991/1122/sys/src/9/port/devdk.c
309a
dp->net.info[3].name = "stats";
dp->net.info[3].fill = urpfillstats;
.
303c
dp->net.ninfo = 4;
.
## diffname port/devdk.c 1991/1206
## diff -e /n/bootesdump/1991/1122/sys/src/9/port/devdk.c /n/bootesdump/1991/1206/sys/src/9/port/devdk.c
1121c
errors(dkerr[lp->err]);
.
1119c
errors(dkerr[0]);
.
840c
for(m = 0; m < DKERRS-1; m++)
if(strcmp(field[2], dkerr[m]) == 0)
break;
dkanswer(c, strtoul(field[1], 0, 0), m);
.
173c
#define DKERRS sizeof(dkerr)/sizeof(char*)
.
163,171c
char* dkerr[]={
[DKok]"",
[DKbusy]"host overloaded",
[DKnetotl]"network not answering",
[DKdestotl]"host not answering",
[DKbadnet]"unknown address",
[DKnetbusy]"network overloaded",
[DKinuse]"server in use",
[DKreject]"connection refused",
.
151c
* map datakit error to errno
.
85,87d
## diffname port/devdk.c 1991/1214
## diff -e /n/bootesdump/1991/1206/sys/src/9/port/devdk.c /n/bootesdump/1991/1214/sys/src/9/port/devdk.c
851a
USED(c);
.
779a
USED(c);
.
## diffname port/devdk.c 1991/1228
## diff -e /n/bootesdump/1991/1214/sys/src/9/port/devdk.c /n/bootesdump/1991/1228/sys/src/9/port/devdk.c
166,167c
[DKnetbusy]"network busy",
[DKinuse]"service in use",
.
164c
[DKdestotl]"destination not answering",
.
162c
[DKbusy]"destination busy",
.
## diffname port/devdk.c 1992/0111
## diff -e /n/bootesdump/1991/1228/sys/src/9/port/devdk.c /n/bootesdump/1992/0111/sys/src/9/port/devdk.c
1123c
error(dkerr[lp->err]);
.
1121c
error(dkerr[0]);
.
270c
error(Ebadarg);
.
248,251d
244c
if(freep == 0 || lines == 0){
.
7c
#include "../port/error.h"
.
## diffname port/devdk.c 1992/0130
## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devdk.c /n/bootesdump/1992/0130/sys/src/9/port/devdk.c
813c
if(n > sizeof buf - 1)
n = sizeof buf - 1;
strncpy(buf, a, n);
buf[n] = '\0';
.
## diffname port/devdk.c 1992/0219
## diff -e /n/bootesdump/1992/0130/sys/src/9/port/devdk.c /n/bootesdump/1992/0219/sys/src/9/port/devdk.c
318a
s->opens++; /* Hold this queue in place */
s->inuse++;
.
## diffname port/devdk.c 1992/0221
## diff -e /n/bootesdump/1992/0219/sys/src/9/port/devdk.c /n/bootesdump/1992/0221/sys/src/9/port/devdk.c
1259c
if((dts++ % 1000) == 0)
print("dklisten: repeat timestamp %d\n", lineno);
.
1177a
static int dts;
.
## diffname port/devdk.c 1992/0223
## diff -e /n/bootesdump/1992/0221/sys/src/9/port/devdk.c /n/bootesdump/1992/0223/sys/src/9/port/devdk.c
325c
* close down a dkmux, this shouldn't happen
.
311,312c
* a new dkmux. hold the stream in place so it can never be closed down.
.
## diffname port/devdk.c 1992/0305
## diff -e /n/bootesdump/1992/0223/sys/src/9/port/devdk.c /n/bootesdump/1992/0305/sys/src/9/port/devdk.c
591,592c
FLOWCTL(dp->wq, bp);
.
109d
106a
Lock;
.
## diffname port/devdk.c 1992/0321
## diff -e /n/bootesdump/1992/0305/sys/src/9/port/devdk.c /n/bootesdump/1992/0321/sys/src/9/port/devdk.c
2c
#include "../port/lib.h"
.
## diffname port/devdk.c 1992/0409
## diff -e /n/bootesdump/1992/0321/sys/src/9/port/devdk.c /n/bootesdump/1992/0409/sys/src/9/port/devdk.c
1368a
/*
* set window size
*/
if(code == 0){
if(waserror()){
close(dc);
nexterror();
}
sprint(reply, "init %d %d", lp->window, Streamhi);
dc = dkopenline(dp, line);
dc->qid.path = STREAMQID(line, Sctlqid);
streamwrite(dc, reply, strlen(reply), 1);
close(dc);
poperror();
}
.
1154a
sprint(lp->other, "w=%d", lp->window);
.
947a
void
dkfillother(Chan *c, char *buf, int len)
{
strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->other, len);
}
.
547a
lp->window = 0;
.
304a
dp->net.info[4].name = "other";
dp->net.info[4].fill = dkfillother;
.
296c
dp->net.ninfo = 5;
.
202a
static void dkfillother(Chan*, char*, int);
.
97a
char other[32];
.
## diffname port/devdk.c 1992/0520
## diff -e /n/bootesdump/1992/0409/sys/src/9/port/devdk.c /n/bootesdump/1992/0520/sys/src/9/port/devdk.c
1344a
return -1; /* never reached */
.
898a
return -1; /* never reached */
.
852a
return -1; /* never reached */
.
## diffname port/devdk.c 1992/0601
## diff -e /n/bootesdump/1992/0520/sys/src/9/port/devdk.c /n/bootesdump/1992/0601/sys/src/9/port/devdk.c
163,169c
[DKbusy]"devdk: destination busy",
[DKnetotl]"devdk: network not answering",
[DKdestotl]"devdk: destination not answering",
[DKbadnet]"devdk: unknown address",
[DKnetbusy]"devdk: network busy",
[DKinuse]"devdk: service in use",
[DKreject]"devdk: connection refused",
.
## diffname port/devdk.c 1992/0622
## diff -e /n/bootesdump/1992/0601/sys/src/9/port/devdk.c /n/bootesdump/1992/0622/sys/src/9/port/devdk.c
725c
dk[i].prot = (Netprot*)xalloc(conf.nurp*sizeof(Netprot));
.
723c
dk = (Dk*)xalloc(conf.dkif*sizeof(Dk));
.
270,286d
264,268c
dp->linep = (Line **)xalloc(sizeof(Line*) * dp->lines);
if(dp->linep == 0)
error(Enomem);
lp = xalloc(dp->lines*sizeof(Line));
if(lp == 0)
error(Enomem);
for(i = 0; i < dp->lines; i++) {
lp->lineno = i;
dp->linep[i] = lp++;
.
232d
162,169c
[DKok] "",
[DKbusy] "devdk: destination busy",
[DKnetotl] "devdk: network not answering",
[DKdestotl] "devdk: destination not answering",
[DKbadnet] "devdk: unknown address",
[DKnetbusy] "devdk: network busy",
[DKinuse] "devdk: service in use",
[DKreject] "devdk: connection refused",
.
## diffname port/devdk.c 1992/0623
## diff -e /n/bootesdump/1992/0622/sys/src/9/port/devdk.c /n/bootesdump/1992/0623/sys/src/9/port/devdk.c
1679a
if(lp == 0)
continue;
.
1667a
for(;;){
.
1664,1666c
while(waserror());
.
1640,1661d
1601d
1598c
if(line < 0 || line >= dp->lines || (lp = dp->linep[line]) == 0)
.
1552a
if(lp == 0)
continue;
.
1532d
1527c
if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) {
.
1496d
1491c
if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) {
.
1397c
lp = linealloc(&dk[c->dev], STREAMID(c->qid.path), 1);
.
1348c
lp = linealloc(dp, line, 1);
.
1345a
Dk *dp;
.
1343d
1324c
netown(lp, dp->linep[from]->owner, 0);
.
1250c
lp = linealloc(dp, lineno, 1);
.
1002c
lp = linealloc(dp, line, 1);
.
919c
qunlock(&dp->csclock);
.
914c
Line *lp;
qlock(&dp->csclock);
.
884a
qunlock(&dp->netlock);
.
881c
qunlock(&dp->netlock);
.
879c
netown(lp, u->p->user, 0);
.
871,875c
if(lp == 0 || lp->state == Lclosed){
lp = linealloc(dp, line, 0);
.
868a
qlock(&dp->netlock);
.
762c
Dk *dp;
dp = &dk[c->dev];
linealloc(dp, STREAMID(c->qid.path), 1);
return netopen(c, omode, &dp->net);
.
709,711c
dk = (Dk*)xalloc(Maxdk*sizeof(Dk));
.
560c
* low order byte first. Make sure the first block contains
* both the 2 channel bytes and the control byte.
.
539,544d
537c
netdisown(lp);
.
479,483d
445,451d
402,403c
lp = linealloc(dp, line, 1);
if(lp && canqlock(lp)){
.
314,347d
300a
* allocate a line if it doesn't exist
*/
static Line*
linealloc(Dk *dp, int lineno, int dolock)
{
Line *lp;
if(dp->opened == 0)
error(Enoifc);
if(dolock)
qlock(&dp->netlock);
if(lineno > dp->lines)
panic("linealloc");
lp = dp->linep[lineno];
if(lp == 0){
lp = smalloc(sizeof(Line));
lp->lineno = lineno;
netadd(&dp->net, lp, lineno);
dp->linep[lineno] = lp;
}
if(dolock)
qunlock(&dp->netlock);
return lp;
}
/*
.
283d
263,272c
dp->linep = smalloc(sizeof(Line*) * dp->lines);
.
261c
* allocate memory for array of pointers to lines.
* line structures are allocated as needed.
.
250,252d
242c
if(dp->name[0] == 0)
.
237c
for(dp = dk; dp < &dk[Maxdk]; dp++){
.
227c
static Dk*
.
220c
0,
.
212d
125,128d
111c
Lock;
.
107,108c
QLock netlock;
Network net;
QLock csclock;
.
86a
Netprot; /* stat info */
.
18c
Maxdk = 4,
.
## diffname port/devdk.c 1992/0625
## diff -e /n/bootesdump/1992/0623/sys/src/9/port/devdk.c /n/bootesdump/1992/0625/sys/src/9/port/devdk.c
1495d
1491,1493c
if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0)
.
1362c
lp = linealloc(dk[c->dev], STREAMID(c->qid.path), 1);
.
1312c
dp = dk[c->dev];
.
1142c
dp = dk[c->dev];
.
966c
dp = dk[c->dev];
.
909c
strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->other, len);
.
904c
strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->ruser, len);
.
899c
strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->raddr, len);
.
894c
strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->addr, len);
.
882,883c
incref(dp->csc);
.
872c
* open the common signalling channel (dp->csc's reference count never goes below 1)
.
829c
dp = dk[c->dev];
.
816c
netwstat(c, dp, &dk[c->dev]->net);
.
746c
return netread(c, a, n, offset, &dk[c->dev]->net);
.
724c
dp = dk[c->dev];
.
716c
netstat(c, dp, &dk[c->dev]->net);
.
710c
return netwalk(c, name, &dk[c->dev]->net);
.
697c
c->dev = dev;
.
691c
for(dev = 0; dev < Maxdk; dev++){
dp = dk[dev];
if(dp && strcmp(dp->name, spec) == 0)
break;
}
if(dev == Maxdk)
error(Enoifc);
.
684a
int dev;
.
669,671d
657a
tsleep(&dp->closeallr, haveca, dp, 15000);
.
656d
646d
638d
632c
q->ptr = q->other->ptr = dp;
dk[n] = dp;
unlock(&dklock);
poperror();
.
628,630d
625a
for(n = 0; n < Maxdk; n++){
dp = dk[n];
if(dp == 0)
break;
if(strcmp(name, dp->name) == 0)
error(Einuse);
}
if(n == Maxdk)
error(Enoifc);
/*
* allocate both a dk structure and an array of pointers to line
* structures
*/
dp = smalloc(sizeof(Dk));
dp->ncsc = ncsc;
dp->lines = lines;
dp->linep = smalloc(sizeof(Line*) * dp->lines);
strcpy(dp->name, name);
dp->net.name = dp->name;
dp->net.nconv = dp->lines;
dp->net.devp = &dkinfo;
dp->net.protop = &urpinfo;
dp->net.listen = dklisten;
dp->net.clone = dkcloneline;
dp->net.ninfo = 5;
dp->net.info[0].name = "addr";
dp->net.info[0].fill = dkfilladdr;
dp->net.info[1].name = "raddr";
dp->net.info[1].fill = dkfillraddr;
dp->net.info[2].name = "ruser";
dp->net.info[2].fill = dkfillruser;
dp->net.info[3].name = "stats";
dp->net.info[3].fill = urpfillstats;
dp->net.info[4].name = "other";
dp->net.info[4].fill = dkfillother;
.
620,624c
lock(&dklock);
if(waserror()){
unlock(&dklock);
nexterror();
.
618c
* find a free dk slot. it name is already configured
* or no slots are left, error.
.
600a
name[sizeof(name)-1] = 0;
.
501,502d
420c
dp = dk[s->dev];
.
398,401c
static Streamopen dkstopen;
static Streamclose dkstclose;
static Streamput dkoput, dkiput;
.
321,322c
naildownstream(s);
.
318c
RD(q)->ptr = 0;
.
294,295d
223,286d
210,212c
static Streamopen dkmuxopen;
static Streamput dkmuxoput;
static Streamput dkmuxiput;
.
129,130c
Lock dklock;
Dk *dk[Maxdk];
.
122d
119d
114,116d
109c
Network net; /* stat info */
Line **linep; /* array of line structures */
.
107c
struct Dk
{
.
## diffname port/devdk.c 1992/0711
## diff -e /n/bootesdump/1992/0625/sys/src/9/port/devdk.c /n/bootesdump/1992/0711/sys/src/9/port/devdk.c
1560c
int i;
.
1520d
1324d
843,844d
722a
USED(offset);
.
698a
USED(name);
USED(omode);
USED(perm);
.
## diffname port/devdk.c 1992/0717
## diff -e /n/bootesdump/1992/0711/sys/src/9/port/devdk.c /n/bootesdump/1992/0717/sys/src/9/port/devdk.c
1218a
if(cp = strchr(lp->addr, '.')){
*cp = '!';
if(cp = strchr(cp, '.'))
*cp = 0;
}
.
1216c
* Special characters are escaped by '\'s. Convert to
* a plan 9 address, i.e. system!service.
.
1107a
char *cp;
.
1085d
876c
Dk *dp;
Line *lp;
int line;
char lbuf[65];
line = STREAMID(c->qid.path);
dp = dk[c->dev];
lp = linealloc(dp, line, 1);
sprint(lbuf, "%s/%d %d %s window %d\n", dp->name, line,
lp->state != Lclosed ? 1 : 0, dkstate[lp->state], lp->window);
strncpy(buf, lbuf, len);
.
874c
dkfillstatus(Chan *c, char *buf, int len)
.
871c
if(len < sizeof(dk[0]->linep[0]->ruser)+2)
error(Ebadarg);
sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->ruser);
.
866c
if(len < sizeof(dk[0]->linep[0]->raddr)+2)
error(Ebadarg);
sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->raddr);
.
861c
if(len < sizeof(dk[0]->linep[0]->addr)+2)
error(Ebadarg);
sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->addr);
.
588,589c
dp->net.info[4].name = "status";
dp->net.info[4].fill = dkfillstatus;
.
586c
dp->net.info[3].name = "urpstats";
.
582c
dp->net.info[1].name = "remote";
.
580c
dp->net.info[0].name = "local";
.
200c
static void dkfillstatus(Chan*, char*, int);
.
142a
char *dkstate[] =
{
[Lclosed] "Closed",
[Lopened] "Opened",
[Lconnected] "Established",
[Lrclose] "Rclose",
[Llclose] "Lclose",
[Ldialing] "Dialing",
[Llistening] "Listen",
[Lackwait] "Ackwait",
[Laccepting] "Accepting",
};
.
99d
## diffname port/devdk.c 1992/1030
## diff -e /n/bootesdump/1992/0717/sys/src/9/port/devdk.c /n/bootesdump/1992/1030/sys/src/9/port/devdk.c
1034c
for(win = 0; ; win++)
if(W_VALUE(win) >= dp->urpwindow || win == 15)
break;
dkmesg(csc, t_val, d_val, line, W_WINDOW(win, win, 2));
.
950c
int line, win;
.
## diffname port/devdk.c 1992/1031
## diff -e /n/bootesdump/1992/1030/sys/src/9/port/devdk.c /n/bootesdump/1992/1031/sys/src/9/port/devdk.c
536a
if(window < 16)
window = 1<<(window+4);
.
527c
window = 2048;
.
491c
* the urp window size (default==2048)
.
83d
## diffname port/devdk.c 1993/0501
## diff -e /n/bootesdump/1992/1031/sys/src/9/port/devdk.c /n/fornaxdump/1993/0501/sys/src/brazil/port/devdk.c
993c
strcat(dialstr, up->user);
.
979c
if(strlen(addr)+strlen(up->user)+2 >= sizeof(dialstr))
.
823c
netown(lp, up->user, 0);
.
## diffname port/devdk.c 1993/0804 # deleted
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/devdk.c /n/fornaxdump/1993/0804/sys/src/brazil/port/devdk.c
1,1636d
|