home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 367.lha / netkeys_v2.0 / dnetlib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  10.2 KB  |  481 lines

  1. /*
  2.  *  DNETLIB.C
  3.  *
  4.  *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  5.  *
  6.  *  Library Interface for DNET.
  7.  */
  8.  
  9. #include "dnet.h"
  10.  
  11. #include <stdio.h>
  12.  
  13. #ifndef BUG
  14. #define BUG(a)
  15. #define BUGGETC
  16. #endif
  17.  
  18. static struct DChannel *MakeChannel U_ARGS((IOR *, char *));
  19. static void DeleteChannel U_ARGS((struct DChannel *));
  20. static void FixSignal      U_ARGS((struct DChannel *));
  21.  
  22. #define NAMELEN sizeof("DNET.PORT.XXXXX")
  23. #define NAMEPAT "DNET.PORT.%ld"
  24.  
  25. PORT *DListen(portnum)
  26. uword portnum;
  27. {
  28.     PORT *port;
  29.     char *ptr;
  30.  
  31.     port = NULL;
  32.     ptr = AllocMem(NAMELEN, MEMF_PUBLIC);   /*  memory the the name     */
  33.     sprintf(ptr, NAMEPAT, portnum);
  34.     Forbid();                               /*  task-atomic operation   */
  35.     if (FindPort(ptr) || !(port = CreatePort(ptr,0)))
  36.        FreeMem(ptr, NAMELEN);
  37.     Permit();
  38.     return(port);
  39. }
  40.  
  41. void
  42. DUnListen(lisport)
  43. PORT *lisport;
  44. {
  45.    register char *ptr;
  46.    ptr = lisport->mp_Node.ln_Name;
  47.  
  48.    if (lisport)
  49.    {
  50.       Forbid();                       /*  task-atomic operation       */
  51.       while (DNAAccept(lisport));     /*  remove all pending requests */
  52.       DeletePort(lisport);            /*  gone!                       */
  53.       Permit();
  54.       FreeMem(ptr, NAMELEN);
  55.    }
  56. }
  57.  
  58. /*
  59.  *  DAccept()
  60.  *
  61.  *  Note:   This call will work even if called by a task which does not
  62.  *        own the listen port.
  63.  */
  64.  
  65. PORT *
  66. DAccept(lisport)
  67. PORT *lisport;
  68. {
  69.     register IOR *ior;
  70.     register struct DChannel * chan;
  71.  
  72. BUG(("DAccept: Entry, port %lx\n", lisport))
  73.  
  74.     chan = NULL;
  75.     while (!chan && (ior = (IOR *)GetMsg(lisport))) {
  76.        switch(ior->io_Command) {
  77.       case DNCMD_SOPEN:
  78.          BUG(("DAccept: SOPEN command\n"))
  79.          chan = MakeChannel(ior, NULL);
  80.          break;
  81.       default:
  82.          BUG(("DAccept: Unrecognized command '%d'\n", ior->io_Command))
  83.          ior->io_Error = 1;
  84.          break;
  85.     }
  86.     BUG(("DAccept: Replying\n"))
  87.     ReplyMsg(&ior->io_Message);
  88.     }
  89.     BUG(("DAccept: After while loop\n"))
  90.     if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
  91.        SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
  92.  
  93.     return(chan ? &chan->port : NULL);
  94. }
  95.  
  96. /*
  97.  *  Refuse a connection
  98.  */
  99.  
  100. DNAAccept(lisport)
  101. PORT *lisport;
  102. {
  103.     IOR *ior;
  104.  
  105.     if (ior = (IOR *)GetMsg(lisport)) {
  106.     ior->io_Error = 1;
  107.     ReplyMsg(&ior->io_Message);
  108.     }
  109.     if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
  110.        SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
  111.     return(ior != NULL);
  112. }
  113.  
  114. void DPri(chan, pri)
  115. struct DChannel * chan;
  116. int pri;
  117. {
  118. }
  119.  
  120.  
  121. PORT *
  122. DOpen(host, portnum, txpri, rxpri)
  123. char *host;
  124. char txpri, rxpri;
  125. uword portnum;
  126. {
  127.     IOR ior;
  128.     struct DChannel *chan;
  129.  
  130.     if (!host)
  131.        host = "0";
  132.     chan = MakeChannel(&ior, host);
  133.     if (rxpri > 126)
  134.     rxpri = 126;
  135.     if (rxpri < -127)
  136.     rxpri = -127;
  137.     if (txpri > 126)
  138.     txpri = 126;
  139.     if (txpri < -127)
  140.     txpri = -127;
  141.     if (chan->dnetport) {
  142.     ior.io_Command = DNCMD_OPEN;
  143.     ior.io_Unit = (void *)portnum;
  144.     ior.io_Offset = (long)chan;
  145.     ior.io_Message.mn_ReplyPort = &chan->port;
  146.     ior.io_Message.mn_Node.ln_Pri = txpri;
  147.     ior.io_Message.mn_Node.ln_Name= (char *)rxpri;
  148.  
  149.     PutMsg(chan->dnetport, &ior.io_Message);
  150.     WaitMsg(&ior);
  151.     if (ior.io_Error == 0) {
  152.        chan->chan = (long)ior.io_Unit;
  153.        FixSignal(chan);
  154.        return(&chan->port);
  155.        }
  156.     }
  157.     DeleteChannel(chan);
  158.     return(NULL);
  159. }
  160.  
  161.  
  162. DNRead(chan, buf, bytes)
  163. struct DChannel * chan;
  164. char *buf;
  165. int bytes;
  166. {
  167.     register IOR *ior;
  168.     int len;
  169.     long n;
  170.  
  171.     len = 0;
  172.     if (chan->eof)
  173.        return(-1);
  174.     while (bytes && ((ior = (IOR *)
  175.            RemHead((struct List *)&chan->rdylist)) ||
  176.            (ior = (IOR *)GetMsg(&chan->port)))) {
  177.        if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG)
  178.        {
  179.       if (!chan->queued)
  180.       {
  181.          BUG(("DNRead: Software Error"));
  182.       }
  183.       else
  184.          --chan->queued;
  185.       if (ior->io_Length)
  186.          FreeMem((char *)ior->io_Data, (long)ior->io_Length);
  187.      FreeMem((char *)ior, (long)sizeof(IOR));
  188.      continue;
  189.        }
  190.       switch(ior->io_Command)
  191.       {
  192.      case DNCMD_CLOSE:
  193.      case DNCMD_EOF:
  194.         chan->eof = 1;
  195.         ReplyMsg(&ior->io_Message);
  196.         break;
  197.  
  198.      case DNCMD_WRITE:
  199.         n = ior->io_Length - ior->io_Actual;
  200.         if (n <= bytes)
  201.         {
  202.            memcpy(buf, ((char *)ior->io_Data) + ior->io_Actual, n);
  203.            bytes -= n;
  204.            len += n;
  205.            buf += n;
  206.            ReplyMsg(&ior->io_Message);
  207.         }
  208.         else
  209.         {
  210.            memcpy(buf, (char *)ior->io_Data + ior->io_Actual, bytes);
  211.            len += bytes;
  212.            ior->io_Actual += bytes;
  213.            bytes = 0;
  214.            Forbid();   /*  DNET device is a task, no need to Disable() */
  215.            ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  216.            AddHead(&chan->port.mp_MsgList, (struct Node *)ior);
  217.            Permit();
  218.         }
  219.         break;
  220.      default:
  221.         ior->io_Error = 1;
  222.         ReplyMsg(&ior->io_Message);
  223.       }
  224.     }
  225.     FixSignal(chan);
  226.     if (chan->eof)
  227.        SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
  228.     return(len);
  229. }
  230.  
  231. int DRead(chan, buf, bytes)
  232. char *buf;
  233. struct DChannel * chan;
  234. int bytes;
  235. {
  236.    long len;
  237.    long n;
  238.  
  239.    len = 0;
  240.    if (chan->eof)
  241.    {
  242.       BUG(("****DNET EOF!!!\n"));
  243.       return(-1);
  244.    }
  245.  
  246.    while (bytes)
  247.    {
  248.       WaitPort(&chan->port);
  249.       n = DNRead(chan, buf, bytes);
  250.       len += n;
  251.       if (n < 0) break;
  252.       buf += n;
  253.       bytes -= n;
  254.       if (chan->eof) break;
  255.    }
  256.    return(len);
  257. }
  258.  
  259. void DQueue(chan, n)
  260. struct DChannel * chan;
  261. int n;
  262. {
  263.     chan->qlen = n;
  264. }
  265.  
  266. DWrite(chan, buf, bytes)
  267. struct DChannel * chan;
  268. char *buf;
  269. int bytes;
  270. {
  271.     IOR tmpior;
  272.     IOR *ior;
  273.     int error;
  274.  
  275.    error = bytes;
  276.    if (chan->qlen)
  277.    {
  278.       if (WaitQueue(chan, NULL) >= 0)
  279.       {
  280.      ior = (IOR *)AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC);
  281.      ior->io_Command = DNCMD_WRITE;
  282.      ior->io_Unit = (void *)chan->chan;
  283.      ior->io_Offset = (long)chan;
  284.      ior->io_Message.mn_ReplyPort = &chan->port;
  285.      ior->io_Data = (APTR)AllocMem(bytes, MEMF_PUBLIC);
  286.      ior->io_Length = bytes;
  287.      memcpy((char *)ior->io_Data, buf, (int)bytes);
  288.      PutMsg(chan->dnetport, &ior->io_Message);
  289.      ++chan->queued;
  290.       }
  291.       else
  292.       {
  293.      error = -1;
  294.       }
  295.    }
  296.    else
  297.    {
  298.       tmpior.io_Command = DNCMD_WRITE;
  299.       tmpior.io_Unit = (void *)chan->chan;
  300.       tmpior.io_Offset = (long)chan;
  301.       tmpior.io_Message.mn_ReplyPort = &chan->port;
  302.       tmpior.io_Data = (APTR)buf;
  303.       tmpior.io_Length = bytes;
  304.       PutMsg(chan->dnetport, &tmpior.io_Message);
  305.       WaitMsg(&tmpior);
  306.       if (tmpior.io_Error)
  307.       {
  308.      error = -1;
  309.      BUG(("*****DWrite: io_Error %d\n", tmpior.io_Error));
  310.      BUGGETC
  311.       }
  312.    }
  313.    FixSignal(chan);
  314.    return(error);
  315. }
  316.  
  317. void DEof(chan)
  318. struct DChannel * chan;
  319. {
  320.     IOR ior;
  321.  
  322.     ior.io_Command = DNCMD_EOF;
  323.     ior.io_Unit = (void *)chan->chan;
  324.     ior.io_Offset = (long)chan;
  325.     ior.io_Message.mn_ReplyPort = &chan->port;
  326.     PutMsg(chan->dnetport, &ior.io_Message);
  327.     WaitMsg(&ior);
  328.     FixSignal(chan);
  329. }
  330.  
  331. void DIoctl(chan, cmd, val, aux)
  332. struct DChannel * chan;
  333. ubyte cmd;
  334. uword val;
  335. ubyte aux;
  336. {
  337.     IOR ior;
  338.  
  339.     ior.io_Command = DNCMD_IOCTL;
  340.     ior.io_Unit = (void *)chan->chan;
  341.     ior.io_Offset = (long)chan;
  342.     ior.io_Message.mn_ReplyPort = &chan->port;
  343.     ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd);
  344.     PutMsg(chan->dnetport, &ior.io_Message);
  345.     WaitMsg(&ior);
  346.     FixSignal(chan);
  347. }
  348.  
  349. int DQuit(host)
  350. char *host;
  351. {
  352.     IOR ior;
  353.     char buf[sizeof(DNETPORTNAME)+32];
  354.     PORT *replyport;
  355.     PORT *dnetport;
  356.  
  357.     if (!host)
  358.     host = "0";
  359.     sprintf(buf, "%s%s", DNETPORTNAME, host);
  360.     if (dnetport = FindPort(buf)) {
  361.     replyport = CreatePort(NULL, 0);
  362.     ior.io_Command = DNCMD_QUIT;
  363.     ior.io_Unit = 0;
  364.     ior.io_Offset = 0;
  365.     ior.io_Message.mn_ReplyPort = replyport;
  366.     PutMsg(dnetport, &ior.io_Message);
  367.     WaitMsg(&ior);
  368.     DeletePort(replyport);
  369.     }
  370.     return(dnetport != NULL);
  371. }
  372.  
  373.  
  374. void DClose(chan)
  375. struct DChannel * chan;
  376. {
  377.     IOR ior;
  378.     IOR *io;
  379.  
  380. BUG(("DClose: Enter\n"))
  381.  
  382.     ior.io_Command = DNCMD_CLOSE;
  383.     ior.io_Unit = (void *)chan->chan;
  384.     ior.io_Offset = (long)chan;
  385.     ior.io_Message.mn_ReplyPort = &chan->port;
  386.     PutMsg(chan->dnetport, &ior.io_Message);
  387.     ++chan->queued;
  388.     chan->qlen = 0;
  389.     WaitQueue(chan, &ior);
  390.     while ((io = (IOR *)RemHead((struct List *)&chan->rdylist)) ||
  391.        (io = (IOR *)GetMsg(&chan->port))) {
  392.     io->io_Error = 1;
  393.     ReplyMsg(&io->io_Message);
  394.     }
  395.     DeleteChannel(chan);
  396. }
  397.  
  398. void WaitMsg(ior)
  399. IOR *ior;
  400. {
  401.     while (ior->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
  402.     Wait(1 << ior->io_Message.mn_ReplyPort->mp_SigBit);
  403.     Forbid();
  404.     Remove((struct Node *)ior);
  405.     Permit();
  406. }
  407.  
  408. int WaitQueue(chan, skipior)
  409. struct DChannel * chan;
  410. IOR *skipior;
  411. {
  412.     register IOR *io;
  413.     short error;
  414.  
  415.    error = 0;
  416.     while (chan->queued > chan->qlen) {     /*  until done  */
  417.     WaitPort(&chan->port);   /*  something   */
  418.     io = (IOR *)GetMsg(&chan->port);
  419.     if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  420.         if (error == 0)
  421.         error = io->io_Error;
  422.         if (io != skipior) {
  423.         if (io->io_Length)
  424.             FreeMem((char *)io->io_Data, io->io_Length);
  425.         FreeMem((char *)io, sizeof(IOR));
  426.         }
  427.         --chan->queued;
  428.     } else {
  429.         AddTail(&chan->rdylist, (struct Node *)io);
  430.     }
  431.     }
  432.     return((int)error);
  433. }
  434.  
  435. static struct DChannel *MakeChannel(ior, host)
  436. register IOR *ior;
  437. char *host;
  438. {
  439.     struct DChannel * chan;
  440.     char buf[sizeof(DNETPORTNAME)+32];
  441.  
  442. BUG(("MakeChannel: Entry\n"))
  443.  
  444.     chan = (struct DChannel *)AllocMem(sizeof(struct DChannel),
  445.                        MEMF_PUBLIC|MEMF_CLEAR);
  446.  
  447.     /*    Name, Pri */
  448.     chan->port.mp_Node.ln_Type = NT_MSGPORT;
  449.     chan->port.mp_SigBit = AllocSignal(-1);
  450.     chan->port.mp_SigTask = FindTask(NULL);
  451.     NewList(&chan->port.mp_MsgList);
  452.     NewList(&chan->rdylist);
  453.     chan->chan = (long)ior->io_Unit;
  454.     ior->io_Offset = (long)chan;
  455.     if (host) {
  456.        sprintf(buf, "%s%s", DNETPORTNAME, host);
  457.     ior->io_Message.mn_ReplyPort = FindPort(buf);
  458.     }
  459.     chan->dnetport = ior->io_Message.mn_ReplyPort;
  460.     return(chan);
  461. }
  462.  
  463. static void
  464. DeleteChannel(chan)
  465. struct DChannel * chan;
  466. {
  467.     FreeSignal(chan->port.mp_SigBit);
  468.     FreeMem((char *)chan, (long)sizeof(struct DChannel));
  469. }
  470.  
  471. static void
  472. FixSignal(chan)
  473. register struct DChannel * chan;
  474. {
  475.     if (chan->port.mp_MsgList.lh_Head !=
  476.          (NODE *)&chan->port.mp_MsgList.lh_Tail ||
  477.        chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail)
  478.     SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
  479. }
  480.  
  481.