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 >
C/C++ Source or Header  |  1989-05-02  |  10KB  |  396 lines

  1.  
  2. /*
  3.  *  DNET.C
  4.  *
  5.  *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  6.  */
  7.  
  8. #include "dnet.h"
  9. #include <local/deemu.h>
  10. #include <local/ipc.h>
  11.  
  12. short Deemu[] = {
  13.     DMSTRT, 0, 0,
  14.     DMNW  , 0,10, 50, 50, 320, 100, 0xFFFF,
  15.     DMEND , 0, 0
  16. };
  17.  
  18.  
  19. extern int Enable_Abort;
  20. long DResBase;
  21. char PortName[sizeof(DNETPORTNAME)+32];
  22.  
  23. main(ac,av)
  24. char *av[];
  25. {
  26.     long sink_mask, dnet_mask, ipc_mask;
  27.     long baud = 0;
  28.     char *netdevice = "serial.device";
  29.     long netunit = 0;
  30.     char *autoclient = "FTERM";
  31.  
  32.     unlink("ENV:DNET_NORUNCLIENT");
  33.     Enable_Abort = 0;
  34.     bzero(Pkts,sizeof(Pkts));
  35.     if ((DResBase = (long)OpenLibrary("dres.library", 0)) == NULL) {
  36.     puts("Unable to open DRES.LIBRARY");
  37.     exit(1);
  38.     }
  39.     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",
  40.     &PDebug, &baud, &DDebug, &HostName, &autoclient, &AutoAnswer,
  41.     &AutoHangup, &netunit, &netdevice, &NetworkNum, &Master8, &DialOut,
  42.     &TOBaud
  43.     );
  44.     if (ac < 0) {
  45.     puts("Unknown option, valid options:\n");
  46.     puts("dnet -pb#B#d#n<hostname>s<autorunclient>aU#D<device>N<netid>8");
  47.     dneterror("Unknown switch");
  48.     }
  49.     if (AutoAnswer) {
  50.     AutoHangup = 1;
  51.     DialOut = 0;
  52.     }
  53.     sprintf(PortName, "%s%d", DNETPORTNAME, NetworkNum);
  54.     {
  55.     PORT *port;
  56.     if (port = (PORT *)FindPort(PortName)) {
  57.         puts("DNET: Network number in use");
  58.         CloseLibrary(DResBase);
  59.         exit(1);
  60.     }
  61.     }
  62.     DNetPort = (PORT *)CreatePort(PortName, 0);
  63.     IOSink   = (PORT *)CreatePort(NULL,0);
  64.     IPCPort  = (PORT *)OpenIPC("dnet.CMD", 0);
  65.     if (!DNetPort || !IOSink)
  66.     dneterror("CreatePort");
  67.  
  68.     NewList(&TxList);
  69.     NewList(&SvList);
  70.     Rto_act = Wto_act = Cto_act = 0;
  71.     NetOpen(IOSink, netdevice, netunit, &baud);
  72.     TimerOpen(&Rto, IOSink);
  73.     TimerOpen(&Wto, IOSink);
  74.     TimerOpen(&Cto, IOSink);
  75.  
  76.     if (TOBaud)
  77.     SetTimeouts(TOBaud);
  78.     else
  79.     SetTimeouts(Baud);
  80.  
  81.     NetStartRead(&Raux->sync, 3);
  82.  
  83.     do_dnetwindow(baud);
  84.     if (Quit)
  85.     dneterror(NULL);
  86.  
  87.     Rto.tr_node.io_Message.mn_Node.ln_Name = (char *)RTO_REQ;
  88.     Wto.tr_node.io_Message.mn_Node.ln_Name = (char *)WTO_REQ;
  89.     Cto.tr_node.io_Message.mn_Node.ln_Name = (char *)CTO_REQ;
  90.  
  91.     sink_mask = 1 << IOSink->mp_SigBit;
  92.     dnet_mask = 1 << DNetPort->mp_SigBit;
  93.     ipc_mask = 1 << IPCPort->mp_SigBit;
  94.  
  95.     do_netreset();
  96. loop:
  97.     if (strcmp(autoclient, "-") != 0) {
  98.     char buf[64];
  99.     char *tmp;
  100.  
  101.     if ((tmp = GetDEnv("DNET_NORUNCLIENT")) == NULL) {
  102.         sprintf(buf, "RUN <NIL: >NIL: %s -N%ld", autoclient, NetworkNum);
  103.         if (Execute(buf, NULL, NULL) == 0) {
  104.         puts("Unable to RUN FTERM (path not setup?)");
  105.         puts("You can do it yourself");
  106.         }
  107.     } else {
  108.         free(tmp);
  109.     }
  110.     }
  111.     NetWrite(RestartPkt, 3, 1);
  112.     Restart = 1;
  113.     OnLine = 1;
  114.  
  115.     /*
  116.      *    NOTE:    Routines must be particularly careful not to clear the
  117.      *        signal mask unless it doesn't matter.  Specifically,
  118.      *        routines in the dnet_mask section cannot arbitrarily
  119.      *        clear the signal associated with the sink_mask section.
  120.      *
  121.      *        If you look at NetWrite(), you will note that the signal
  122.      *        is restored if it must do a WaitIO().
  123.      */
  124.  
  125.     /*
  126.      *    Immediate return from initial Wait() ... due to looping it is
  127.      *    possible one or more requests is ready but the signal bit has
  128.      *    already been cleared.
  129.      */
  130.  
  131.     Signal(FindTask(NULL), ipc_mask|sink_mask|dnet_mask);
  132.  
  133.     while (!Quit && OnLine) {
  134.     long mask = Wait(ipc_mask|sink_mask|dnet_mask|SIGBREAKF_CTRL_C);
  135.  
  136.     if (mask & ipc_mask)
  137.         handle_ipc();
  138.  
  139.     if (mask & sink_mask) {     /*  IOSink returns      */
  140.         register IOR *ior;
  141.         while (ior = (IOR *)GetMsg(IOSink)) {
  142.         switch((long)ior->io_Message.mn_Node.ln_Name) {
  143.         case PKT_REQ:
  144.             --NumCon;
  145.             if (ior->io_Length)
  146.             FreeMem(ior->io_Data, ior->io_Length);
  147.             FreeMem(ior, sizeof(IOR));
  148.             break;
  149.         case CTO_REQ:    /*  Only when line idle         */
  150.             Cto_act = 0;
  151.             do_cto(ior);
  152.             if (Cd == 0 && AutoHangup)
  153.             OnLine = 0;
  154.             break;
  155.         case RTO_REQ:    /*  Read timeout, reset READ state  */
  156.             Rto_act = 0;
  157.             do_rto(ior);
  158.             break;
  159.         case WTO_REQ:    /*  Write-Ack timeout, send CHECK   */
  160.             Wto_act = 0;
  161.             do_wto(ior);
  162.             break;
  163.         case RNET_REQ:    /*  Receive data ready, interpret   */
  164.             NetReadReturned();
  165.             do_rnet(ior);
  166.             if (Cd == 0 && AutoHangup)
  167.             OnLine = 0;
  168.             break;
  169.         case WNET_REQ:    /*  Write data sent, start WTO        */
  170.             NetClWrite(ior);
  171.             do_wnet(ior);
  172.             break;
  173.         case IGWNET_REQ:
  174.             NetClWrite(ior);
  175.             break;
  176.         }
  177.         }
  178.     }
  179.     if (mask & dnet_mask) {     /*  Receive commands    */
  180.         register IOR *ior;
  181.         while (ior = (IOR *)GetMsg(DNetPort)) {
  182.         ior->io_Actual = 0;
  183.         switch(ior->io_Command) {
  184.         case DNCMD_WRITE:    /*  write data to net        */
  185.             {
  186.             uword chan = (ulong)ior->io_Unit;
  187.             if (Chan[chan].state != CHAN_OPEN) {
  188.                 ior->io_Error = 1;
  189.                 break;
  190.             }
  191.             ior->io_Error = 0;
  192.             ior->io_Command = SCMD_DATA;
  193.             ior->io_Message.mn_Node.ln_Pri = Chan[chan].pri;
  194.             Enqueue(&TxList, ior);
  195.             ior = NULL;
  196.             }
  197.             break;
  198.         case DNCMD_SOPEN:   /*    Reply from server port on remote    */
  199.                     /*    open request                */
  200.             {
  201.             CACKCMD ack;
  202.             uword chan = (ulong)ior->io_Unit;
  203.  
  204.  
  205.             ack.chanh = chan >> 8;
  206.             ack.chanl = chan;
  207.             ack.error = ior->io_Error;
  208.             WriteStream(SCMD_ACKCMD, &ack, sizeof(ack), chan);
  209.             if (ack.error) {
  210.                 Chan[chan].state = CHAN_FREE;
  211.                 --NumCon;
  212.             } else {
  213.                 if (Chan[chan].state == CHAN_CLOSE && !ack.error) {
  214.                 WritePort(Chan[chan].port, DNCMD_CLOSE, NULL, 0, PKT_REQ, chan);
  215.                 goto sopenbrk;
  216.                 }
  217.                 Chan[chan].state = CHAN_OPEN;
  218.                 Chan[chan].port  = (PORT *)ior->io_Offset;
  219.                 Chan[chan].flags = CHANF_ROK|CHANF_WOK;
  220.             }
  221. sopenbrk:
  222.             if (ior->io_Length)
  223.                 FreeMem(ior->io_Data, ior->io_Length);
  224.             FreeMem(ior, sizeof(IOR));
  225.             ior = NULL;
  226.             }
  227.             break;
  228.         case DNCMD_EOF:
  229.             {
  230.             CEOFCMD eof;
  231.             uword chan = (ulong)ior->io_Unit;
  232.  
  233.             ior->io_Error = 0;
  234.             eof.chanh = chan >> 8;
  235.             eof.chanl = chan;
  236.             eof.flags = CHANF_ROK;
  237.             WriteStream(SCMD_EOFCMD, &eof, sizeof(CEOFCMD), chan);
  238.             Chan[chan].flags &= ~CHANF_WOK;
  239.             }
  240.             break;
  241.         case DNCMD_IOCTL:
  242.             {
  243.             CIOCTL cio;
  244.             uword chan = (ulong)ior->io_Unit;
  245.  
  246.             ior->io_Error = 0;
  247.             cio.chanh = chan >> 8;
  248.             cio.chanl = chan;
  249.             cio.valh   = (ubyte)((ulong)ior->io_Data >> 24);
  250.             cio.vall   = (ubyte)((ulong)ior->io_Data >> 16);
  251.             cio.valaux = (ubyte)((ulong)ior->io_Data >> 8);
  252.             cio.cmd = (ubyte)(ulong)ior->io_Data;
  253.             WriteStream(SCMD_IOCTL, &cio, sizeof(CIOCTL), chan);
  254.             }
  255.             break;
  256.         case DNCMD_QUIT:
  257.             {
  258.             char dummy;
  259.  
  260.             WriteStream(SCMD_QUIT, &dummy, 1, -1);
  261.             }
  262.             break;
  263.         case DNCMD_INFO:
  264.             {
  265.             char *ptr = (char *)ior->io_Data;
  266.             sprintf(ptr, "         Bytes  Packets   Errors\n");
  267.             ptr += strlen(ptr);
  268.             sprintf(ptr, "OUT:  %8ld %8ld %8ld\n", BytesOut, PacketsOut, PacketsResent);
  269.             ptr += strlen(ptr);
  270.             sprintf(ptr, "IN :  %8ld %8ld %8ld\n", BytesIn, PacketsIn, PacketsNakd);
  271.             ptr += strlen(ptr);
  272.             sprintf(ptr, "Garbage Bytes In: %ld\n", GarbageIn);
  273.             }
  274.             break;
  275.         case DNCMD_OPEN:
  276.             ior->io_Error = 0;
  277.             {
  278.             uword chan = alloc_channel();
  279.             COPEN co;
  280.             if (chan >= MAXCHAN) {
  281.                 ior->io_Error = 1;
  282.                 break;
  283.             }
  284.             co.chanh = chan >> 8;
  285.             co.chanl = chan;
  286.             co.porth = (ulong)ior->io_Unit >> 8;  /* port #   */
  287.             co.portl = (ulong)ior->io_Unit;
  288.             co.error= 0;
  289.             co.pri = (char)(long)ior->io_Message.mn_Node.ln_Name;
  290.             Chan[chan].ior = ior;
  291.             Chan[chan].port= (PORT *)ior->io_Offset;
  292.             Chan[chan].state = CHAN_LOPEN;
  293.             Chan[chan].flags = 0;
  294.             Chan[chan].pri = ior->io_Message.mn_Node.ln_Pri;
  295.             WriteStream(SCMD_OPEN, &co, sizeof(COPEN), chan);
  296.             ior = NULL;
  297.             }
  298.             break;
  299.         case DNCMD_CLOSE:    /*  same io_Command for CCTL_?    */
  300.             ior->io_Error = 0;
  301.             {
  302.             CCLOSE cc;
  303.             uword chan = (ulong)ior->io_Unit;
  304.  
  305.             cc.chanh = chan >> 8;
  306.             cc.chanl = chan;
  307.             WriteStream(SCMD_CLOSE, &cc, sizeof(CCLOSE), chan);
  308.             Chan[chan].ior = ior;
  309.             Chan[chan].state = CHAN_CLOSE;
  310.             Chan[chan].flags |= CHANF_LCLOSE;
  311.             if (Chan[chan].flags & CHANF_RCLOSE) {
  312.                 Chan[chan].state = CHAN_FREE;
  313.                 Chan[chan].ior = NULL;
  314.             } else {
  315.                 ior = NULL;
  316.             }
  317.             }
  318.             break;
  319.         }
  320.         if (ior)
  321.             ReplyMsg(ior);
  322.         }
  323.     }
  324.     if (mask & SIGBREAKF_CTRL_C)
  325.         OnLine = 0;
  326.     do_wupdate();
  327.     }
  328.     do_netreset();
  329.     if (!Cd) {
  330.     ResetConnect();
  331.     ResetIdle();
  332.     }
  333.     if (!Quit)
  334.     do_dnetwindow(baud);
  335.     if (!Cd) {
  336.     ResetConnect();
  337.     ResetIdle();
  338.     }
  339.     if (!Quit)
  340.     goto loop;
  341.     dneterror(NULL);
  342. }
  343.  
  344. do_netreset()
  345. {
  346.     register short i;
  347.     register CHAN *ch;
  348.     register IOR *ior;
  349.  
  350.     while (ior = RemHead(&TxList)) {
  351.     ior->io_Error = 1;
  352.     ReplyMsg(ior);
  353.     }
  354.     for (i = 0, ch = Chan; i < MAXCHAN; ++i, ++ch) {
  355.     switch(ch->state) {
  356.     case CHAN_OPEN:
  357.         WritePort(Chan[i].port, DNCMD_CLOSE, NULL, 0, PKT_REQ, i);
  358.     case CHAN_ROPEN:    /*  pending on listen port  */
  359.         ch->state = CHAN_CLOSE;
  360.         ch->flags = CHANF_RCLOSE;
  361.         ch->ior = NULL;
  362.         break;
  363.     case CHAN_LOPEN:    /*  pending on network        */
  364.         ch->ior->io_Error = 1;
  365.         ReplyMsg(ch->ior);
  366.         ch->ior = NULL;
  367.         ch->state = CHAN_FREE;
  368.         ch->flags = 0;
  369.         --NumCon;
  370.         break;
  371.     case CHAN_CLOSE:
  372.         if (!(ch->flags & CHANF_LCLOSE))
  373.         break;
  374.         ch->ior->io_Error = 1;
  375.         ReplyMsg(ch->ior);
  376.         ch->ior = NULL;
  377.         ch->state = CHAN_FREE;
  378.         ch->flags = 0;
  379.         --NumCon;
  380.     }
  381.     }
  382.     RPStart = 0;
  383.     WPStart = 0;
  384.     WPUsed  = 0;
  385.     RState  = 0;
  386.     RChan = 0;
  387.     WChan = 0;
  388.     if (!Cto_act) {
  389.     Cto.tr_time.tv_secs = 1;
  390.     Cto.tr_time.tv_micro= 0;
  391.     SendIO(&Cto);
  392.     Cto_act = 1;
  393.     }
  394. }
  395.  
  396.