home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / xsap1a.exe / SERVER.C < prev    next >
Text File  |  1994-08-24  |  17KB  |  693 lines

  1. /****************************************************************************
  2. **    File:    SERVER.C
  3. **
  4. **    Desc:
  5. **
  6. **        Example of SAPing server process.  It listens on it's dynamic 
  7. **        socket for requests and services them.
  8. **
  9. **    Disclaimer:
  10. **
  11. **        Novell, Inc. makes no representations or warranties with respect to
  12. **        any NetWare software, and specifically disclaims any express or
  13. **        implied warranties of merchantability, title, or fitness for a
  14. **        particular purpose.  
  15. **
  16. **        Distribution of any NetWare software is forbidden without the
  17. **        express written consent of Novell, Inc.  Further, Novell reserves
  18. **        the right to discontinue distribution of any NetWare software.
  19. **
  20. **        Novell is not responsible for lost profits or revenue, loss of use
  21. **        of the software, loss of data, costs of re-creating lost data, the
  22. **        cost of any substitute equipment or program, or claims by any party
  23. **        other than you.  Novell strongly recommends a backup be made before
  24. **        any software is installed.   Technical support for this software
  25. **        may be provided at the discretion of Novell.
  26. **
  27. **
  28. **    QMK386 options used: None.
  29. **
  30. **    Programmers:
  31. **
  32. **        Ini    Who                        Firm
  33. **        -----------------------------------------------------------------------
  34. **        ABJ    Adam B. Jerome            Novell Developer Support.
  35. **
  36. **    History:
  37. **
  38. **        When        Who    What
  39. **        -----------------------------------------------------------------------
  40. **        08-19-94    ABJ    First code.
  41. */
  42.  
  43. /****************************************************************************
  44. **    Include headers, macros, function prototypes, etc.
  45. */
  46.     /*------------------------------------------------------------------------
  47.     **    ANSI
  48.     */
  49.     #include <stdlib.h>    /*    exit()    */
  50.     #include <stdio.h>    /* printf() */
  51.     #include <string.h>    /* strlen() */
  52.     #include <conio.h>      /* CreateScreen(), DestroyScreen() */
  53.     #include <process.h>    /* GetNLMHandle() */
  54.     #include <errno.h>    /* errno */
  55.     #include <signal.h>    /* signal(), SIGTERM, SIGINT */
  56.  
  57.     /*------------------------------------------------------------------------
  58.     **    NetWare
  59.     */
  60.     #include <advanced.h>    /* AllocatResourceTag() */
  61.     #include <nwsnut.h>        /* NWSRestoreNut(), NWSPushList(), ...*/
  62.     #include <nwipxspx.h>    /* IPXOpenSocket() */
  63.     #include <niterror.h>    /*    NetWareErrno */
  64.     #include <sap.h>            /* AdvertiseService(), ShutDownAdvertising() */
  65.     #include <nwsemaph.h>    /* OpenLocalSemaphore(), CloseLocalSemaphore() */
  66.     #include <nwmisc.h>        /* IntSwap() */
  67.  
  68.     /*------------------------------------------------------------------------
  69.     **    SERVER
  70.     */
  71.     #include "common.h"
  72.     #define NLM_MIN_ECBS            10            /* Initial number of ECBs    */
  73.  
  74.     typedef struct ECB_NODE
  75.         {
  76.         struct ECB_NODE *prior;
  77.         struct ECB_NODE *next;
  78.         IPX_ECB               ecb;
  79.         } ECB_NODE;
  80.  
  81. /****************************************************************************
  82. **    Global storage
  83. */
  84. unsigned short  NLM_serviceSocket = 0x0000;    /* zero value causes NetWare to allocate a socket dynamicly */
  85. int                 NLM_exiting        = 0;
  86. int                 NLM_threadCnt        = 0;
  87. LONG                 NLM_sapHandle        = (-1);
  88. IPX_ECB            *NLM_queueHead     = NULL;
  89. long                 NLM_semHandle        = 0;
  90. char                *NLM_serverName;
  91.  
  92. /****************************************************************************
  93. ** Signal handler.
  94. **
  95. **    Parameters:
  96. **
  97. **        int event            Signal event which occured.
  98. */
  99. void NLM_SignalHandler(int event)
  100.     {
  101.     switch(event)
  102.         {
  103.         case SIGTERM:
  104.             NLM_exiting = (-1);
  105.             while(NLM_threadCnt) ThreadSwitch();
  106.             delay(1000);
  107.             break;
  108.  
  109.         case SIGINT:
  110.             signal(SIGINT, NLM_SignalHandler);
  111.             break;
  112.         }
  113.     
  114.     return;
  115.     }
  116.  
  117. /****************************************************************************
  118. ** Allocate (or free) ECB nodes.
  119. **
  120. **    Parameters:
  121. **
  122. **        int buffers            Number of communication buffers to allocate;
  123. **                                or (0) zero to free all allocated buffers.
  124. */
  125. void NLM_AllocCommBuffers(int buffers)
  126.     {
  127.     static ECB_NODE *head = NULL;
  128.     static ECB_NODE *tail = NULL;
  129.     ECB_NODE *node;
  130.     int cCode;
  131.     int cnt;
  132.  
  133.     /*------------------------------------------------------------------------
  134.     **    Free nodes.
  135.     */
  136.     if(buffers == 0)
  137.         {
  138.         /*---------------------------------------------------------------------
  139.         **    Cancel events.
  140.         */
  141.         node=head;
  142.         while(node != NULL)
  143.             {
  144.             if(node->ecb.status > 0)
  145.                 {
  146.                 cCode=IpxCancelEvent(&node->ecb);
  147.                 switch(cCode)
  148.                     {
  149.                     case ESUCCESS:
  150.                         break;
  151.  
  152.                     case ERR_ECB_CANNOT_BE_CANCELLED:
  153.                         printf("ERROR:  ECB cannot be canceled.\n");
  154.                         break;
  155.  
  156.                     default:
  157.                         printf("ERROR:  IpxCancelEvent() returned unknown error %d.\n", cCode);
  158.                         break;
  159.                     }
  160.                 }
  161.  
  162.             node=node->next;
  163.             }
  164.  
  165.         /*---------------------------------------------------------------------
  166.         **    Free nodes.
  167.         */
  168.         while(head != NULL)
  169.             {
  170.             node=head;
  171.             head=head->next;
  172.  
  173.             if(node->ecb.fragList[0].fragAddress != NULL)
  174.                 free(node->ecb.fragList[0].fragAddress);
  175.  
  176.             if(node->ecb.fragList[1].fragAddress != NULL)
  177.                 free(node->ecb.fragList[1].fragAddress);
  178.  
  179.             free(node);
  180.             }
  181.         
  182.         goto END;
  183.         }
  184.  
  185.     /*------------------------------------------------------------------------
  186.     **    Allocate new nodes.
  187.     */
  188.     for(cnt=0; cnt<buffers; ++cnt)
  189.         {
  190.  
  191.         /*---------------------------------------------------------------------
  192.         **    Allocate an ECB_NODE.
  193.         */
  194.         node=(ECB_NODE *)malloc(sizeof(ECB_NODE));
  195.         if(node == NULL)
  196.             {
  197.             printf("ERROR:  Cannot allocate ECB_NODE.\n");
  198.             goto END_ERROR;
  199.             }
  200.         memset(node, 0x00, sizeof(ECB_NODE));
  201.  
  202.         /*---------------------------------------------------------------------
  203.         **    Initialize ECB.
  204.         */
  205.         node->ecb.queueHead     = &NLM_queueHead;
  206.         node->ecb.semHandle    = NLM_semHandle;
  207.         node->ecb.fragCount    = 2;
  208.         
  209.         node->ecb.fragList[0].fragSize        = sizeof(IPX_HEADER);
  210.         node->ecb.fragList[0].fragAddress    = malloc(sizeof(IPX_HEADER));
  211.         if(node->ecb.fragList[0].fragAddress == NULL) goto END_ERROR;
  212.  
  213.         node->ecb.fragList[1].fragSize        = COM_MAX_DATA_SIZE;
  214.         node->ecb.fragList[1].fragAddress    = malloc(COM_MAX_DATA_SIZE);
  215.         if(node->ecb.fragList[1].fragAddress == NULL) goto END_ERROR;
  216.  
  217.         /*---------------------------------------------------------------------
  218.         **    Link node into node list.
  219.         */
  220.         if(head == NULL)                /* Add node to empty list */
  221.             {
  222.             node->prior    =    NULL;
  223.             node->next     =     NULL;
  224.             head             =    node;
  225.             tail             =    node;
  226.             }
  227.          else                                /* Add node to end of list */
  228.             {
  229.             node->prior =    tail;
  230.             node->next     =    NULL;
  231.             tail->next    =    node;
  232.             tail             =    node;
  233.             }
  234.  
  235.         /*---------------------------------------------------------------------
  236.         **    Post the ECB.
  237.         */
  238.         cCode=IpxReceive(NLM_serviceSocket, &node->ecb);
  239.         switch(cCode)
  240.             {
  241.             case ESUCCESS:
  242.                 break;
  243.  
  244.             case ERR_SOCKET_NOT_OPEN:
  245.                 printf("ERROR:  Socket not open.\n");
  246.                 goto END_ERROR;
  247.  
  248.             case ERR_REQUEST_CANCELLED:
  249.                 printf("ERROR:  Request cancelled.\n");
  250.                 goto END_ERROR;
  251.  
  252.             case ERR_PACKET_OVERFLOW:
  253.                 printf("ERROR:  Packet overflow.\n");
  254.                 goto END_ERROR;
  255.  
  256.             case ERR_TIMEOUT_FAILURE:    /* ERROR_BAD_PACKET has same value. */
  257.                 printf("ERROR:  Timeout failure, or bad packet.\n");
  258.                 goto END_ERROR;
  259.  
  260.             default:
  261.                 printf("ERROR:  IpxRecieve() returned unknown error %d.\n", cCode);
  262.                 goto END_ERROR;
  263.             }
  264.  
  265.         }
  266.  
  267.     goto END;
  268.  
  269. END_ERROR:
  270.     if(node != NULL)
  271.         {
  272.         if(node->ecb.fragList[0].fragAddress != NULL)
  273.             free(node->ecb.fragList[0].fragAddress);
  274.  
  275.         if(node->ecb.fragList[1].fragAddress != NULL)
  276.             free(node->ecb.fragList[1].fragAddress);
  277.  
  278.         free(node);
  279.         }
  280.  
  281. END:
  282.     return;
  283.     }
  284.  
  285. /****************************************************************************
  286. ** Program shut down.
  287. */
  288. void NLM_Uninit(void)
  289.     {
  290.     int cCode;
  291.  
  292.     NLM_exiting = (-1);
  293.  
  294.     /*------------------------------------------------------------------------
  295.     ** Shut down server SAP advertising.
  296.     */
  297.     if(NLM_sapHandle != (-1))
  298.         {
  299.         cCode=ShutdownAdvertising(NLM_sapHandle);
  300.         switch(cCode)
  301.             {
  302.             case 0:
  303.                 break;
  304.  
  305.             default:
  306.                 printf("ERROR: ShutDownAdvertising() returned error code %d\n", cCode);
  307.             }
  308.         }
  309.  
  310.     /*------------------------------------------------------------------------
  311.     ** Free up list of ECBs.
  312.     */
  313.     NLM_AllocCommBuffers(0);
  314.  
  315.     /*------------------------------------------------------------------------
  316.     ** Give our semaphore back to NetWare.
  317.     */
  318.     if(NLM_semHandle)
  319.         {
  320.         cCode=CloseLocalSemaphore(NLM_semHandle);
  321.         switch(cCode)
  322.             {
  323.             case ESUCCESS:
  324.                 break;
  325.  
  326.             default:
  327.                 printf("ERROR: CloseLocalSemaphore() returned unknown error: %d\n", cCode);
  328.             }
  329.         }
  330.  
  331.     /*------------------------------------------------------------------------
  332.     ** Give our socket back to NetWare.
  333.     */
  334.     if(NLM_serviceSocket != 0x0000)
  335.         {
  336.         cCode=IpxCloseSocket(NLM_serviceSocket);
  337.         switch(cCode)
  338.             {
  339.             case ESUCCESS:
  340.                 break;
  341.  
  342.             default:
  343.                 printf("ERROR:  IpxCloseSocket() returned an unknown error: %d\n", cCode);
  344.                 break;
  345.             }
  346.         }
  347.     
  348.     return;
  349.     }
  350.  
  351. /****************************************************************************
  352. ** Handle a client Request.
  353. */
  354. void NLM_HandleRequest(void *vp)
  355.     {
  356.     COM_DATA_PACKET *p = (COM_DATA_PACKET *)vp;
  357.  
  358.     switch(p->type)
  359.         {
  360.         case COM_REQ_PING:
  361.             strcpy(p->data, "PONG");
  362.             p->status = COM_SUCCESS;
  363.             break;
  364.  
  365.         default:
  366.             p->status = COM_ERR_UNKNOWN_TYPE;
  367.             break;
  368.         }
  369.     
  370.     return;
  371.     }
  372.  
  373. /****************************************************************************
  374. ** Handle a client packet.
  375. */
  376. void NLM_HandlePacket(void *vArg)
  377.     {
  378.     IPX_ECB         *ecb = (IPX_ECB *)vArg;
  379.     IPX_HEADER    *ipxHdr = (IPX_HEADER *)ecb->fragList[0].fragAddress;
  380.     IPX_HEADER     hdr;
  381.     int cCode;
  382.  
  383.     /*------------------------------------------------------------------------
  384.     **    Service the client's request.    
  385.     */
  386.     NLM_HandleRequest(ecb->fragList[1].fragAddress);
  387.  
  388.     /*------------------------------------------------------------------------
  389.     **    Swap IPX header's source & destination.
  390.     */
  391.     memcpy(&hdr, &ipxHdr->destNet, sizeof(InternetAddress));
  392.     memcpy(&ipxHdr->destNet, &ipxHdr->sourceNet, sizeof(InternetAddress));
  393.     memcpy(&ipxHdr->sourceNet, &hdr, sizeof(InternetAddress));
  394.  
  395.     /*------------------------------------------------------------------------
  396.     **    Send the packet back to client.
  397.     */
  398.     cCode=IpxSend(0, ecb);
  399.     switch(cCode)
  400.         {
  401.         case ESUCCESS:
  402.             break;
  403.  
  404.         case ERR_NO_KNOWN_ROUTE_TO_DESTINATION:
  405.             printf("ERROR:  No known route to destination.\n");
  406.             NLM_exiting = (-1);
  407.             break;
  408.  
  409.         case ERR_REQUEST_CANCELLED:
  410.             printf("ERROR:  Request canceled.\n");
  411.             NLM_exiting = (-1);
  412.             break;
  413.  
  414.         case ERR_BAD_PACKET:
  415.             printf("ERROR:  Bad packet received.\n");
  416.             NLM_exiting = (-1);
  417.             break;
  418.  
  419.  
  420.         case HARDWARE_FAILURE:                             
  421.             printf("ERROR:  Hardware failure.\n");         
  422.             NLM_exiting = (-1);                                 
  423.             break;                                                 
  424.  
  425.         default:
  426.             printf("ERROR:  IpxSendPacket() returned an unknown error: %d.\n", cCode);
  427.             NLM_exiting = (-1);
  428.             break;
  429.         }
  430.  
  431.     /*------------------------------------------------------------------------
  432.     **    Re-post the ECB.
  433.     */
  434.     ecb->semHandle    = NLM_semHandle;
  435.     cCode=IpxReceive(NLM_serviceSocket, ecb);
  436.     switch(cCode)
  437.         {
  438.         case ESUCCESS:
  439.             break;
  440.  
  441.         case ERR_SOCKET_NOT_OPEN:
  442.             printf("ERROR:  Socket not open.\n");
  443.             NLM_exiting = (-1);
  444.             break;
  445.  
  446.         case ERR_REQUEST_CANCELLED:
  447.             printf("ERROR:  Request cancelled.\n");
  448.             NLM_exiting = (-1);
  449.             break;
  450.  
  451.         case ERR_PACKET_OVERFLOW:
  452.             printf("ERROR:  Packet overflow.\n");
  453.             NLM_exiting = (-1);
  454.             break;
  455.  
  456.         case ERR_TIMEOUT_FAILURE:    /* ERROR_BAD_PACKET has same value. */
  457.             printf("ERROR:  Timeout failure, or bad packet.\n");
  458.             break;
  459.  
  460.         default:
  461.             printf("ERROR:  IpxRecieve() returned unknown error %d.\n", cCode);
  462.             NLM_exiting = (-1);
  463.             break;
  464.         }
  465.  
  466.     return;
  467.     }
  468.  
  469. /****************************************************************************
  470. ** Watch for incomming client requests.
  471. */
  472. void NLM_PollForPackets(void *v)
  473.     {
  474.     int cCode;
  475.     IPX_ECB *head = NULL;
  476.     IPX_ECB *node;
  477.     int         threadID;
  478.     
  479.     v=v;
  480.  
  481.     while(!NLM_exiting)
  482.         {
  483.         /*---------------------------------------------------------------------
  484.         **    Wait for an ECB event.
  485.         */
  486.         cCode=WaitOnLocalSemaphore(NLM_semHandle);
  487.         switch(cCode)
  488.             {
  489.             case 0:
  490.                 break;
  491.  
  492.             default:
  493.                 printf("ERROR:  WaitOnLocalSemaphore() returned unknown error: %d.\n", cCode);
  494.                 NLM_exiting = (-1);
  495.                 break;
  496.             }
  497.  
  498.         /*---------------------------------------------------------------------
  499.         **    Get list of incomming ECBs.
  500.         */
  501.         if((head=IpxGetAndClearQ(&NLM_queueHead)) == NULL) continue;
  502.         while(head != NULL)
  503.             {
  504.             node=head;
  505.             head=head->next;
  506.  
  507.             threadID=BeginThread(NLM_HandlePacket, NULL, 0, node);
  508.             if(threadID == EFAILURE)
  509.                 {
  510.                 switch(errno)
  511.                     {
  512.                     case ENOMEM:
  513.                         printf("ERROR:  Not enough memory to begin event handler thread.\n");
  514.                         break;
  515.  
  516.                     case EINVAL:
  517.                         printf("ERROR:  Invalid argument was passed into BeginThread().\n");
  518.                         break;
  519.  
  520.                     default:
  521.                         printf("ERROR:  BeginThread() returned unknown error: %d.\n", errno);
  522.                         break;
  523.  
  524.                     }
  525.  
  526.                 NLM_exiting = (-1);
  527.                 break;
  528.                 }
  529.  
  530.             }
  531.  
  532.  
  533.         ThreadSwitch();
  534.         }
  535.  
  536.     return;
  537.     }
  538.  
  539. /****************************************************************************
  540. ** Program core process.
  541. */
  542. void NLM_Proc(void)
  543.     {
  544.     printf("<Press a key to unload>\n");
  545.     
  546.     while(!NLM_exiting)
  547.         {
  548.         /*---------------------------------------------------------------------
  549.         **    Alternate unload method.
  550.         */
  551.         if(kbhit())
  552.             {
  553.             if(!getch()) getch();
  554.             NLM_exiting = (-1);
  555.             }
  556.  
  557.         ThreadSwitch();
  558.         }
  559.  
  560.     return;
  561.     }
  562.  
  563. /****************************************************************************
  564. ** Program initialization.
  565. */
  566. void NLM_Init(int argC, char *argV[])
  567.     {
  568.     LONG cCode;
  569.     int  threadID;
  570.  
  571.     /*------------------------------------------------------------------------
  572.     ** Check and parse command-line args.
  573.     */
  574.     if(argC != 2)
  575.         {
  576.         printf("USAGE:   SERVER {NLM_serverName}\n");
  577.         cCode = (-1);
  578.         goto END;
  579.         }
  580.     NLM_serverName=argV[1];
  581.     if(strlen(NLM_serverName) > 47)
  582.         {
  583.         printf("ERROR:  Server name is too long.\n");
  584.         cCode = (-1);
  585.         goto END;
  586.         }
  587.  
  588.     /*------------------------------------------------------------------------
  589.     ** Register functions with NetWare.
  590.     */
  591.     signal(SIGINT,  NLM_SignalHandler);
  592.     signal(SIGTERM, NLM_SignalHandler);
  593.         
  594.     /*------------------------------------------------------------------------
  595.     ** Get NetWare to assign us a dynamic socket number.
  596.     */
  597.     cCode=IpxOpenSocket(&NLM_serviceSocket);
  598.     switch(cCode)
  599.         {
  600.         case ESUCCESS:
  601.             break;
  602.  
  603.         case ERR_IPX_NOT_INSTALLED:
  604.             printf("ERROR:  IPX is not installed.\n");
  605.             goto END;
  606.  
  607.         case ERR_SOCKET_ALREADY_OPEN:
  608.             printf("ERROR:  IPX socket 0x%04hX is already in use on this node.\n", NLM_serviceSocket);
  609.             goto END;
  610.  
  611.         case ERR_SOCKET_TABLE_FULL:
  612.             printf("ERROR:  IPX socket table is full on this node.\n");
  613.             goto END;
  614.  
  615.         default:
  616.             printf("ERROR:  IpxOpenSocket() returned an unknown error: %d\n", cCode);
  617.             goto END;
  618.         }
  619.  
  620.     /*------------------------------------------------------------------------
  621.     ** Open a local semaphore handle for receiving IPX packets.
  622.     */
  623.     NLM_semHandle=OpenLocalSemaphore(0);
  624.  
  625.     /*------------------------------------------------------------------------
  626.     ** Begin listening on socket for requests.
  627.     */
  628.     NLM_AllocCommBuffers(NLM_MIN_ECBS);
  629.  
  630.     /*------------------------------------------------------------------------
  631.     ** Begin advertising.
  632.     */
  633.     NLM_sapHandle=(int)AdvertiseService(
  634.         /* serverType         */    COM_SERVER_TYPE,
  635.         /* NLM_serverName        */    NLM_serverName,
  636.         /* NLM_serviceSocket    */    NLM_serviceSocket
  637.         );
  638.     if(NLM_sapHandle == (-1)) switch(NetWareErrno)
  639.         {
  640.         default:
  641.             printf("ERROR:  AdvertiseService() returned error code %d.\n", NetWareErrno);
  642.             goto END;
  643.         }
  644.  
  645.     /*------------------------------------------------------------------------
  646.     ** Begin listening for requests.
  647.     */
  648.     threadID=BeginThread(NLM_PollForPackets, NULL, 0, NULL);
  649.     if(threadID == EFAILURE)
  650.         {
  651.         switch(errno)
  652.             {
  653.             case ENOMEM:
  654.                 printf("ERROR:  Not enough memory to begin polling thread.\n");
  655.                 break;
  656.  
  657.             case EINVAL:
  658.                 printf("ERROR:  Invalid argument was passed into BeginThread().\n");
  659.                 break;
  660.  
  661.             default:
  662.                 printf("ERROR:  BeginThread() returned unknown error: %d.\n", errno);
  663.                 break;
  664.  
  665.             }
  666.  
  667.         NLM_exiting = (-1);
  668.         goto END;
  669.         }
  670.  
  671. END:
  672.     if(cCode) NLM_exiting=(-1);
  673.  
  674.     return;
  675.     }
  676.  
  677. /****************************************************************************
  678. ** Program start.
  679. */
  680. void main(int argC, char *argV[])
  681.     {
  682.     NLM_threadCnt++;
  683.  
  684.     NLM_Init(argC, argV);
  685.     NLM_Proc();
  686.     NLM_Uninit();
  687.     
  688.     NLM_threadCnt--;
  689.     exit(0);
  690.     }
  691.  
  692.  
  693.