home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff294.lzh / DNet / amiga / dnet / subs.c < prev    next >
C/C++ Source or Header  |  1989-12-11  |  10KB  |  514 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. #ifdef LATTICE
  12. #include <dos.h>
  13. #endif
  14.  
  15. #ifndef LATTICE
  16. char *FakeArgs;
  17. long  FakeLen;
  18. long  FakeGo;
  19. long  FakeCLI;
  20.  
  21. extern char *malloc();
  22. #endif
  23.  
  24. void dneterror();
  25.  
  26. typedef struct CommandLineInterface CLI;
  27.  
  28. /*
  29.  *  Add the high-level command to the queue of commands to be sent to
  30.  *  the remote DNET.
  31.  */
  32.  
  33. void
  34. WriteStream(sdcmd, buf, len, chan)
  35. int sdcmd;
  36. void *buf;
  37. int len;
  38. uword chan;
  39. {
  40.     IOSTD *ior = AllocMem(sizeof(IOSTD), MEMF_PUBLIC);
  41.  
  42.     if (DDebug)
  43.     printf("WriteStream: cmd %ld  buflen %ld  chan %ld\n", sdcmd, len, chan);
  44.     ior->io_Message.mn_Node.ln_Name = (char *)PKT_REQ;
  45.     ior->io_Message.mn_ReplyPort = IOSink;
  46.     ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
  47.     ior->io_Length = len;
  48.     ior->io_Actual = 0;
  49.     ior->io_Command = sdcmd;
  50.     ior->io_Error = 0;
  51.     ior->io_Message.mn_Node.ln_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
  52.     BMov(buf, ior->io_Data, len);
  53.     Enqueue(&TxList, (NODE *)ior);
  54.     do_wupdate();
  55. }
  56.  
  57. /*
  58.  *  Send a packet to a port.  Used to send data/eof/close to channel
  59.  *  ports, and to relay open requests to server ports.
  60.  */
  61.  
  62. void
  63. WritePort(port, scmd, buf, len, rettype, unit)
  64. PORT *port;
  65. int scmd;
  66. void *buf;
  67. int len;
  68. int rettype;
  69. int unit;
  70. {
  71.     IOSTD *ior = AllocMem(sizeof(IOSTD), MEMF_PUBLIC);
  72.  
  73.     if (DDebug)
  74.     printf("WritePort: cmd %ld  buflen %ld  rt %ld unit %ld\n", scmd, len, rettype, unit);
  75.     ior->io_Message.mn_Node.ln_Name = (char *)rettype;
  76.     ior->io_Message.mn_ReplyPort = (rettype) ? IOSink : DNetPort;
  77.     ior->io_Unit = (struct Unit *)unit;
  78.     ior->io_Command = scmd;
  79.     ior->io_Error = 0;
  80.     ior->io_Data  = NULL;
  81.     ior->io_Length = 0;
  82.     ior->io_Actual = 0;
  83.     if (buf) {
  84.     ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
  85.     ior->io_Length = len;
  86.     BMov(buf, ior->io_Data, len);
  87.     }
  88.     PutMsg(port, (MSG *)ior);
  89.     if (rettype == PKT_REQ)
  90.     ++NumCon;
  91. }
  92.  
  93. /*
  94.  *  ALLOC_CHANNEL()
  95.  *
  96.  *    Allocate a channel.  Starting at a random point, find the first
  97.  *    free channel.  Return -1 if no free channels found.
  98.  */
  99.  
  100. alloc_channel()
  101. {
  102.     static ulong ran = 13;
  103.     long stamp[3];
  104.     uword i;
  105.  
  106.     DateStamp(stamp);
  107.     ran = ((ran * 13) + 1) ^ (ran >> 9) + stamp[0] + stamp[1] + stamp[2];
  108.     for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
  109.     if (Chan[i].state == 0) {
  110.         return((int)i);
  111.     }
  112.     }
  113.     for (i = ran % MAXCHAN; i != 0xFFFF; --i) {  /*  Fixed 28 September 1988 */
  114.     if (Chan[i].state == 0) {
  115.         return((int)i);
  116.     }
  117.     }
  118.     return(-1);
  119. }
  120.  
  121. /*
  122.  *  Get next node in a linked list.  If a pointer to a list base
  123.  *  is passed, gets the first node in the linked list.    Returns
  124.  *  NULL if no further nodes in the list.
  125.  */
  126.  
  127. GetNext(node)
  128. NODE *node;
  129. {
  130.     NODE *next = node->ln_Succ;
  131.     if (*(long *)next)
  132.     return((long)next);
  133.     return(NULL);
  134. }
  135.  
  136. /*
  137.  *  CHKBUF
  138.  *
  139.  *  Generate a two-byte checksum for data.  Uses a very simple, but
  140.  *  effective algorithm.
  141.  */
  142.  
  143. chkbuf(buf, bytes)
  144. ubyte *buf;
  145. uword bytes;
  146. {
  147.     uword i;
  148.     ubyte c1,c2;
  149.  
  150.     for (i = c1 = c2 = 0; i < bytes; ++i) {
  151.     c1 += buf[i];
  152.     c2 += c1;
  153.     }
  154.     c1 = -(c1 + c2);
  155.     return((c1<<8)|c2);
  156. }
  157.  
  158. void
  159. TimerOpen(req, sink)
  160. IOT *req;
  161. PORT *sink;
  162. {
  163.     if (OpenDevice("timer.device", UNIT_VBLANK, (IOR *)req, 0))
  164.     dneterror("timer.device");
  165.     req->tr_node.io_Message.mn_ReplyPort = sink;
  166.     req->tr_node.io_Command = TR_ADDREQUEST;
  167. }
  168.  
  169. void
  170. TimerClose(req)
  171. IOT *req;
  172. {
  173.     CloseDevice((IOR *)req);
  174.     req->tr_node.io_Device = NULL;
  175. }
  176.  
  177.  
  178. /*
  179.  *  RUNSERVER
  180.  *
  181.  *    Search the file [S:]DNET.SERVERS for the specified server and
  182.  *    attempt to LoadSeg()/CreateProc() it.  The port number must be
  183.  *    non-zero (allows commening out lines in DNET.SERVERS), and
  184.  *    regardless of whether the server is able to DListen(), it must
  185.  *    perform a small handshake sequence with DNET.
  186.  */
  187.  
  188. #ifdef LATTICE
  189.  
  190. static struct ProcID *SvBase;
  191.  
  192. void
  193. InitServers()
  194. {
  195.     SvBase = NULL;
  196. }
  197.  
  198. void
  199. RunServer(portnum)
  200. uword portnum;
  201. {
  202.     FILE *fi;
  203.     char buf[128];
  204.     char s1[64], s2[64];
  205.     long v1;
  206.  
  207.     if (!portnum)
  208.     return;
  209.     if ((fi = fopen("dnet.servers", "r")) == NULL)
  210.     fi = fopen("s:dnet.servers", "r");
  211.     if (fi) {
  212.     while (fgets(buf, 128, fi)) {
  213.         if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
  214.         goto success;
  215.     }
  216.     fclose(fi);
  217.     }
  218.     return;
  219. success:
  220.     fclose(fi);
  221.  
  222.     {
  223.     PROC    *myproc;
  224.     MSG    msg;
  225.     struct ProcID *pid = malloc(sizeof(struct ProcID));
  226.     int error;
  227.  
  228.     BZero(pid, sizeof(*pid));
  229.     error = forkl(s1, "__dnet", "__dnet", NULL, NULL, pid);
  230.  
  231.     if (error < 0) {
  232.         printf("Server not found: %s\n", s1);
  233.         free(pid);
  234.     } else {
  235.         myproc = (PROC *)FindTask(NULL);
  236.  
  237.         msg.mn_ReplyPort = &myproc->pr_MsgPort;
  238.         msg.mn_Node.ln_Name = s2;
  239.         printf("Starting Server: %s proc %08lx  ", s1, pid->process);
  240.         fflush(stdout);
  241.         PutMsg(&pid->process->pr_MsgPort, &msg);       /*  startup handshake */
  242.         WaitPort(&myproc->pr_MsgPort);
  243.         (void)GetMsg(&myproc->pr_MsgPort);
  244.         puts("started");
  245.         fflush(stdout);
  246.         pid->nextID = SvBase;
  247.         SvBase = pid;
  248.     }
  249.     }
  250. }
  251.  
  252. void
  253. DeleteServers()
  254. {
  255.     struct ProcID *pid, *pn;
  256.  
  257.     for (pid = SvBase; pid; pid = pn) {
  258.     pn = pid->nextID;
  259.     for (;;) {
  260.         Signal((TASK *)pid->process, SIGBREAKF_CTRL_C);
  261.         printf("Waiting for pid %08lx to die\n", pid->process);
  262.         if (CheckPort(pid->parent))
  263.         break;
  264.         Delay(10);
  265.     }
  266.     wait(pid);
  267.     free(pid);
  268.     }
  269. }
  270.  
  271. #else
  272.  
  273. static MLIST SvList;
  274.  
  275. void
  276. InitServers()
  277. {
  278.     NewList(&SvList);
  279. }
  280.  
  281. void
  282. RunServer(portnum)
  283. uword portnum;
  284. {
  285.     FILE *fi;
  286.     char buf[128];
  287.     char s1[64], s2[64];
  288.     long v1;
  289.     long seg;
  290.  
  291.     if (!portnum)
  292.     return;
  293.     if ((fi = fopen("dnet.servers", "r")) == NULL)
  294.     fi = fopen("s:dnet.servers", "r");
  295.     if (fi) {
  296.     while (fgets(buf, 128, fi)) {
  297.         if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
  298.         goto success;
  299.     }
  300.     fclose(fi);
  301.     }
  302.     return;
  303. success:
  304.     fclose(fi);
  305.  
  306.     if (seg = (long)LoadSeg(s1)) {
  307.     PNODE    *pnode;
  308.     PROC    *myproc;
  309.     PROC    *proc;
  310.     char    *name;
  311.     BSTR    oldclicmd;
  312.     CLI    *cli;
  313.     char    *fakestr;
  314.  
  315.     MSG    msg;
  316.     void    fakeseg();
  317.  
  318.     printf("Addr: %08lx\n", seg);
  319.  
  320.     myproc = (PROC *)FindTask(NULL);
  321.     pnode = AllocMem(sizeof(PNODE), MEMF_PUBLIC);
  322.     sprintf(pnode->name, "DNET.SERVER.%ld", portnum);
  323.     pnode->seg = seg;
  324.  
  325.     FakeArgs= "__dnet";
  326.     FakeLen = 6;
  327.     FakeGo    = ((long)pnode->seg << 2) + 4;
  328.     FakeCLI = (long)myproc->pr_CLI;
  329.  
  330.     printf("Addr: %08lx %08lx\n", seg, FakeGo);
  331.  
  332.     fakestr = malloc(32);
  333.     strcpy(fakestr, "\006__dnet");
  334.     cli = BTOC(FakeCLI);
  335.     oldclicmd = cli->cli_CommandName;
  336.     cli->cli_CommandName = CTOB(fakestr);
  337.  
  338.     if (proc = CreateProc(pnode->name, 0, (long)fakeseg >> 2, 4096)) {
  339.         proc = (PROC *)((char *)proc - OFFSET(proc,pr_MsgPort));
  340.         msg.mn_ReplyPort = &myproc->pr_MsgPort;
  341.         msg.mn_Node.ln_Name = s2;
  342.         printf("Starting Server: %s %s\n", s1, pnode->name);
  343.         PutMsg(&proc->pr_MsgPort, &msg);        /*  startup handshake */
  344.         WaitPort(&myproc->pr_MsgPort);
  345.         (void)GetMsg(&myproc->pr_MsgPort);
  346.         AddTail(&SvList, pnode);
  347.     } else {
  348.         printf("Unable to start server: %s %s\n", s1, pnode->name);
  349.         FreeMem(pnode, sizeof(PNODE));
  350.     }
  351.     cli->cli_CommandName = oldclicmd;
  352.     free(fakestr);
  353.     } else {
  354.     printf("Server not found: %s\n", s1);
  355.     }
  356. }
  357.  
  358. void
  359. DeleteServers()
  360. {
  361.     PNODE *pnode;
  362.     PROC *proc;
  363.     while (pnode = (PNODE *)RemHead(&SvList)) {
  364.     Forbid();
  365.     while (proc = (PROC *)FindTask(pnode->name)) {
  366.         Signal(proc, SIGBREAKF_CTRL_C);
  367.         Permit();
  368.         printf("Waiting for server %s to exit\n", pnode->name);
  369.         Forbid();
  370.     }
  371.     Permit();
  372.     UnLoadSeg(pnode->seg);
  373.     FreeMem(pnode, sizeof(PNODE));
  374.     }
  375. }
  376.  
  377. #asm
  378.  
  379.     INCLUDE "exec/types.i"
  380.     INCLUDE "exec/alerts.i"
  381.     INCLUDE "exec/nodes.i"
  382.     INCLUDE "exec/lists.i"
  383.     INCLUDE "exec/ports.i"
  384.     INCLUDE "exec/libraries.i"
  385.     INCLUDE "exec/tasks.i"
  386.  
  387.     INCLUDE "exec/memory.i"
  388.     INCLUDE "exec/execbase.i"
  389.     INCLUDE "libraries/dos.i"
  390.     INCLUDE "libraries/dosextens.i"
  391.  
  392.  
  393.     public    _geta4
  394.     public    _LVOFindTask
  395.  
  396.     nop
  397.     nop
  398.     nop
  399.     nop
  400. _fakeseg:
  401.     nop
  402.     nop
  403.     nop
  404.     nop
  405.  
  406.     bsr    _geta4
  407.     move.l    4,A6
  408.     sub.l    A1,A1
  409.     jsr    _LVOFindTask(A6)
  410.     move.l    D0,A0
  411.     move.l    _FakeCLI,pr_CLI(A0)     ; dummy CLI so Lattice startup doesn't
  412.                     ; croak thinking its a workbench process
  413.     move.l    _FakeArgs,A0
  414.     move.l    _FakeLen,D0
  415.     move.l    _FakeGo,A1
  416.     jmp    (A1)
  417.  
  418. #endasm
  419.  
  420. #endif
  421.  
  422. /*
  423.  *  This cleans up as best as possible, but if there are still ACTIVE
  424.  *  servers or any CLIENTS, this call will not completely get rid of
  425.  *  them...
  426.  *
  427.  *  Note that this call will KILL any servers automatically started up
  428.  *  by DNET and then UnLoadSeg() them.  If the server has already exited,
  429.  *  it simply unloads the server's segment.
  430.  */
  431.  
  432. void
  433. dneterror(str)
  434. char *str;
  435. {
  436.     short i;
  437.     if (str)
  438.     puts(str);
  439.     if (DNetPort) {
  440.     IOSTD *ior;
  441.     Forbid();
  442.     while ((ior = (IOSTD *)RemHead(&TxList)) || (ior = (IOSTD *)GetMsg(DNetPort))) {
  443.         ior->io_Error = -1;
  444.         ReplyMsg((MSG *)ior);
  445.     }
  446.     DeletePort(DNetPort);
  447.     Permit();
  448.     DNetPort = NULL;
  449.     }
  450.     if (Wto.tr_node.io_Device) {
  451.     if (Wto_act) {
  452.         AbortIO((IOR *)&Wto);
  453.         WaitIO((IOR *)&Wto);
  454.         Wto_act = 0;
  455.     }
  456.     TimerClose(&Wto);
  457.     }
  458.     if (Rto.tr_node.io_Device) {
  459.     if (Rto_act) {
  460.         AbortIO((IOR *)&Rto);
  461.         WaitIO((IOR *)&Rto);
  462.         Rto_act = 0;
  463.     }
  464.     TimerClose(&Rto);
  465.     }
  466.     if (Cto.tr_node.io_Device) {
  467.     if (Cto_act) {
  468.         AbortIO((IOR *)&Cto);
  469.         WaitIO((IOR *)&Cto);
  470.         Cto_act = 0;
  471.     }
  472.     TimerClose(&Cto);
  473.     }
  474.  
  475.     NetClose();
  476.     if (IOSink)
  477.     DeletePort(IOSink);
  478.     IOSink = NULL;
  479.     for (i = 0; i < MAXCHAN; ++i) {
  480.     if (Chan[i].state != CHAN_FREE && Chan[i].ior) {
  481.         Chan[i].ior->io_Error = -1;
  482.         Chan[i].state = CHAN_FREE;
  483.         ReplyMsg((MSG *)Chan[i].ior);
  484.     }
  485.     }
  486.     DeleteServers();
  487.  
  488.     /*
  489.     if (IPCPort)
  490.     CloseIPC(IPCPort);
  491.     if (DResBase)
  492.     CloseLibrary(DResBase);
  493.     */
  494.     exit(1);
  495. }
  496.  
  497. void
  498. fixsignal(port)
  499. PORT *port;
  500. {
  501.     if ((long)port->mp_MsgList.lh_Head != (long)&port->mp_MsgList.lh_Tail)
  502.     Signal(port->mp_SigTask, 1 << port->mp_SigBit);
  503. }
  504.  
  505. void
  506. SetTimeouts(baud)
  507. {
  508.     WTimeoutVal = ((MAXPKT * 2) * 1000 / (baud / 10 + 1));
  509.     RTimeoutVal = ((MAXPKT + 50) * 1000 / (baud / 10 + 1));
  510.     WTimeoutVal *= 1000;
  511.     RTimeoutVal *= 1000;
  512. }
  513.  
  514.