home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
239.lha
/
amiga
/
src
/
dnet
/
dnet.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-05-02
|
10KB
|
396 lines
/*
* DNET.C
*
* DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
*/
#include "dnet.h"
#include <local/deemu.h>
#include <local/ipc.h>
short Deemu[] = {
DMSTRT, 0, 0,
DMNW , 0,10, 50, 50, 320, 100, 0xFFFF,
DMEND , 0, 0
};
extern int Enable_Abort;
long DResBase;
char PortName[sizeof(DNETPORTNAME)+32];
main(ac,av)
char *av[];
{
long sink_mask, dnet_mask, ipc_mask;
long baud = 0;
char *netdevice = "serial.device";
long netunit = 0;
char *autoclient = "FTERM";
unlink("ENV:DNET_NORUNCLIENT");
Enable_Abort = 0;
bzero(Pkts,sizeof(Pkts));
if ((DResBase = (long)OpenLibrary("dres.library", 0)) == NULL) {
puts("Unable to open DRES.LIBRARY");
exit(1);
}
ac = DoOption(ac, av, "p,b%ld,d%d,n%s,s%s,a,h%d,U%ld,D%s,N%d,8X%d,B%ld",
&PDebug, &baud, &DDebug, &HostName, &autoclient, &AutoAnswer,
&AutoHangup, &netunit, &netdevice, &NetworkNum, &Master8, &DialOut,
&TOBaud
);
if (ac < 0) {
puts("Unknown option, valid options:\n");
puts("dnet -pb#B#d#n<hostname>s<autorunclient>aU#D<device>N<netid>8");
dneterror("Unknown switch");
}
if (AutoAnswer) {
AutoHangup = 1;
DialOut = 0;
}
sprintf(PortName, "%s%d", DNETPORTNAME, NetworkNum);
{
PORT *port;
if (port = (PORT *)FindPort(PortName)) {
puts("DNET: Network number in use");
CloseLibrary(DResBase);
exit(1);
}
}
DNetPort = (PORT *)CreatePort(PortName, 0);
IOSink = (PORT *)CreatePort(NULL,0);
IPCPort = (PORT *)OpenIPC("dnet.CMD", 0);
if (!DNetPort || !IOSink)
dneterror("CreatePort");
NewList(&TxList);
NewList(&SvList);
Rto_act = Wto_act = Cto_act = 0;
NetOpen(IOSink, netdevice, netunit, &baud);
TimerOpen(&Rto, IOSink);
TimerOpen(&Wto, IOSink);
TimerOpen(&Cto, IOSink);
if (TOBaud)
SetTimeouts(TOBaud);
else
SetTimeouts(Baud);
NetStartRead(&Raux->sync, 3);
do_dnetwindow(baud);
if (Quit)
dneterror(NULL);
Rto.tr_node.io_Message.mn_Node.ln_Name = (char *)RTO_REQ;
Wto.tr_node.io_Message.mn_Node.ln_Name = (char *)WTO_REQ;
Cto.tr_node.io_Message.mn_Node.ln_Name = (char *)CTO_REQ;
sink_mask = 1 << IOSink->mp_SigBit;
dnet_mask = 1 << DNetPort->mp_SigBit;
ipc_mask = 1 << IPCPort->mp_SigBit;
do_netreset();
loop:
if (strcmp(autoclient, "-") != 0) {
char buf[64];
char *tmp;
if ((tmp = GetDEnv("DNET_NORUNCLIENT")) == NULL) {
sprintf(buf, "RUN <NIL: >NIL: %s -N%ld", autoclient, NetworkNum);
if (Execute(buf, NULL, NULL) == 0) {
puts("Unable to RUN FTERM (path not setup?)");
puts("You can do it yourself");
}
} else {
free(tmp);
}
}
NetWrite(RestartPkt, 3, 1);
Restart = 1;
OnLine = 1;
/*
* NOTE: Routines must be particularly careful not to clear the
* signal mask unless it doesn't matter. Specifically,
* routines in the dnet_mask section cannot arbitrarily
* clear the signal associated with the sink_mask section.
*
* If you look at NetWrite(), you will note that the signal
* is restored if it must do a WaitIO().
*/
/*
* Immediate return from initial Wait() ... due to looping it is
* possible one or more requests is ready but the signal bit has
* already been cleared.
*/
Signal(FindTask(NULL), ipc_mask|sink_mask|dnet_mask);
while (!Quit && OnLine) {
long mask = Wait(ipc_mask|sink_mask|dnet_mask|SIGBREAKF_CTRL_C);
if (mask & ipc_mask)
handle_ipc();
if (mask & sink_mask) { /* IOSink returns */
register IOR *ior;
while (ior = (IOR *)GetMsg(IOSink)) {
switch((long)ior->io_Message.mn_Node.ln_Name) {
case PKT_REQ:
--NumCon;
if (ior->io_Length)
FreeMem(ior->io_Data, ior->io_Length);
FreeMem(ior, sizeof(IOR));
break;
case CTO_REQ: /* Only when line idle */
Cto_act = 0;
do_cto(ior);
if (Cd == 0 && AutoHangup)
OnLine = 0;
break;
case RTO_REQ: /* Read timeout, reset READ state */
Rto_act = 0;
do_rto(ior);
break;
case WTO_REQ: /* Write-Ack timeout, send CHECK */
Wto_act = 0;
do_wto(ior);
break;
case RNET_REQ: /* Receive data ready, interpret */
NetReadReturned();
do_rnet(ior);
if (Cd == 0 && AutoHangup)
OnLine = 0;
break;
case WNET_REQ: /* Write data sent, start WTO */
NetClWrite(ior);
do_wnet(ior);
break;
case IGWNET_REQ:
NetClWrite(ior);
break;
}
}
}
if (mask & dnet_mask) { /* Receive commands */
register IOR *ior;
while (ior = (IOR *)GetMsg(DNetPort)) {
ior->io_Actual = 0;
switch(ior->io_Command) {
case DNCMD_WRITE: /* write data to net */
{
uword chan = (ulong)ior->io_Unit;
if (Chan[chan].state != CHAN_OPEN) {
ior->io_Error = 1;
break;
}
ior->io_Error = 0;
ior->io_Command = SCMD_DATA;
ior->io_Message.mn_Node.ln_Pri = Chan[chan].pri;
Enqueue(&TxList, ior);
ior = NULL;
}
break;
case DNCMD_SOPEN: /* Reply from server port on remote */
/* open request */
{
CACKCMD ack;
uword chan = (ulong)ior->io_Unit;
ack.chanh = chan >> 8;
ack.chanl = chan;
ack.error = ior->io_Error;
WriteStream(SCMD_ACKCMD, &ack, sizeof(ack), chan);
if (ack.error) {
Chan[chan].state = CHAN_FREE;
--NumCon;
} else {
if (Chan[chan].state == CHAN_CLOSE && !ack.error) {
WritePort(Chan[chan].port, DNCMD_CLOSE, NULL, 0, PKT_REQ, chan);
goto sopenbrk;
}
Chan[chan].state = CHAN_OPEN;
Chan[chan].port = (PORT *)ior->io_Offset;
Chan[chan].flags = CHANF_ROK|CHANF_WOK;
}
sopenbrk:
if (ior->io_Length)
FreeMem(ior->io_Data, ior->io_Length);
FreeMem(ior, sizeof(IOR));
ior = NULL;
}
break;
case DNCMD_EOF:
{
CEOFCMD eof;
uword chan = (ulong)ior->io_Unit;
ior->io_Error = 0;
eof.chanh = chan >> 8;
eof.chanl = chan;
eof.flags = CHANF_ROK;
WriteStream(SCMD_EOFCMD, &eof, sizeof(CEOFCMD), chan);
Chan[chan].flags &= ~CHANF_WOK;
}
break;
case DNCMD_IOCTL:
{
CIOCTL cio;
uword chan = (ulong)ior->io_Unit;
ior->io_Error = 0;
cio.chanh = chan >> 8;
cio.chanl = chan;
cio.valh = (ubyte)((ulong)ior->io_Data >> 24);
cio.vall = (ubyte)((ulong)ior->io_Data >> 16);
cio.valaux = (ubyte)((ulong)ior->io_Data >> 8);
cio.cmd = (ubyte)(ulong)ior->io_Data;
WriteStream(SCMD_IOCTL, &cio, sizeof(CIOCTL), chan);
}
break;
case DNCMD_QUIT:
{
char dummy;
WriteStream(SCMD_QUIT, &dummy, 1, -1);
}
break;
case DNCMD_INFO:
{
char *ptr = (char *)ior->io_Data;
sprintf(ptr, " Bytes Packets Errors\n");
ptr += strlen(ptr);
sprintf(ptr, "OUT: %8ld %8ld %8ld\n", BytesOut, PacketsOut, PacketsResent);
ptr += strlen(ptr);
sprintf(ptr, "IN : %8ld %8ld %8ld\n", BytesIn, PacketsIn, PacketsNakd);
ptr += strlen(ptr);
sprintf(ptr, "Garbage Bytes In: %ld\n", GarbageIn);
}
break;
case DNCMD_OPEN:
ior->io_Error = 0;
{
uword chan = alloc_channel();
COPEN co;
if (chan >= MAXCHAN) {
ior->io_Error = 1;
break;
}
co.chanh = chan >> 8;
co.chanl = chan;
co.porth = (ulong)ior->io_Unit >> 8; /* port # */
co.portl = (ulong)ior->io_Unit;
co.error= 0;
co.pri = (char)(long)ior->io_Message.mn_Node.ln_Name;
Chan[chan].ior = ior;
Chan[chan].port= (PORT *)ior->io_Offset;
Chan[chan].state = CHAN_LOPEN;
Chan[chan].flags = 0;
Chan[chan].pri = ior->io_Message.mn_Node.ln_Pri;
WriteStream(SCMD_OPEN, &co, sizeof(COPEN), chan);
ior = NULL;
}
break;
case DNCMD_CLOSE: /* same io_Command for CCTL_? */
ior->io_Error = 0;
{
CCLOSE cc;
uword chan = (ulong)ior->io_Unit;
cc.chanh = chan >> 8;
cc.chanl = chan;
WriteStream(SCMD_CLOSE, &cc, sizeof(CCLOSE), chan);
Chan[chan].ior = ior;
Chan[chan].state = CHAN_CLOSE;
Chan[chan].flags |= CHANF_LCLOSE;
if (Chan[chan].flags & CHANF_RCLOSE) {
Chan[chan].state = CHAN_FREE;
Chan[chan].ior = NULL;
} else {
ior = NULL;
}
}
break;
}
if (ior)
ReplyMsg(ior);
}
}
if (mask & SIGBREAKF_CTRL_C)
OnLine = 0;
do_wupdate();
}
do_netreset();
if (!Cd) {
ResetConnect();
ResetIdle();
}
if (!Quit)
do_dnetwindow(baud);
if (!Cd) {
ResetConnect();
ResetIdle();
}
if (!Quit)
goto loop;
dneterror(NULL);
}
do_netreset()
{
register short i;
register CHAN *ch;
register IOR *ior;
while (ior = RemHead(&TxList)) {
ior->io_Error = 1;
ReplyMsg(ior);
}
for (i = 0, ch = Chan; i < MAXCHAN; ++i, ++ch) {
switch(ch->state) {
case CHAN_OPEN:
WritePort(Chan[i].port, DNCMD_CLOSE, NULL, 0, PKT_REQ, i);
case CHAN_ROPEN: /* pending on listen port */
ch->state = CHAN_CLOSE;
ch->flags = CHANF_RCLOSE;
ch->ior = NULL;
break;
case CHAN_LOPEN: /* pending on network */
ch->ior->io_Error = 1;
ReplyMsg(ch->ior);
ch->ior = NULL;
ch->state = CHAN_FREE;
ch->flags = 0;
--NumCon;
break;
case CHAN_CLOSE:
if (!(ch->flags & CHANF_LCLOSE))
break;
ch->ior->io_Error = 1;
ReplyMsg(ch->ior);
ch->ior = NULL;
ch->state = CHAN_FREE;
ch->flags = 0;
--NumCon;
}
}
RPStart = 0;
WPStart = 0;
WPUsed = 0;
RState = 0;
RChan = 0;
WChan = 0;
if (!Cto_act) {
Cto.tr_time.tv_secs = 1;
Cto.tr_time.tv_micro= 0;
SendIO(&Cto);
Cto_act = 1;
}
}