home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff220.lzh / DNet / amiga / dnet / subs.c < prev    next >
C/C++ Source or Header  |  1989-06-04  |  7KB  |  324 lines

  1.  
  2. /*
  3.  *  SUBS.C
  4.  *
  5.  *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  6.  *
  7.  */
  8.  
  9. #include "dnet.h"
  10. #include <stdio.h>
  11.  
  12. /*
  13.  *  Add the high-level command to the queue of commands to be sent to
  14.  *  the remote DNET.
  15.  */
  16.  
  17. WriteStream(sdcmd, buf, len, chan)
  18. uword chan;
  19. {
  20.     register IOR *ior = (IOR *)AllocMem(sizeof(IOR), MEMF_PUBLIC);
  21.  
  22.     if (DDebug)
  23.     printf("WriteStream: cmd %ld  buflen %ld  chan %ld\n", sdcmd, len, chan);
  24.     ior->io_Message.mn_Node.ln_Name = (char *)PKT_REQ;
  25.     ior->io_Message.mn_ReplyPort = IOSink;
  26.     ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
  27.     ior->io_Length = len;
  28.     ior->io_Actual = 0;
  29.     ior->io_Command = sdcmd;
  30.     ior->io_Error = 0;
  31.     ior->io_Message.mn_Node.ln_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
  32.     CopyMem(buf, ior->io_Data, len);
  33.     Enqueue(&TxList, ior);
  34.     do_wupdate();
  35. }
  36.  
  37. /*
  38.  *  Send a packet to a port.  Used to send data/eof/close to channel
  39.  *  ports, and to relay open requests to server ports.
  40.  */
  41.  
  42. WritePort(port, scmd, buf, len, rettype, unit)
  43. PORT *port;
  44. ubyte *buf;
  45. {
  46.     register IOR *ior = (IOR *)AllocMem(sizeof(IOR), MEMF_PUBLIC);
  47.  
  48.     if (DDebug)
  49.     printf("WritePort: cmd %ld  buflen %ld  rt %ld unit %ld\n", scmd, len, rettype, unit);
  50.     ior->io_Message.mn_Node.ln_Name = (char *)rettype;
  51.     ior->io_Message.mn_ReplyPort = (rettype) ? IOSink : DNetPort;
  52.     ior->io_Unit = (struct Unit *)unit;
  53.     ior->io_Command = scmd;
  54.     ior->io_Error = 0;
  55.     ior->io_Data  = NULL;
  56.     ior->io_Length = 0;
  57.     ior->io_Actual = 0;
  58.     if (buf) {
  59.     ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
  60.     ior->io_Length = len;
  61.     CopyMem(buf, ior->io_Data, len);
  62.     }
  63.     PutMsg(port, ior);
  64.     if (rettype == PKT_REQ)
  65.     ++NumCon;
  66. }
  67.  
  68. /*
  69.  *  ALLOC_CHANNEL()
  70.  *
  71.  *    Allocate a channel.  Starting at a random point, find the first
  72.  *    free channel.  Return -1 if no free channels found.
  73.  */
  74.  
  75. alloc_channel()
  76. {
  77.     static ulong ran = 13;
  78.     long stamp[3];
  79.     register uword i;
  80.  
  81.     DateStamp(stamp);
  82.     ran = ((ran * 13) + 1) ^ (ran >> 9) + stamp[0] + stamp[1] + stamp[2];
  83.     for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
  84.     if (Chan[i].state == 0) {
  85.         return(i);
  86.     }
  87.     }
  88.     for (i = ran % MAXCHAN; i != 0xFFFF; --i) {  /*  Fixed 28 September 1988 */
  89.     if (Chan[i].state == 0) {
  90.         return(i);
  91.     }
  92.     }
  93.     return(-1);
  94. }
  95.  
  96. /*
  97.  *  Get next node in a linked list.  If a pointer to a list base
  98.  *  is passed, gets the first node in the linked list.    Returns
  99.  *  NULL if no further nodes in the list.
  100.  */
  101.  
  102. GetNext(node)
  103. NODE *node;
  104. {
  105.     register NODE *next = node->ln_Succ;
  106.     if (*(long *)next)
  107.     return((long)next);
  108.     return(NULL);
  109. }
  110.  
  111. /*
  112.  *  CHKBUF
  113.  *
  114.  *  Generate a two-byte checksum for data.  Uses a very simple, but
  115.  *  effective algorithm.
  116.  */
  117.  
  118. chkbuf(buf, bytes)
  119. register ubyte *buf;
  120. register uword bytes;
  121. {
  122.     register uword i;
  123.     register ubyte c1,c2;
  124.  
  125.     for (i = c1 = c2 = 0; i < bytes; ++i) {
  126.     c1 += buf[i];
  127.     c2 += c1;
  128.     }
  129.     c1 = -(c1 + c2);
  130.     return((c1<<8)|c2);
  131. }
  132.  
  133.  
  134. TimerOpen(req, sink)
  135. IOT *req;
  136. PORT *sink;
  137. {
  138.     if (OpenDevice("timer.device", UNIT_VBLANK, req, 0))
  139.     dneterror("timer.device");
  140.     req->tr_node.io_Message.mn_ReplyPort = sink;
  141.     req->tr_node.io_Command = TR_ADDREQUEST;
  142. }
  143.  
  144. TimerClose(req)
  145. IOT *req;
  146. {
  147.     CloseDevice(req);
  148.     req->tr_node.io_Device = NULL;
  149. }
  150.  
  151.  
  152. /*
  153.  *  RUNSERVER
  154.  *
  155.  *    Search the file [S:]DNET.SERVERS for the specified server and
  156.  *    attempt to LoadSeg()/CreateProc() it.  The port number must be
  157.  *    non-zero (allows commening out lines in DNET.SERVERS), and
  158.  *    regardless of whether the server is able to DListen(), it must
  159.  *    perform a small handshake sequence with DNET.
  160.  */
  161.  
  162. void
  163. RunServer(portnum)
  164. uword portnum;
  165. {
  166.     FILE *fi;
  167.     char buf[128];
  168.     char s1[64], s2[64];
  169.     long v1;
  170.     long seg;
  171.  
  172.     if (!portnum)
  173.     return;
  174.     if ((fi = fopen("dnet.servers", "r")) == NULL)
  175.     fi = fopen("s:dnet.servers", "r");
  176.     if (fi) {
  177.     while (fgets(buf, 128, fi)) {
  178.         if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
  179.         goto success;
  180.     }
  181.     fclose(fi);
  182.     }
  183.     return;
  184. success:
  185.     fclose(fi);
  186.     if (seg = LoadSeg(s1)) {
  187.     PNODE    *pnode;
  188.     PROC    *myproc;
  189.     PROC    *proc;
  190.     char    *name;
  191.     MSG    msg;
  192.  
  193.     myproc = (PROC *)FindTask(NULL);
  194.     pnode = AllocMem(sizeof(PNODE), MEMF_PUBLIC);
  195.     sprintf(pnode->name, "DNET.SERVER.%ld", portnum);
  196.     pnode->seg = seg;
  197.     if (proc = CreateProc(pnode->name, 0, pnode->seg, 4096)) {
  198.         proc = (PROC *)((char *)proc - OFFSET(proc,pr_MsgPort));
  199.         msg.mn_ReplyPort = &myproc->pr_MsgPort;
  200.         msg.mn_Node.ln_Name = s2;
  201.         printf("Starting Server: %s %s\n", s1, pnode->name);
  202.         PutMsg(&proc->pr_MsgPort, &msg);        /*  startup handshake */
  203.         WaitPort(&myproc->pr_MsgPort);
  204.         GetMsg(&myproc->pr_MsgPort);
  205.         AddTail(&SvList, pnode);
  206.     } else {
  207.         printf("Unable to start server: %s %s\n", s1, pnode->name);
  208.         FreeMem(pnode, sizeof(PNODE));
  209.     }
  210.     } else {
  211.     printf("Server not found: %s\n", s1);
  212.     }
  213. }
  214.  
  215. /*
  216.  *  This cleans up as best as possible, but if there are still ACTIVE
  217.  *  servers or any CLIENTS, this call will not completely get rid of
  218.  *  them...
  219.  *
  220.  *  Note that this call will KILL any servers automatically started up
  221.  *  by DNET and then UnLoadSeg() them.  If the server has already exited,
  222.  *  it simply unloads the server's segment.
  223.  */
  224.  
  225. dneterror(str)
  226. char *str;
  227. {
  228.     register short i;
  229.     if (str)
  230.     puts(str);
  231.     if (DNetPort) {
  232.     register IOR *ior;
  233.     Forbid();
  234.     while ((ior = (IOR *)RemHead(&TxList)) || (ior = (IOR *)GetMsg(DNetPort))) {
  235.         ior->io_Error = -1;
  236.         ReplyMsg(ior);
  237.     }
  238.     DeletePort(DNetPort);
  239.     Permit();
  240.     DNetPort = NULL;
  241.     }
  242.     if (Wto.tr_node.io_Device) {
  243.     if (Wto_act) {
  244.         AbortIO(&Wto);
  245.         WaitIO(&Wto);
  246.         Wto_act = 0;
  247.     }
  248.     TimerClose(&Wto);
  249.     }
  250.     if (Rto.tr_node.io_Device) {
  251.     if (Rto_act) {
  252.         AbortIO(&Rto);
  253.         WaitIO(&Rto);
  254.         Rto_act = 0;
  255.     }
  256.     TimerClose(&Rto);
  257.     }
  258.     if (Cto.tr_node.io_Device) {
  259.     if (Cto_act) {
  260.         AbortIO(&Cto);
  261.         WaitIO(&Cto);
  262.         Cto_act = 0;
  263.     }
  264.     TimerClose(&Cto);
  265.     }
  266.  
  267.     NetClose();
  268.     if (IOSink)
  269.     DeletePort(IOSink);
  270.     IOSink = NULL;
  271.     for (i = 0; i < MAXCHAN; ++i) {
  272.     if (Chan[i].state != CHAN_FREE && Chan[i].ior) {
  273.         Chan[i].ior->io_Error = -1;
  274.         Chan[i].state = CHAN_FREE;
  275.         ReplyMsg(Chan[i].ior);
  276.     }
  277.     }
  278.     {
  279.     register PNODE *pnode;
  280.     register PROC *proc;
  281.     while (pnode = (PNODE *)RemHead(&SvList)) {
  282.         Forbid();
  283.         while (proc = (PROC *)FindTask(pnode->name)) {
  284.         Signal(proc, SIGBREAKF_CTRL_C);
  285.         Permit();
  286.         printf("Waiting for server %s to exit\n", pnode->name);
  287.         Forbid();
  288.         }
  289.         Permit();
  290.         UnLoadSeg(pnode->seg);
  291.         FreeMem(pnode, sizeof(PNODE));
  292.     }
  293.     }
  294.     if (IPCPort)
  295.     CloseIPC(IPCPort);
  296.     if (DResBase)
  297.     CloseLibrary(DResBase);
  298.     exit(1);
  299. }
  300.  
  301. bzero(ptr, bytes)
  302. register ubyte *ptr;
  303. register long bytes;
  304. {
  305.     while (bytes--)
  306.     *ptr++ = 0;
  307. }
  308.  
  309. fixsignal(port)
  310. register PORT *port;
  311. {
  312.     if ((long)port->mp_MsgList.lh_Head != (long)&port->mp_MsgList.lh_Tail)
  313.     Signal(port->mp_SigTask, 1 << port->mp_SigBit);
  314. }
  315.  
  316. SetTimeouts(baud)
  317. {
  318.     WTimeoutVal = ((MAXPKT * 2) * 1000 / (baud / 10 + 1));
  319.     RTimeoutVal = ((MAXPKT + 50) * 1000 / (baud / 10 + 1));
  320.     WTimeoutVal *= 1000;
  321.     RTimeoutVal *= 1000;
  322. }
  323.  
  324.