home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / dax1.exe / CP / CPS / CPRECV.C < prev    next >
Text File  |  1992-07-15  |  11KB  |  243 lines

  1. //   ╔════════════════════════════════════════════════════════════════════╗
  2. //   ║                                                                    ║
  3. //   ║ module:      cprecv.c                                              ║
  4. //   ║ abstract:    This module contains the routines to handle incoming  ║
  5. //   ║              requests from clients.                                ║
  6. //   ║                                                                    ║
  7. //   ║ environment: NetWare 3.x v3.11                                     ║
  8. //   ║              Network C for NLMs SDK                                ║
  9. //   ║              CLib v3.11                                            ║
  10. //   ║                                                                    ║
  11. //   ║  This software is provided as is and carries no warranty           ║
  12. //   ║  whatsoever.  Novell disclaims and excludes any and all implied    ║
  13. //   ║  warranties of merchantability, title and fitness for a particular ║
  14. //   ║  purpose.  Novell does not warrant that the software will satisfy  ║
  15. //   ║  your requirements or that the software is without defect or error ║
  16. //   ║  or that operation of the software will be uninterrupted.  You are ║
  17. //   ║  using the software at your risk.  The software is not a product   ║
  18. //   ║  of Novell, Inc. or any of subsidiaries.                           ║
  19. //   ║                                                                    ║
  20. //   ╟────────────────────────────────────────────────────────────────────╢
  21. //   ║ maintenance history:                                               ║
  22. //   ║ level    date      pi   description                                ║
  23. //   ╟────────────────────────────────────────────────────────────────────╢
  24. //   ║  001   01/29/92    kl   initial release.                           ║
  25. //   ╚════════════════════════════════════════════════════════════════════╝
  26.  
  27. #include <string.h>
  28. #include <nwsemaph.h>
  29. #include <process.h>
  30. #include <errno.h>
  31. #include "cp/cpsys.h"
  32.  
  33. //------------------------------------------------------------------------
  34.  
  35. //
  36. //  Miscellaneous variables needed by this module.
  37. //
  38.  
  39. STATIC  LONG    recvSemaHandle;     // used in recv ECBs
  40. STATIC  IPX_ECB *recvQueueHead;     // queue head pointer (ipx)
  41. STATIC  LONG    recvThreadID;       // id of this thread
  42.  
  43. //
  44. //
  45. //  'recvs' is an array of structures, each one having what we need to
  46. //  receive a single request from a client.
  47. //
  48.  
  49. STATIC  CPCOMMDATA  recvs[CPSNUMRECVELEM];
  50.  
  51. //
  52. //  This variable contains a pointer to the API in the DAP layer that
  53. //  will be called when a new request is received by the CP Layer.
  54. //
  55.  
  56. STATIC  (*DAPEnqueueRequest)(UINT32, void *);
  57.  
  58. //------------------------------------------------------------------------
  59.  
  60. //   **********************************************************************
  61. //   *  Initialize an Ipx Listen ECB and Packet                           *
  62. //   **********************************************************************
  63. void    CPInitRecvPacket(WORD     socket,       // socket to receive on
  64.                        long       semHandle,    // IPX will signal if non-zero
  65.                        IPX_ECB    **queueHead,  // ptr to linked list when cplt
  66.                        IPX_ECB    *ecb,         // the ecb
  67.                        IPX_HEADER *hdr,         // the ipx header
  68.                        void       *reply,       // the data portion
  69.                        WORD       sizeReply)    // the data portion size
  70. {
  71.         //
  72.         //  The semHandle field, if set, will cause IPX to call
  73.         //  SignalLocalSemaphore with this handle, when a packet is received.
  74.         //  This way, you can block a thread from execution via WaitOnLocalSem
  75.         //  until a message comes in. No need for ESR's!
  76.         //
  77.         ecb->semHandle               = semHandle;
  78.         //
  79.         //  Note that since the socket is a parameter to the IPX CLIB
  80.         //  functions, it can be init'ed here, or simply passed via Receive.
  81.         //  If you init here, then pass 0 when you call IpxReceive...
  82.         //
  83.         ecb->socket                  = socket;
  84.         //
  85.         //  Queuehead is a pointer to an ECB pointer that will be set to
  86.         //  point to a completed ECB.  It will be used to form a double-
  87.         //  threaded linked list of completed ECB's.
  88.         //
  89.         ecb->queueHead               = queueHead;
  90.         ecb->fragCount               = 2;
  91.         ecb->fragList[0].fragAddress = hdr;
  92.         ecb->fragList[0].fragSize    = sizeof( IPX_HEADER );
  93.         ecb->fragList[1].fragAddress = reply;
  94.         ecb->fragList[1].fragSize    = sizeReply;
  95. }
  96.  
  97. //   **********************************************************************
  98. //   *  This is the thread that monitors the queuehead pointer waiting    *
  99. //   *  for incoming messages. It then verifies a valid client sent the   *
  100. //   *  message (registers a new client if necessary), then enqueues the  *
  101. //   *  request to the DAP layer via the API registered during init.      *
  102. //   **********************************************************************
  103.  
  104. STATIC  void    CPRecvMessageThread(void *threadID)
  105. {
  106.         IPX_ECB         *queuedECB;
  107.         IPX_ECB         *recvECB, *nextECB;
  108.         IPX_HEADER      *IPXinfo;
  109.         CPMESSAGE       *CPinfo;
  110.         UINT32          sessionID;
  111.  
  112.         *(LONG *)threadID = GetThreadID();
  113.         xDIAG1(RenameThread(GetThreadID(),"CP_RECV"));
  114.  
  115.         #define SuspendOrStop() if(!recvSemaHandle){*(LONG *)threadID = 0; ExitThread(EXIT_THREAD,0);}
  116.  
  117.         while( 1 ){
  118.             //
  119.             //  Wait for an ECB(s) to be posted off the queueHead
  120.             //
  121.             SuspendOrStop();
  122.             WaitOnLocalSemaphore(recvSemaHandle);
  123.             SuspendOrStop();
  124.             //
  125.             //  Since we can handle multiple requests in the loop below,
  126.             //  we might wake up from the semaphore without any work to
  127.             //  be done.  If this is the case, just wait again...
  128.             //
  129.             if( !recvQueueHead ) continue;
  130.             //
  131.             //  Get and clear the queue head pointer.
  132.             //
  133.             nextECB = (queuedECB = IpxGetAndClearQ(&recvQueueHead))->prev;
  134.             do{
  135.                 //
  136.                 //  Process the newly received request
  137.                 //
  138.                 recvECB = nextECB;
  139.                 if( recvECB->status == NULL ){  // if successful receive...
  140.                     DIAG4("*\n* Received new request\n*");
  141.                     //
  142.                     //  get the session id, allocate if necessary
  143.                     //
  144.                     IPXinfo = (IPX_HEADER *)recvECB->fragList[0].fragAddress;
  145.                     CPinfo  = (CPMESSAGE  *)recvECB->fragList[1].fragAddress;
  146.                     //
  147.                     //  Get the session ID on whoever sent this...
  148.                     //
  149.                     //<<!!>>
  150.                     //  Enhance by creating some way to tell the client we
  151.                     //  were unable to allocate a session for him...
  152.                     //<<!!>>
  153.                     if( (sessionID = CPGetSessionID(IPXinfo,CPinfo) ) != -1){
  154.                         //
  155.                         //  enqueue the request.  Note how we'll just ignore
  156.                         //  the request if we can't get a session ID.
  157.                         //!!
  158.                         //  Need to authenticate the session ID in the
  159.                         //  EnqueueRequest API I guess... That is, make
  160.                         //  sure from the DAP perspective that this is
  161.                         //  a valid match 'sessionID' and DAPserverid.
  162.                         //!!
  163.                         DAPEnqueueRequest(sessionID,CPinfo->msg);
  164.                     }
  165.                     else{
  166.                         DIAG1("Unable to get sessionID for client");
  167.                     }
  168.                 }
  169.                 else{
  170.                     HEXDIAG1("Error receiving message: ",recvECB->status);
  171.                 }
  172.                 //
  173.                 //  Traverse the linked list backwards, in the order they
  174.                 //  were received by IPX.
  175.                 //
  176.                 nextECB = recvECB->prev;
  177.                 //
  178.                 //  Resubmit the ECB to IPX to receive next message.
  179.                 //
  180.                 IpxReceive(CPGetAdvertisingSocket(), recvECB);
  181.                 //
  182.                 //  Don't hog the CPU!
  183.                 //
  184.                 SuspendOrStop();
  185.                 ThreadSwitch();
  186.                 //
  187.                 //  When recvECB == queuedECB, we have reached the end of
  188.                 //  the linked list.  Loop back and wait for another message.
  189.                 //
  190.             }while( recvECB != queuedECB );     // until end of list
  191.         }
  192. }
  193.  
  194. T_RC    CPInitializeRecvLogic(void (*EnqueueRequestAPI)(UINT32, void *))
  195. {
  196.         int     i;
  197.         WORD    socket = CPGetAdvertisingSocket();
  198.         //
  199.         //  We need a local semaphore to block the receive thread
  200.         //
  201.         if( (recvSemaHandle = OpenLocalSemaphore(0)) == -1){
  202.             recvSemaHandle = 0;         // so we don't accidentally close it
  203.             return CP_RESOURCE_ERROR;
  204.         }
  205.         //
  206.         //  Remember the API that will be called by the receiving thread
  207.         //  that will handle any incoming requests.
  208.         //
  209.         DAPEnqueueRequest = EnqueueRequestAPI;
  210.         //
  211.         //  Get our recv ECBs ready.
  212.         //
  213.         for(i=0; i < CPSNUMRECVELEM; ++i){
  214.             CPInitRecvPacket(socket,
  215.                              recvSemaHandle,
  216.                              &recvQueueHead,
  217.                              &recvs[i].ecb,
  218.                              &recvs[i].ipx,
  219.                              &recvs[i].cpmsg,
  220.                              sizeof recvs[i].cpmsg);
  221.             IpxReceive(socket, &recvs[i].ecb);
  222.         }
  223.         if( BeginThread(CPRecvMessageThread,NULL,8192,&recvThreadID) == EFAILURE ){
  224.             return CP_RESOURCE_ERROR;
  225.         }
  226.         ThreadSwitch();
  227.         return CP_SUCCESS;
  228. }
  229.  
  230. void    CPDeInitializeRecvLogic()
  231. {
  232.         int     i;
  233.  
  234.         if( recvSemaHandle ) CloseLocalSemaphore(recvSemaHandle);
  235.         //
  236.         //  If any packets are still pending, cancel them.
  237.         //
  238.         for(i=0; i < CPSNUMRECVELEM; ++i){
  239.             if( recvs[i].ecb.status > 0 && recvs[i].ecb.status < 0xF000 )
  240.                 IpxCancelEvent(&recvs[i].ecb);
  241.         }
  242. }
  243.