home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
142.lha
/
DNet
/
lib
/
dnetlib.c
< prev
Wrap
C/C++ Source or Header
|
1986-11-21
|
9KB
|
433 lines
/*
* DNETLIB.C
*
* DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
*
* Library Interface for DNET.
*/
#define NOEXT
#include "/dnet/dnet.h"
#define CHANN struct _CHANN
#define NAMELEN sizeof("DNET.PORT.XXXXX")
#define NAMEPAT "DNET.PORT.%ld"
CHANN {
PORT port; /* receive data, replies */
PORT *dnetport; /* dnet's master port */
LIST rdylist; /* ready to be read */
uword chan; /* channel # for open channels */
ubyte eof; /* channel remotely closed/eof */
ubyte filler;
int qlen; /* allowed write queue size */
int queued; /* current # packets queued */
};
static CHANN *MakeChannel();
PORT *
DListen(portnum)
uword portnum;
{
PORT *port = NULL;
char *ptr;
ptr = AllocMem(NAMELEN, MEMF_PUBLIC); /* memory the the name */
sprintf(ptr, NAMEPAT, portnum);
Forbid(); /* task-atomic operation */
if (FindPort(ptr) || !(port = CreatePort(ptr,0)))
FreeMem(ptr, NAMELEN);
Permit();
return(port);
}
void
DUnListen(lisport)
PORT *lisport;
{
if (lisport) {
register char *ptr = lisport->mp_Node.ln_Name;
Forbid(); /* task-atomic operation */
while (DNAAccept(lisport)); /* remove all pending requests */
DeletePort(lisport); /* gone! */
Permit();
FreeMem(ptr, NAMELEN);
}
}
/*
* DAccept()
*
* Note: This call will work even if called by a task which does not
* own the listen port.
*/
PORT *
DAccept(lisport)
PORT *lisport;
{
register IOR *ior;
register CHANN *chan = NULL;
while (!chan && (ior = GetMsg(lisport))) {
switch(ior->io_Command) {
case DNCMD_SOPEN:
chan = MakeChannel(ior, NULL);
break;
default:
ior->io_Error = 1;
break;
}
ReplyMsg(ior);
}
if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
return((PORT *)chan);
}
/*
* Refuse a connection
*/
DNAAccept(lisport)
PORT *lisport;
{
IOR *ior;
if (ior = GetMsg(lisport)) {
ior->io_Error = 1;
ReplyMsg(ior);
}
if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
return(ior != NULL);
}
DPri(chan, pri)
CHANN *chan;
{
}
PORT *
DOpen(host, portnum, txpri, rxpri)
char *host;
char txpri, rxpri;
uword portnum;
{
IOR ior;
CHANN *chan;
if (!host)
host = "0";
chan = MakeChannel(&ior, host);
if (rxpri > 126)
rxpri = 126;
if (rxpri < -127)
rxpri = -127;
if (txpri > 126)
txpri = 126;
if (txpri < -127)
txpri = -127;
if (chan->dnetport) {
ior.io_Command = DNCMD_OPEN;
ior.io_Unit = (void *)portnum;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = (PORT *)chan;
ior.io_Message.mn_Node.ln_Pri = txpri;
ior.io_Message.mn_Node.ln_Name= (char *)rxpri;
PutMsg(chan->dnetport, &ior);
WaitMsg(&ior);
if (ior.io_Error == 0) {
chan->chan = (long)ior.io_Unit;
FixSignal(chan);
return((PORT *)chan);
}
}
DeleteChannel(chan);
return(NULL);
}
DNRead(chan, buf, bytes)
CHANN *chan;
char *buf;
{
register IOR *ior;
int len = 0;
long n;
if (chan->eof)
return(-1);
while (bytes && ((ior = RemHead(&chan->rdylist)) || (ior = GetMsg(chan)))) {
if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
if (!chan->queued)
puts("DNRead: Software Error");
else
--chan->queued;
if (ior->io_Length)
FreeMem(ior->io_Data, ior->io_Length);
FreeMem(ior, sizeof(IOR));
continue;
}
switch(ior->io_Command) {
case DNCMD_CLOSE:
case DNCMD_EOF:
chan->eof = 1;
ReplyMsg(ior);
break;
case DNCMD_WRITE:
n = ior->io_Length - ior->io_Actual;
if (n <= bytes) {
CopyMem((char *)ior->io_Data + ior->io_Actual, buf, n);
bytes -= n;
len += n;
buf += n;
ReplyMsg(ior);
} else {
CopyMem((char *)ior->io_Data + ior->io_Actual, buf, bytes);
len += bytes;
ior->io_Actual += bytes;
bytes = 0;
Forbid(); /* DNET device is a task, no need to Disable() */
ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
AddHead(&chan->port.mp_MsgList, ior);
Permit();
}
break;
default:
ior->io_Error = 1;
ReplyMsg(ior);
}
}
FixSignal(chan);
if (chan->eof)
SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
return(len);
}
DRead(chan, buf, bytes)
char *buf;
CHANN *chan;
{
long len = 0;
long n;
if (chan->eof)
return(-1);
while (bytes) {
WaitPort(chan);
n = DNRead(chan, buf, bytes);
if (n < 0)
break;
len += n;
buf += n;
bytes -= n;
if (chan->eof)
break;
}
return(len);
}
DQueue(chan, n)
CHANN *chan;
{
chan->qlen = n;
}
DWrite(chan, buf, bytes)
CHANN *chan;
{
int error = bytes;
if (chan->qlen) {
if (WaitQueue(chan, NULL) >= 0) {
register IOR *ior = AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC);
ior->io_Command = DNCMD_WRITE;
ior->io_Unit = (void *)chan->chan;
ior->io_Offset = (long)chan;
ior->io_Message.mn_ReplyPort = (PORT *)chan;
ior->io_Data = AllocMem(bytes, MEMF_PUBLIC);
ior->io_Length = bytes;
CopyMem(buf, ior->io_Data, bytes);
PutMsg(chan->dnetport, ior);
++chan->queued;
} else {
error = -1;
}
} else {
IOR ior;
ior.io_Command = DNCMD_WRITE;
ior.io_Unit = (void *)chan->chan;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = (PORT *)chan;
ior.io_Data = (APTR)buf;
ior.io_Length = bytes;
PutMsg(chan->dnetport, &ior);
WaitMsg(&ior);
if (ior.io_Error)
error = -1;
}
FixSignal(chan);
return(error);
}
DEof(chan)
CHANN *chan;
{
IOR ior;
ior.io_Command = DNCMD_EOF;
ior.io_Unit = (void *)chan->chan;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = (PORT *)chan;
PutMsg(chan->dnetport, &ior);
WaitMsg(&ior);
FixSignal(chan);
}
DIoctl(chan, cmd, val, aux)
CHANN *chan;
ubyte cmd;
uword val;
ubyte aux;
{
IOR ior;
ior.io_Command = DNCMD_IOCTL;
ior.io_Unit = (void *)chan->chan;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = (PORT *)chan;
ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd);
PutMsg(chan->dnetport, &ior);
WaitMsg(&ior);
FixSignal(chan);
}
DQuit(host)
char *host;
{
IOR ior;
char buf[sizeof(DNETPORTNAME)+32];
PORT *replyport = CreatePort(NULL, 0);
PORT *dnetport;
if (!host)
host = "0";
sprintf(buf, "%s%s", DNETPORTNAME, host);
if (dnetport = FindPort(buf)) {
ior.io_Command = DNCMD_QUIT;
ior.io_Unit = 0;
ior.io_Offset = 0;
ior.io_Message.mn_ReplyPort = replyport;
PutMsg(dnetport, &ior);
WaitMsg(&ior);
DeletePort(replyport);
}
return(dnetport != NULL);
}
DClose(chan)
CHANN *chan;
{
IOR ior;
IOR *io;
ior.io_Command = DNCMD_CLOSE;
ior.io_Unit = (void *)chan->chan;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = (PORT *)chan;
PutMsg(chan->dnetport, &ior);
++chan->queued;
chan->qlen = 0;
WaitQueue(chan, &ior);
while ((io = RemHead(&chan->rdylist)) || (io = GetMsg(chan))) {
io->io_Error = 1;
ReplyMsg(io);
}
DeleteChannel(chan);
}
WaitMsg(ior)
IOR *ior;
{
while (ior->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
Wait(1 << ior->io_Message.mn_ReplyPort->mp_SigBit);
Forbid();
Remove(ior);
Permit();
}
WaitQueue(chan, skipior)
CHANN *chan;
IOR *skipior;
{
register IOR *io;
short error = 0;
while (chan->queued > chan->qlen) { /* until done */
WaitPort(chan); /* something */
io = (IOR *)GetMsg(chan);
if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
if (error == 0)
error = io->io_Error;
if (io != skipior) {
if (io->io_Length)
FreeMem(io->io_Data, io->io_Length);
FreeMem(io, sizeof(IOR));
}
--chan->queued;
} else {
AddTail(&chan->rdylist, io);
}
}
return(error);
}
static
CHANN *
MakeChannel(ior, host)
register IOR *ior;
char *host;
{
CHANN *chan = AllocMem(sizeof(CHANN), MEMF_PUBLIC|MEMF_CLEAR);
/* Name, Pri */
chan->port.mp_Node.ln_Type = NT_MSGPORT;
chan->port.mp_SigBit = AllocSignal(-1);
chan->port.mp_SigTask = FindTask(NULL);
NewList(&chan->port.mp_MsgList);
NewList(&chan->rdylist);
chan->chan = (long)ior->io_Unit;
ior->io_Offset = (long)chan;
if (host) {
char buf[sizeof(DNETPORTNAME)+32];
sprintf(buf, "%s%s", DNETPORTNAME, host);
ior->io_Message.mn_ReplyPort = FindPort(buf);
}
chan->dnetport = ior->io_Message.mn_ReplyPort;
return(chan);
}
static
DeleteChannel(chan)
CHANN *chan;
{
FreeSignal(chan->port.mp_SigBit);
FreeMem(chan, sizeof(CHANN));
}
static
FixSignal(chan)
register CHANN *chan;
{
if (chan->port.mp_MsgList.lh_Head != (NODE *)&chan->port.mp_MsgList.lh_Tail ||
chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail)
SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
}