home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 142.lha / DNet / dnet / subs.c < prev    next >
C/C++ Source or Header  |  1986-11-21  |  7KB  |  310 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 < MAXCHAN; --i) {
  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.         printf("Starting Server: %s %s\n", s1, pnode->name);
  201.         PutMsg(&proc->pr_MsgPort, &msg);        /*  startup handshake */
  202.         WaitPort(&myproc->pr_MsgPort);
  203.         GetMsg(&myproc->pr_MsgPort);
  204.         AddTail(&SvList, pnode);
  205.     } else {
  206.         printf("Unable to start server: %s %s\n", s1, pnode->name);
  207.         FreeMem(pnode, sizeof(PNODE));
  208.     }
  209.     } else {
  210.     printf("Server not found: %s\n", s1);
  211.     }
  212. }
  213.  
  214. /*
  215.  *  This cleans up as best as possible, but if there are still ACTIVE
  216.  *  servers or any CLIENTS, this call will not completely get rid of
  217.  *  them...
  218.  *
  219.  *  Note that this call will KILL any servers automatically started up
  220.  *  by DNET and then UnLoadSeg() them.  If the server has already exited,
  221.  *  it simply unloads the server's segment.
  222.  */
  223.  
  224. dneterror(str)
  225. char *str;
  226. {
  227.     register short i;
  228.     if (str)
  229.     puts(str);
  230.     if (DNetPort) {
  231.     register IOR *ior;
  232.     Forbid();
  233.     while ((ior = (IOR *)RemHead(&TxList)) || (ior = (IOR *)GetMsg(DNetPort))) {
  234.         ior->io_Error = -1;
  235.         ReplyMsg(ior);
  236.     }
  237.     DeletePort(DNetPort);
  238.     Permit();
  239.     DNetPort = NULL;
  240.     }
  241.     if (Wto.tr_node.io_Device) {
  242.     if (Wto_act) {
  243.         AbortIO(&Wto);
  244.         WaitIO(&Wto);
  245.         Wto_act = 0;
  246.     }
  247.     TimerClose(&Wto);
  248.     }
  249.     if (Rto.tr_node.io_Device) {
  250.     if (Rto_act) {
  251.         AbortIO(&Rto);
  252.         WaitIO(&Rto);
  253.         Rto_act = 0;
  254.     }
  255.     TimerClose(&Rto);
  256.     }
  257.     if (RNet) {
  258.     AbortIO(RNet);
  259.     WaitIO(RNet);
  260.     }
  261.     if (WNet)
  262.     NetWrite(NULL, 0, 0);
  263.     if (IOSink)
  264.     DeletePort(IOSink);
  265.     IOSink = NULL;
  266.     NetClose(&RNet, &WNet);
  267.     for (i = 0; i < MAXCHAN; ++i) {
  268.     if (Chan[i].state != CHAN_FREE && Chan[i].ior) {
  269.         Chan[i].ior->io_Error = -1;
  270.         Chan[i].state = CHAN_FREE;
  271.         ReplyMsg(Chan[i].ior);
  272.     }
  273.     }
  274.     {
  275.     register PNODE *pnode;
  276.     register PROC *proc;
  277.     while (pnode = (PNODE *)RemHead(&SvList)) {
  278.         Forbid();
  279.         while (proc = (PROC *)FindTask(pnode->name)) {
  280.         Signal(proc, SIGBREAKF_CTRL_C);
  281.         Permit();
  282.         printf("Waiting for server %s to exit\n", pnode->name);
  283.         Forbid();
  284.         }
  285.         Permit();
  286.         UnLoadSeg(pnode->seg);
  287.         FreeMem(pnode, sizeof(PNODE));
  288.     }
  289.     }
  290.     exit(1);
  291. }
  292.  
  293. bzero(ptr, bytes)
  294. register ubyte *ptr;
  295. register long bytes;
  296. {
  297.     while (bytes--)
  298.     *ptr++ = 0;
  299. }
  300.  
  301. fixsignal(port)
  302. register PORT *port;
  303. {
  304.     if ((long)port->mp_MsgList.lh_Head != (long)&port->mp_MsgList.lh_Tail) {
  305.     register ulong mask = 1 << port->mp_SigBit;
  306.     SetSignal(mask, mask);
  307.     }
  308. }
  309.  
  310.