home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
142.lha
/
DNet
/
dnet
/
subs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-21
|
7KB
|
310 lines
/*
* SUBS.C
*
* DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
*
*/
#include "dnet.h"
#include <stdio.h>
/*
* Add the high-level command to the queue of commands to be sent to
* the remote DNET.
*/
WriteStream(sdcmd, buf, len, chan)
uword chan;
{
register IOR *ior = (IOR *)AllocMem(sizeof(IOR), MEMF_PUBLIC);
if (DDebug)
printf("WriteStream: cmd %ld buflen %ld chan %ld\n", sdcmd, len, chan);
ior->io_Message.mn_Node.ln_Name = (char *)PKT_REQ;
ior->io_Message.mn_ReplyPort = IOSink;
ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
ior->io_Length = len;
ior->io_Actual = 0;
ior->io_Command = sdcmd;
ior->io_Error = 0;
ior->io_Message.mn_Node.ln_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
CopyMem(buf, ior->io_Data, len);
Enqueue(&TxList, ior);
do_wupdate();
}
/*
* Send a packet to a port. Used to send data/eof/close to channel
* ports, and to relay open requests to server ports.
*/
WritePort(port, scmd, buf, len, rettype, unit)
PORT *port;
ubyte *buf;
{
register IOR *ior = (IOR *)AllocMem(sizeof(IOR), MEMF_PUBLIC);
if (DDebug)
printf("WritePort: cmd %ld buflen %ld rt %ld unit %ld\n", scmd, len, rettype, unit);
ior->io_Message.mn_Node.ln_Name = (char *)rettype;
ior->io_Message.mn_ReplyPort = (rettype) ? IOSink : DNetPort;
ior->io_Unit = (struct Unit *)unit;
ior->io_Command = scmd;
ior->io_Error = 0;
ior->io_Data = NULL;
ior->io_Length = 0;
ior->io_Actual = 0;
if (buf) {
ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
ior->io_Length = len;
CopyMem(buf, ior->io_Data, len);
}
PutMsg(port, ior);
if (rettype == PKT_REQ)
++NumCon;
}
/*
* ALLOC_CHANNEL()
*
* Allocate a channel. Starting at a random point, find the first
* free channel. Return -1 if no free channels found.
*/
alloc_channel()
{
static ulong ran = 13;
long stamp[3];
register uword i;
DateStamp(stamp);
ran = ((ran * 13) + 1) ^ (ran >> 9) + stamp[0] + stamp[1] + stamp[2];
for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
if (Chan[i].state == 0) {
return(i);
}
}
for (i = ran % MAXCHAN; i < MAXCHAN; --i) {
if (Chan[i].state == 0) {
return(i);
}
}
return(-1);
}
/*
* Get next node in a linked list. If a pointer to a list base
* is passed, gets the first node in the linked list. Returns
* NULL if no further nodes in the list.
*/
GetNext(node)
NODE *node;
{
register NODE *next = node->ln_Succ;
if (*(long *)next)
return((long)next);
return(NULL);
}
/*
* CHKBUF
*
* Generate a two-byte checksum for data. Uses a very simple, but
* effective algorithm.
*/
chkbuf(buf, bytes)
register ubyte *buf;
register uword bytes;
{
register uword i;
register ubyte c1,c2;
for (i = c1 = c2 = 0; i < bytes; ++i) {
c1 += buf[i];
c2 += c1;
}
c1 = -(c1 + c2);
return((c1<<8)|c2);
}
TimerOpen(req, sink)
IOT *req;
PORT *sink;
{
if (OpenDevice("timer.device", UNIT_VBLANK, req, 0))
dneterror("timer.device");
req->tr_node.io_Message.mn_ReplyPort = sink;
req->tr_node.io_Command = TR_ADDREQUEST;
}
TimerClose(req)
IOT *req;
{
CloseDevice(req);
req->tr_node.io_Device = NULL;
}
/*
* RUNSERVER
*
* Search the file [S:]DNET.SERVERS for the specified server and
* attempt to LoadSeg()/CreateProc() it. The port number must be
* non-zero (allows commening out lines in DNET.SERVERS), and
* regardless of whether the server is able to DListen(), it must
* perform a small handshake sequence with DNET.
*/
void
RunServer(portnum)
uword portnum;
{
FILE *fi;
char buf[128];
char s1[64], s2[64];
long v1;
long seg;
if (!portnum)
return;
if ((fi = fopen("dnet.servers", "r")) == NULL)
fi = fopen("s:dnet.servers", "r");
if (fi) {
while (fgets(buf, 128, fi)) {
if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
goto success;
}
fclose(fi);
}
return;
success:
fclose(fi);
if (seg = LoadSeg(s1)) {
PNODE *pnode;
PROC *myproc;
PROC *proc;
char *name;
MSG msg;
myproc = (PROC *)FindTask(NULL);
pnode = AllocMem(sizeof(PNODE), MEMF_PUBLIC);
sprintf(pnode->name, "DNET.SERVER.%ld", portnum);
pnode->seg = seg;
if (proc = CreateProc(pnode->name, 0, pnode->seg, 4096)) {
proc = (PROC *)((char *)proc - OFFSET(proc,pr_MsgPort));
msg.mn_ReplyPort = &myproc->pr_MsgPort;
printf("Starting Server: %s %s\n", s1, pnode->name);
PutMsg(&proc->pr_MsgPort, &msg); /* startup handshake */
WaitPort(&myproc->pr_MsgPort);
GetMsg(&myproc->pr_MsgPort);
AddTail(&SvList, pnode);
} else {
printf("Unable to start server: %s %s\n", s1, pnode->name);
FreeMem(pnode, sizeof(PNODE));
}
} else {
printf("Server not found: %s\n", s1);
}
}
/*
* This cleans up as best as possible, but if there are still ACTIVE
* servers or any CLIENTS, this call will not completely get rid of
* them...
*
* Note that this call will KILL any servers automatically started up
* by DNET and then UnLoadSeg() them. If the server has already exited,
* it simply unloads the server's segment.
*/
dneterror(str)
char *str;
{
register short i;
if (str)
puts(str);
if (DNetPort) {
register IOR *ior;
Forbid();
while ((ior = (IOR *)RemHead(&TxList)) || (ior = (IOR *)GetMsg(DNetPort))) {
ior->io_Error = -1;
ReplyMsg(ior);
}
DeletePort(DNetPort);
Permit();
DNetPort = NULL;
}
if (Wto.tr_node.io_Device) {
if (Wto_act) {
AbortIO(&Wto);
WaitIO(&Wto);
Wto_act = 0;
}
TimerClose(&Wto);
}
if (Rto.tr_node.io_Device) {
if (Rto_act) {
AbortIO(&Rto);
WaitIO(&Rto);
Rto_act = 0;
}
TimerClose(&Rto);
}
if (RNet) {
AbortIO(RNet);
WaitIO(RNet);
}
if (WNet)
NetWrite(NULL, 0, 0);
if (IOSink)
DeletePort(IOSink);
IOSink = NULL;
NetClose(&RNet, &WNet);
for (i = 0; i < MAXCHAN; ++i) {
if (Chan[i].state != CHAN_FREE && Chan[i].ior) {
Chan[i].ior->io_Error = -1;
Chan[i].state = CHAN_FREE;
ReplyMsg(Chan[i].ior);
}
}
{
register PNODE *pnode;
register PROC *proc;
while (pnode = (PNODE *)RemHead(&SvList)) {
Forbid();
while (proc = (PROC *)FindTask(pnode->name)) {
Signal(proc, SIGBREAKF_CTRL_C);
Permit();
printf("Waiting for server %s to exit\n", pnode->name);
Forbid();
}
Permit();
UnLoadSeg(pnode->seg);
FreeMem(pnode, sizeof(PNODE));
}
}
exit(1);
}
bzero(ptr, bytes)
register ubyte *ptr;
register long bytes;
{
while (bytes--)
*ptr++ = 0;
}
fixsignal(port)
register PORT *port;
{
if ((long)port->mp_MsgList.lh_Head != (long)&port->mp_MsgList.lh_Tail) {
register ulong mask = 1 << port->mp_SigBit;
SetSignal(mask, mask);
}
}