home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / tmonit.exe / TMONITOR.C < prev    next >
C/C++ Source or Header  |  1995-01-06  |  10KB  |  342 lines

  1. /****************************************************************************
  2. **    File:    TMONITOR.C
  3. **
  4. **    Desc:    Sample telephony program
  5. **
  6. **        This NetWare Telephony Services program acts as an NLM.  It monitors
  7. **        a device for the delivered event, (calls being made), and reports them.
  8. **        It asks the user if they want to attempt to answer the call or not.
  9. **        At this time, it reports both incoming and outgoing calls.
  10. **
  11. **        This program is written for Watcom C/C++ 10.0a, using the NLM SDK.
  12. **
  13. **
  14. **        DISCLAIMER
  15. **
  16. **    Novell, Inc. makes no representations or warranties with respect to
  17. **    any NetWare software, and specifically disclaims any express or
  18. **    implied warranties of merchantability, title, or fitness for a
  19. **    particular purpose.
  20. **
  21. **    Distribution of any NetWare software is forbidden without the
  22. **    express written consent of Novell, Inc.  Further, Novell reserves
  23. **    the right to discontinue distribution of any NetWare software.
  24. **
  25. **    Novell is not responsible for lost profits or revenue, loss of use
  26. **    of the software, loss of data, costs of re-creating lost data, the
  27. **    cost of any substitute equipment or program, or claims by any party
  28. **    other than you.  Novell strongly recommends a backup be made before
  29. **    any software is installed.   Technical support for this software
  30. **    may be provided at the discretion of Novell.
  31. **
  32. **    Programmers:
  33. **
  34. **        Ini    Who                        Firm
  35. **        -----------------------------------------------------------------------
  36. **        KVW    Kevin V White                Novell Developer Support.
  37. **
  38. **    History:
  39. **
  40. **        When        Who    What
  41. **        -----------------------------------------------------------------------
  42. **        1/5/95    kvw    wrote code
  43. **        1/6/95    kvw    added comments, disclaimer
  44. */
  45.  
  46. /****************************************************************************
  47. **    Include headers, macros, function prototypes, etc.
  48. */
  49.  
  50.     /*------------------------------------------------------------------------
  51.     **    ANSI
  52.     */
  53.  
  54.     #include <stdio.h>
  55.     #include <conio.h>
  56.     #include <string.h>
  57.     #include <errno.h>
  58.     #include <process.h>
  59.     #include <signal.h>
  60.  
  61.     /*------------------------------------------------------------------------
  62.     ** Telephony Services
  63.     */
  64.     #include <acs.h>
  65.     #include <csta.h>
  66.  
  67. /*------------------------------------------------------------------------
  68. ** Just in case...
  69. */
  70. #ifndef BOOL
  71.     #define BOOL int
  72. #endif
  73.  
  74. /*------------------------------------------------------------------------
  75. ** Stack size for the thread
  76. */
  77. #define MY_STACK_SIZE 16384
  78.  
  79. /*------------------------------------------------------------------------
  80. ** These are for thread control, so the NLM and thread can synchronize
  81. ** close down.
  82. */
  83. BOOL NLM_exiting=FALSE;
  84. BOOL NLM_mainDone=FALSE;
  85. int NLM_threadCnt=0;
  86.  
  87. /*------------------------------------------------------------------------
  88. ** Global variables (ok, slap my wrist) used for getting events, and the
  89. ** stream handle.
  90. */
  91. ACSHandle_t acsHandle;
  92. InvokeID_t invokeID;
  93. DeviceID_t deviceToMonitor;
  94. CSTAEvent_t eventBuffer;
  95. unsigned short eventBufferSize;
  96. unsigned short numEvents;
  97.  
  98. /*------------------------------------------------------------------------
  99. ** This function is actually a thread.  It basicly sits in a poll loop
  100. ** getting all events from the queue, searching for delivered events.
  101. */
  102. void monitorFunc(void *arg)
  103. {
  104.     char ch;
  105.     RetCode_t rCode;
  106.     CSTAMonitorFilter_t monitorFilter;
  107.     CSTAMonitorCrossRefID_t monitorCrossRefID=0;
  108.  
  109.     /*------------------------------------------------------
  110.     ** Just do this so I don't get a compiler warning for
  111.     ** not using the argument
  112.     */
  113.     arg=arg;
  114.  
  115.     NLM_threadCnt++;
  116.  
  117.     /*------------------------------------------------------
  118.     ** I am only going to monitor for delivered events.
  119.     */
  120.     monitorFilter.call=~CF_DELIVERED;
  121.     /*------------------------------------------------------
  122.     ** Start the device type monitor.
  123.     */
  124.     rCode=cstaMonitorDevice(acsHandle,invokeID,&deviceToMonitor,&monitorFilter,NULL);
  125.  
  126.     /*------------------------------------------------------
  127.     ** If successful, enter event poll loop.
  128.     */
  129.     if(rCode>=0)
  130.     {
  131.         printf("\n\nWaiting for a call...");
  132.  
  133.         /*---------------------------------------------------
  134.         ** This flag gets set when SigTerm occurs, and the
  135.         ** NLM tries to shutdown
  136.         */
  137.         while(!NLM_exiting)
  138.         {
  139.             eventBufferSize=sizeof(CSTAEvent_t);
  140.             /*------------------------------------------------
  141.             ** Get an event, and check its type
  142.             */
  143.             rCode=acsGetEventPoll(acsHandle,&eventBuffer,&eventBufferSize,NULL,&numEvents);
  144.             if(rCode==ACSPOSITIVE_ACK)
  145.             {
  146.                 switch(eventBuffer.eventHeader.eventType)
  147.                 {
  148.                     /*-----------------------------------------------
  149.                     ** This is _probably_ the first event we'll get on
  150.                     ** our new monitor.  However, we can't guarantee
  151.                     ** that, so I handle it here in the switch.
  152.                     ** We need the CrossRefID for use when we shut down
  153.                     ** the monitor.
  154.                     */
  155.                     case CSTA_MONITOR_CONF:
  156.                         monitorCrossRefID=
  157.                             eventBuffer.event.cstaConfirmation.u.monitorStart.monitorCrossRefID;
  158.                         break;
  159.                     /*-----------------------------------------------
  160.                     ** When we get a delivered event, we are going
  161.                     ** to print out information on the screen and
  162.                     ** ask the user if they want to answer it.
  163.                     */
  164.                     case CSTA_DELIVERED:
  165.                         printf("\nAlerting:%s  Calling:%s  Called:%s",
  166.                             eventBuffer.event.cstaUnsolicited.u.delivered.alertingDevice.deviceID,
  167.                             eventBuffer.event.cstaUnsolicited.u.delivered.callingDevice.deviceID,
  168.                             eventBuffer.event.cstaUnsolicited.u.delivered.calledDevice.deviceID);
  169.  
  170.                         /*--------------------------------------------
  171.                         ** User wants to answer the call.  We'll try,
  172.                         ** but it's not guaranteed.  They might be on
  173.                         ** the other line, and since I'm not tracking
  174.                         ** other active calls, I don't have a callID
  175.                         ** to put the other call on hold first.
  176.                         ** If the cstaAnswerCall function fails, we
  177.                         ** don't do anything about it.
  178.                         */
  179.                         printf("\nTry to answer call? (y/n)");
  180.                         ch=getch();
  181.                         switch(ch)
  182.                         {
  183.                             case 'y':
  184.                             case 'Y':
  185.                                 cstaAnswerCall(acsHandle,invokeID,
  186.                                     &eventBuffer.event.cstaUnsolicited.u.delivered.connection,
  187.                                     NULL);
  188.                                 break;
  189.                         }
  190.  
  191.                         printf("\n\nWaiting for a call...");
  192.                         break;
  193.                 }
  194.             }
  195.  
  196.             /*------------------------------------------------
  197.             ** Give back some CPU time.
  198.             */
  199.             ThreadSwitchWithDelay();
  200.         }
  201.         /*---------------------------------------------------
  202.         ** We got here only because of NLM_exiting.  So, we
  203.         ** shut down the monitor.
  204.         */
  205.         if(monitorCrossRefID)
  206.             rCode=cstaMonitorStop(acsHandle,invokeID,monitorCrossRefID,NULL);
  207.  
  208.     }
  209.  
  210.     NLM_threadCnt--;
  211. }
  212.  
  213. /*---------------------------------------------------------
  214. ** This is used to replace the handler for SigTerm, which is
  215. ** triggered when the NLM is unloaded.
  216. */
  217. void mySigTerm(int sigType)
  218. {
  219.     /*------------------------------------------------------
  220.     ** Just use this so we don't get a compiler error for
  221.     ** not using the argument.
  222.     */
  223.     sigType=sigType;
  224.  
  225.     /*------------------------------------------------------
  226.     ** All we do is set NLM_exiting, so the threads all know
  227.     ** we wnat to exit.  Then, check the flags set when the
  228.     ** threads actually are ready to exit.
  229.     */
  230.     NLM_exiting=TRUE;
  231.     while((!NLM_mainDone)||(NLM_threadCnt))
  232.         ThreadSwitchWithDelay();
  233.     return;
  234. }
  235.  
  236. void main(void)
  237. {
  238.     int cCode;
  239.     char myStack[MY_STACK_SIZE];
  240.  
  241.     InvokeIDType_t    invokeIDType;
  242.     StreamType_t      streamType;
  243.     ServerID_t        serverID;
  244.     LoginID_t         loginID;
  245.     Passwd_t          password;
  246.     AppName_t         appName;
  247.     Level_t           acsLevel;
  248.     Version_t         acsVersion;
  249.     unsigned short  sendQSize,sendExtraBufs;
  250.     unsigned short  recvQSize,recvExtraBufs;
  251.     PrivateData_t     *privateData;
  252.     RetCode_t         rCode;
  253.  
  254.  
  255.     /*------------------------------------------------------
  256.     ** Set up my SigTerm handler for exiting the NLM.
  257.     */
  258.     signal(SIGTERM,mySigTerm);
  259.     SetAutoScreenDestructionMode(TRUE);
  260.  
  261.     invokeIDType=LIB_GEN_ID;
  262.     invokeID=0;
  263.     streamType=ST_CSTA;
  264.     strcpy(serverID,"ATT#G3_SWITCH#CSTA#KVWHITETEL");
  265.     printf("\nEnter your user name:");
  266.     scanf("%s",loginID);
  267.     printf("\nEnter your password:");
  268.     scanf("%s",password);
  269.     printf("\nEnter the extension to monitor:");
  270.     scanf("%s",deviceToMonitor);
  271.     strcpy(appName,"monitor");
  272.     acsLevel=ACS_LEVEL1;
  273.     strcpy(acsVersion,CSTA_API_VERSION);
  274.     sendQSize=sendExtraBufs=recvQSize=recvExtraBufs=15;
  275.     privateData=NULL;
  276.  
  277.     /*------------------------------------------------------
  278.     ** Open the stream with the data the user entered.
  279.     */
  280.     rCode=acsOpenStream(&acsHandle,invokeIDType,invokeID,streamType,&serverID,&loginID,&password,
  281.         &appName,acsLevel,&acsVersion,sendQSize,sendExtraBufs,recvQSize,recvExtraBufs,privateData);
  282.  
  283.     if(rCode<0)
  284.     {
  285.         printf("acsOpenStream failure...");
  286.         goto done;
  287.     }
  288.     else
  289.     {
  290.         printf("acsOpenStream success...");
  291.         invokeID=rCode;
  292.     }
  293.  
  294.     eventBufferSize=sizeof(CSTAEvent_t);
  295.     rCode=acsGetEventBlock(acsHandle,&eventBuffer,&eventBufferSize,privateData,&numEvents);
  296.     if(rCode==ACSPOSITIVE_ACK)
  297.     {
  298.         if(eventBuffer.eventHeader.eventType==ACS_OPEN_STREAM_CONF)
  299.         {
  300.             printf("event received for acsOpenStream");
  301.         }
  302.         else
  303.         {
  304.             printf("event type is incorrect on acsOpenStream");
  305.             goto done;
  306.         }
  307.     }
  308.     else
  309.     {
  310.         printf("acsGetEventBlock failure");
  311.         goto done;
  312.     }
  313.  
  314.     /*------------------------------------------------------
  315.     ** If the stream was successfully opened, we start a new
  316.     ** thread to monitor the device for delivered events.
  317.     */
  318.     cCode=BeginThread(monitorFunc,myStack,MY_STACK_SIZE,NULL);
  319.     if(cCode==EFAILURE)
  320.         goto closeStream;
  321.  
  322.     /*------------------------------------------------------
  323.     ** Just sit and wait for the NLM to exit.  The other thread
  324.     ** does all the work while this one just sits back and
  325.     ** relaxes.  Of course, we give the CPU time back.
  326.     */
  327.     while((NLM_threadCnt) || (!NLM_exiting))
  328.     {
  329.         ThreadSwitchWithDelay();
  330.     }
  331.  
  332.     /*------------------------------------------------------
  333.     ** close the stream
  334.     */
  335. closeStream:
  336.     acsAbortStream(acsHandle,NULL);
  337.  
  338. done:
  339.     NLM_mainDone=TRUE;
  340.     return;
  341. }
  342.