home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / dax1.exe / DAP / DAPE / DAPSEND.C < prev    next >
Text File  |  1992-07-15  |  10KB  |  237 lines

  1. //   ╔════════════════════════════════════════════════════════════════════╗
  2. //   ║                                                                    ║
  3. //   ║ module:      dapsend.c                                             ║
  4. //   ║ abstract:    This module contains the send logic for the engine.   ║
  5. //   ║                                                                    ║
  6. //   ║ environment: NetWare 3.x v3.11                                     ║
  7. //   ║              Network C for NLMs SDK                                ║
  8. //   ║              CLib v3.11                                            ║
  9. //   ║                                                                    ║
  10. //   ║  This software is provided as is and carries no warranty           ║
  11. //   ║  whatsoever.  Novell disclaims and excludes any and all implied    ║
  12. //   ║  warranties of merchantability, title and fitness for a particular ║
  13. //   ║  purpose.  Novell does not warrant that the software will satisfy  ║
  14. //   ║  your requirements or that the software is without defect or error ║
  15. //   ║  or that operation of the software will be uninterrupted.  You are ║
  16. //   ║  using the software at your risk.  The software is not a product   ║
  17. //   ║  of Novell, Inc. or any of subsidiaries.                           ║
  18. //   ║                                                                    ║
  19. //   ╟────────────────────────────────────────────────────────────────────╢
  20. //   ║ maintenance history:                                               ║
  21. //   ║ level    date      pi   description                                ║
  22. //   ╟────────────────────────────────────────────────────────────────────╢
  23. //   ║  001   03/03/92    kl   initial release.                           ║
  24. //   ╚════════════════════════════════════════════════════════════════════╝
  25.  
  26. #include <stdio.h>
  27. #include <process.h>
  28. #include <nwsemaph.h>
  29. #include <library.h>
  30. #include <errno.h>
  31. #include "cp/cpapi.h"
  32. #include "dap/dapsys.h"
  33.  
  34. STATIC  DAPDATA     *queueHead;
  35. STATIC  LONG        sendSema;
  36. STATIC  LONG        sendThreadID;
  37.  
  38. //
  39. //  Link the structure onto the reply queue.  Signal the semaphore
  40. //  to wake up the Service Reply Queue thread.
  41. //
  42. //  This queue is ordered just like the Ipx queueHead implementation
  43. //  in CLib.  See NLM Reference Volume 1 for a complete description
  44. //  of queue Head pointers.
  45. //
  46. //  This API is called by the individual protocol routines to enqueue
  47. //  a reply to a client.
  48. //
  49.  
  50. void    DAPEnqueueServiceReply(DAPDATA *DAPid)
  51. {
  52.         char    *error = "EnqueueServiceReply called with %sactive DAPid (%x)\n";
  53.         //
  54.         //  Make sure the DAPid is in use, and that the state is DAP_SERVICE
  55.         //
  56.         DIAG4("EREP: validate DAPid");
  57.         if(!DAPInUse(DAPid)){
  58.             xDIAG1(DAPprintf(error, "in", DAPid));
  59.             return;
  60.         }
  61.         else if(!DAPStateActive(DAPid,DAP_SERVICE)){ 
  62.             DIAG1("EREP: called with bad state");
  63.             return;
  64.         }
  65.         //
  66.         //  Link this one onto the linked list.
  67.         //
  68.         DIAG4("EREP: linking DAPid onto list");
  69.         if( DAPid->next = queueHead ){
  70.             DAPid->prev = DAPid->next->prev;
  71.             DAPid->next->prev = DAPid;
  72.         }
  73.         else{
  74.             DAPid->prev = DAPid;
  75.         }
  76.         queueHead = DAPid;
  77.         //
  78.         //  Set state to 'sitting on the send queue'.
  79.         //
  80.         DAPStateON(DAPid,DAP_SENDQUEUE);
  81.         //
  82.         //  Tell the service thread "there's work to-be-done!"
  83.         //
  84.         DIAG4("EREP: waking up service reply queue thread");
  85.         if( sendSema ) SignalLocalSemaphore(sendSema);
  86. }
  87.  
  88. //
  89. //  This is the thread which services the reply queue.  It sends the
  90. //  reply via CPSendMessage, and then delinks the structure from the reply
  91. //  queue.
  92. //
  93.  
  94. STATIC  void    DAPServiceReplyQueue(void *threadID)
  95. {
  96.         int             rc;
  97.         DAPDATA         *queuedDAPid;
  98.         DAPDATA         *currDAPid, *nextDAPid;
  99.  
  100.         #define SuspendOrStop() if(!sendSema){*(LONG *)threadID = 0;ExitThread(EXIT_THREAD,0);}
  101.  
  102.         *(LONG *)threadID = GetThreadID();
  103.         xDIAG1(RenameThread(GetThreadID(),"DAP_SREP"));
  104.  
  105.         while( 1 ){
  106.             //
  107.             //  Wait for DAPid(s) to be posted to the queueHead
  108.             //
  109.             SuspendOrStop();
  110.             WaitOnLocalSemaphore(sendSema);
  111.             SuspendOrStop();
  112.             //
  113.             //  Since we can handle multiple requests in the loop below,
  114.             //  we might wake up from the semaphore without any work todo.
  115.             //  If this is the case, just wait again...
  116.             //
  117.             if( !queueHead ) continue;
  118.             //
  119.             //  Get and clear the queue head pointer.
  120.             //
  121.             nextDAPid = (queuedDAPid = queueHead)->prev, queueHead = NULL;
  122.             do{
  123.                 //
  124.                 //  Process the newly received request
  125.                 //
  126.                 DAPStateON( currDAPid = nextDAPid, DAP_SENDING );
  127.                 DAPStateOFF(currDAPid,DAP_SENDQUEUE);
  128.                 //
  129.                 //  Traverse the linked list backwards, in the order they
  130.                 //  were queued by DAPEnqueueServiceReply().
  131.                 //
  132.                 nextDAPid = currDAPid->prev;
  133.                 //
  134.                 //  Make final preparation to the dapReply structure.
  135.                 //
  136.                 currDAPid->dapReply.packetType = DAPSERVICEREPLY;
  137.                 currDAPid->dapReply.sequence = currDAPid->dapRequest.sequence;
  138.                 //
  139.                 //  Send the reply to the client
  140.                 //
  141.                 if( rc = CPSendMessage(currDAPid->CPid,
  142.                                        &currDAPid->dapReply, 
  143.                                        sizeof currDAPid->dapReply) ){
  144.                     DAPprintf("Error sending message: %x\n",currDAPid->CPid);
  145.                     xDIAG2(DAPprintf("CPSendMessage returned: %04x\n",rc));
  146.                 }
  147.                 else{
  148.                     xDIAG4(DAPprintf("Successful send to DAPid (%x)\n",currDAPid));
  149.                 }
  150.                 SuspendOrStop();
  151.                 //
  152.                 //  Show we are no longer sending
  153.                 //
  154.                 DAPStateOFF( currDAPid, DAP_SENDING );
  155.                 //
  156.                 //  Check to see if we need to release this structure.
  157.                 //  This flag is normally set on DAPDeAllocateSession()
  158.                 //  to tell me that I can free the entry after sending
  159.                 //  this final reply.
  160.                 //
  161.                 //!!
  162.                 //  Seems like we need to just save the CPSession index
  163.                 //  instead of a pointer.
  164.                 //!!
  165.                 //  Maybe combine the DAPFlags with DAPState...
  166.                 //  Try a test where the client tries to logout twice...
  167.                 //!!
  168.                 if( DAPFlagIsSet(currDAPid,DAP_FREE_THIS_SLOT) ) {
  169.                     //
  170.                     //  Tell the CP Layer to clear this client's session id
  171.                     //
  172.                     CPClearSessionID(currDAPid->CPid);
  173.                     //
  174.                     //  Release this structure back to free pool
  175.                     //  DAPDeAllocateSlot() doesn't care about the state
  176.                     //  of the session, other than if it is an allocated
  177.                     //  slot...
  178.                     //
  179.                     DAPDeAllocateSlot(currDAPid);
  180.                     xDIAG3(DAPprintf("DeAllocated DAPid (%x)\n", currDAPid));
  181.                 }
  182.                 else{
  183.                     //
  184.                     //  Mark this DAP structure as ready to use
  185.                     //
  186.                     currDAPid->next = currDAPid->prev = NULL;
  187.                     //
  188.                     //  By turning off the INUSE state, we allow the 
  189.                     //  receiving thread to post a new request to this
  190.                     //  client structure.
  191.                     //
  192.                     //  This state set on in the EnqueueServiceRequest API
  193.                     //
  194.                     DAPStateOFF( currDAPid, DAP_INUSE );
  195.                 }
  196.                 ThreadSwitch();
  197.                 SuspendOrStop();
  198.                 //
  199.                 //  When currDAPid == queuedDAPid, we have reached the end of
  200.                 //  the linked list.  Loop back and wait for another message.
  201.                 //
  202.             }while( currDAPid != queuedDAPid );     // until end of list
  203.         }
  204. }
  205.  
  206. T_RC    DAPInitializeSendLogic()
  207. {
  208.         //
  209.         //  We need a local semaphore to block the service thread
  210.         //
  211.         if( (sendSema = OpenLocalSemaphore(0)) == -1){
  212.             sendSema = 0;       // so we don't accidentally close it
  213.             DIAG4("Could not open DAP sending semaphore");
  214.             return DAP_RESOURCE_ERROR;
  215.         }
  216.         if( BeginThread(DAPServiceReplyQueue,NULL,8192,&sendThreadID) == EFAILURE ){
  217.             DIAG4("Could not start ServiceReplyQueue thread");
  218.             return DAP_RESOURCE_ERROR;
  219.         }
  220.         ThreadSwitch();         // let the thread run once...
  221.         DIAG4("DAP Send Logic has been initialized");
  222.         return DAP_SUCCESS;
  223. }
  224.  
  225. void    DAPDeInitializeSendLogic()
  226. {
  227.         //
  228.         //  Most of the time, this API will be called during atexit()
  229.         //  processing.
  230.         //
  231.         if( sendSema ){
  232.             CloseLocalSemaphore(sendSema);
  233.             sendSema = 0;       // signal thread to shut down ...
  234.         }
  235.         DIAG4("DAP Send Logic has been DE-initialized");
  236. }
  237.