home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 142.lha / DNet / lib / dnetlib.c < prev   
C/C++ Source or Header  |  1986-11-21  |  9KB  |  433 lines

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