VXIclient.c
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:74k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. /* -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  23.  */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <limits.h>
  28. #include <wchar.h>
  29. #include <VXIvalue.h>
  30. #include <VXItrd.h>
  31. #include <SBcache.h>
  32. #include <SBinet.h>
  33. #include <SBjsi.h>
  34. #include <SBlog.h>
  35. #include "SBlogListeners.h"
  36. #include <SWIprintf.h>
  37. /* VXIclient headers */
  38. #include "VXIclient.h"
  39. #ifdef WIN32
  40. #define WIN32_LEAN_AND_MEAN
  41. #include <windows.h>          /* For GetFullPathName() */
  42. /* Dynamic libraries */
  43. #ifdef NDEBUG
  44. /* OpenVXI impl */
  45. static const char VXIREC_LIB_NAME[]     = "VXIrec.dll";
  46. static const char VXIPROMPT_LIB_NAME[]  = "VXIprompt.dll";
  47. static const char VXITEL_LIB_NAME[]     = "VXItel.dll"; 
  48. /* Vocalocity impl */
  49. static const char QAREC_LIB_NAME[]      = "QArec.dll";
  50. static const char QAPROMPT_LIB_NAME[]   = "QAprompt.dll";
  51. static const char QATEL_LIB_NAME[]      = "QAtel.dll"; 
  52. #else  /* ! NDEBUG */
  53. /* OpenVXI impl */
  54. static const char VXIREC_LIB_NAME[]     = "VXIrecD.dll";
  55. static const char VXIPROMPT_LIB_NAME[]  = "VXIpromptD.dll";
  56. static const char VXITEL_LIB_NAME[]     = "VXItelD.dll"; 
  57. /* Vocalocity impl */
  58. static const char QAREC_LIB_NAME[]      = "QArecD.dll";
  59. static const char QAPROMPT_LIB_NAME[]   = "QApromptD.dll";
  60. static const char QATEL_LIB_NAME[]      = "QAtelD.dll"; 
  61. #endif /* NDEBUG */
  62. #else /* !WIN32 */
  63. #include <errno.h>
  64. #include <string.h>
  65. #ifdef NDEBUG
  66. /* OpenVXI impl */
  67. static const char VXIREC_LIB_NAME[]     = "libVXIrec.so.3";
  68. static const char VXIPROMPT_LIB_NAME[]  = "libVXIprompt.so.3";
  69. static const char VXITEL_LIB_NAME[]     = "libVXItel.so.3"; 
  70. /* Vocalocity impl */
  71. static const char QAREC_LIB_NAME[]      = "libQArec.so.3";
  72. static const char QAPROMPT_LIB_NAME[]   = "libQAprompt.so.3";
  73. static const char QATEL_LIB_NAME[]      = "libQAtel.so.3"; 
  74. #else  /* ! NDEBUG */
  75. /* OpenVXI impl */
  76. static const char VXIREC_LIB_NAME[]     = "libVXIrecD.so.3";
  77. static const char VXIPROMPT_LIB_NAME[]  = "libVXIpromptD.so.3";
  78. static const char VXITEL_LIB_NAME[]     = "libVXItelD.so.3"; 
  79. /* Vocalocity impl */
  80. static const char QAREC_LIB_NAME[]      = "libQArecD.so.3";
  81. static const char QAPROMPT_LIB_NAME[]   = "libQApromptD.so.3";
  82. static const char QATEL_LIB_NAME[]      = "libQAtelD.so.3"; 
  83. #endif /* NDEBUG */
  84. #endif
  85. #ifndef MODULE_PREFIX
  86. #define MODULE_PREFIX  COMPANY_DOMAIN   L"."
  87. #endif
  88. #define MODULE_VXICLIENT MODULE_PREFIX  L"VXIclient"
  89. #define MODULE_NAME                     MODULE_VXICLIENT
  90. #define PROPERTY_MAX_LEN                0x100
  91. #ifndef MAX_PATH
  92. #define MAX_PATH                        4096
  93. #endif
  94. #define STRINGLEN                       4096
  95. /* Globals */
  96. static VXIbool gblPlatformInitialized = FALSE;
  97. static VXIlogInterface *gblLog        = NULL;
  98. static VXIunsigned gblDiagLogBase     = 0;
  99. static SBlogListenerChannelData *gblLogData = NULL;
  100. static const VXIchar *gblUserAgentName= NULL;
  101. static const VXIchar *SSFT            = L"vocalocity";
  102. static const VXIchar *OPENVXI         = L"openvxi"; 
  103. /* data structure for Dynamic libraries */
  104. typedef struct ResourceAPI {
  105.   /* Recognizer's resource APIs */
  106.   VXIrecResult (*RecInit)
  107.   (
  108.     VXIlogInterface *log, 
  109.     VXIunsigned diagLogBase,
  110.     VXIMap *args
  111.   );
  112.   VXIrecResult (*RecShutDown)(VXIlogInterface *log);
  113.   VXIrecResult (*RecCreateResource)
  114.   (
  115.     VXIlogInterface   *log,
  116.     VXIinetInterface   *inet,
  117.     VXIcacheInterface  *cache,
  118.     VXIpromptInterface *prompt,
  119.     VXItelInterface    *tel,
  120.     VXIrecInterface    **rec
  121.   );
  122.   VXIrecResult (*RecDestroyResource)(VXIrecInterface **rec);             
  123.   
  124.   /* Prompt's resource APIs */
  125.   VXIpromptResult (*PromptInit)
  126.   (
  127.     VXIlogInterface *log,
  128.     VXIunsigned       diagLogBase, 
  129.     const VXIVector  *resources,
  130.     VXIMap           *args
  131.   );
  132.   VXIpromptResult (*PromptShutDown)(VXIlogInterface *log);                            
  133.   VXIpromptResult (*PromptCreateResource)
  134.   (
  135.     VXIlogInterface *log,
  136.     VXIinetInterface    *inet,
  137.     VXIcacheInterface   *cache,
  138.     VXIpromptInterface **prompt
  139.   ); 
  140.   VXIpromptResult (*PromptDestroyResource)(VXIpromptInterface **prompt);
  141.   
  142.   /* Tel's resource APIs */
  143.   VXItelResult (*TelInit)
  144.   (
  145.     VXIlogInterface *log,
  146.     VXIunsigned       diagLogBase, 
  147.     VXIMap           *args
  148.   );
  149.   VXItelResult (*TelShutDown)(VXIlogInterface *log);                            
  150.   VXItelResult (*TelCreateResource)
  151.   (
  152.     VXIlogInterface *log,
  153.     VXItelInterface **tel
  154.   ); 
  155.   VXItelResult (*TelDestroyResource)(VXItelInterface **prompt);
  156.   DynLibrary *dynRecLib;    /* Rec lib */
  157.   DynLibrary *dynPromptLib; /* Prompt lib */
  158.   DynLibrary *dynTelLib;    /* Tel. lib */
  159. } ResourceAPI;
  160. static ResourceAPI gblResAPI;
  161. static const VXIchar * AppendStringAlloc(VXIchar ** dst, const VXIchar * src)
  162. {
  163.   VXIchar * temp, *_dst = NULL;
  164.   int srclen = 0, dstlen = 0;
  165.   if( !dst ) return NULL;
  166.   if( !src ) return *dst;
  167.   srclen = wcslen(src) + 1;
  168.   _dst = *dst;
  169.   if( !_dst )
  170.   {
  171.     _dst = (VXIchar*)malloc(sizeof(VXIchar)*srclen);
  172.     if( !_dst ) return NULL;
  173.     wcscpy(_dst, src);
  174.     *dst = _dst;
  175.     return _dst;
  176.   }
  177.   else
  178.   {
  179.     dstlen = wcslen(_dst);
  180.     temp = (VXIchar*)realloc(_dst, (dstlen + srclen + 1) * sizeof(VXIchar));
  181.     if( !temp ) return NULL;
  182.     _dst = temp;
  183.     wcscpy(&_dst[dstlen], src);    
  184.     *dst = _dst;
  185.     return _dst;
  186.   }
  187.   /* shoud never reach here */
  188.   return NULL;
  189. }
  190. static VXIplatformResult LoadImplSpecificLibs(VXIMap *configArgs)
  191. {
  192.   VXIplatformResult platResult;
  193.   const VXIchar* impl = NULL;
  194.   int isLoaded = 0; 
  195.    
  196.   /* Load rec lib */
  197.   if( GetVXIString(configArgs, CLIENT_REC_IMPLEMENTATION, &impl) )
  198.   {
  199.     if( wcscmp(impl, SSFT) == 0 ) {
  200.       /* Load Vocalocity Rec implementation */  
  201.       platResult = LoadDynLibrary(QAREC_LIB_NAME, &gblResAPI.dynRecLib);
  202.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);
  203.       isLoaded = 1;
  204.     }
  205.     else if( wcscmp(impl, OPENVXI) == 0 ) {
  206.       /* Load OpenVXI's implementation */
  207.       platResult = LoadDynLibrary(VXIREC_LIB_NAME, &gblResAPI.dynRecLib);
  208.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult); 
  209.       isLoaded = 1;               
  210.     } else {
  211.       /* Other implementation, return error for now */
  212.       return VXIplatform_RESULT_UNSUPPORTED;       
  213.     }
  214.   }
  215.   
  216.   if( !isLoaded ) {
  217.     /* If there is no specific implementation of rec, assume it is SSFT first */
  218.     platResult = LoadDynLibrary(QAREC_LIB_NAME, &gblResAPI.dynRecLib);
  219.     /* Ignore previous error in case SSFT's impl not found
  220.        try to load OpenVXI's impl */
  221.     if( platResult != 0 ) {
  222.       platResult = LoadDynLibrary(VXIREC_LIB_NAME, &gblResAPI.dynRecLib);
  223.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);                
  224.     }
  225.   }
  226.   
  227.   /* Load rec symbols */
  228.   {
  229.     platResult = LoadDynSymbol(gblResAPI.dynRecLib, "VXIrecInit", 
  230.                               (void **)&gblResAPI.RecInit);
  231.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  232.     platResult = LoadDynSymbol(gblResAPI.dynRecLib, "VXIrecShutDown", 
  233.                               (void **)&gblResAPI.RecShutDown);
  234.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  235.     platResult = LoadDynSymbol(gblResAPI.dynRecLib, "VXIrecCreateResource", 
  236.                               (void **)&gblResAPI.RecCreateResource);
  237.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  238.     platResult = LoadDynSymbol(gblResAPI.dynRecLib, "VXIrecDestroyResource", 
  239.                               (void **)&gblResAPI.RecDestroyResource);
  240.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  241.   }
  242.   /* Load promt lib */
  243.   isLoaded = 0;
  244.   impl = NULL;
  245.   if( GetVXIString(configArgs, CLIENT_PROMPT_IMPLEMENTATION, &impl) )
  246.   {
  247.     if( wcscmp(impl, SSFT) == 0 ) {
  248.       /* Load Vocalocity Prompt implementation */  
  249.       platResult = LoadDynLibrary(QAPROMPT_LIB_NAME, &gblResAPI.dynPromptLib);
  250.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);
  251.       isLoaded = 1;
  252.     }    
  253.     else if( wcscmp(impl, OPENVXI) == 0 ) {
  254.       /* Load OpenVXI's implementation */
  255.       platResult = LoadDynLibrary(VXIPROMPT_LIB_NAME, &gblResAPI.dynPromptLib);
  256.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);   
  257.       isLoaded = 1;             
  258.     } else {
  259.       /* Other implementation, return error for now */
  260.       return VXIplatform_RESULT_UNSUPPORTED;       
  261.     }
  262.   }
  263.   
  264.   if( !isLoaded ) {
  265.     /* If there is no specific implementation of prompt, assume it is SSFT */
  266.     platResult = LoadDynLibrary(QAPROMPT_LIB_NAME, &gblResAPI.dynPromptLib);
  267.     /* Ignore previous error in case SSFT's impl not found,
  268.        try to load OpenVXI Prompt implementation */  
  269.     if( platResult != 0 ) {
  270.       platResult = LoadDynLibrary(VXIPROMPT_LIB_NAME, &gblResAPI.dynPromptLib);
  271.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);                
  272.     }
  273.   }
  274.   
  275.   /* Load Prompt symbols */
  276.   {  
  277.     platResult = LoadDynSymbol(gblResAPI.dynPromptLib, "VXIpromptInit", 
  278.                               (void **)&gblResAPI.PromptInit);
  279.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  280.     platResult = LoadDynSymbol(gblResAPI.dynPromptLib, "VXIpromptShutDown", 
  281.                               (void **)&gblResAPI.PromptShutDown);
  282.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  283.     platResult = LoadDynSymbol(gblResAPI.dynPromptLib, "VXIpromptCreateResource", 
  284.                               (void **)&gblResAPI.PromptCreateResource);
  285.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  286.     platResult = LoadDynSymbol(gblResAPI.dynPromptLib, "VXIpromptDestroyResource", 
  287.                               (void **)&gblResAPI.PromptDestroyResource);
  288.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);    
  289.   }           
  290.   /* Load Tel lib */
  291.   isLoaded = 0;
  292.   impl = NULL;
  293.   if( GetVXIString(configArgs, CLIENT_TEL_IMPLEMENTATION, &impl) )
  294.   {
  295.     if( wcscmp(impl, SSFT) == 0 ) {
  296.       /* Load Vocalocity Tel implementation */  
  297.       platResult = LoadDynLibrary(QATEL_LIB_NAME, &gblResAPI.dynTelLib);
  298.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);
  299.       isLoaded = 1;
  300.     }    
  301.     else if( wcscmp(impl, OPENVXI) == 0 ) {
  302.       /* Load OpenVXI's implementation */
  303.       platResult = LoadDynLibrary(VXITEL_LIB_NAME, &gblResAPI.dynTelLib);
  304.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);                
  305.       isLoaded = 1;
  306.     } else {
  307.       /* Other implementation, return error for now */
  308.       return VXIplatform_RESULT_UNSUPPORTED;       
  309.     }
  310.   }
  311.   
  312.   if( !isLoaded ) {
  313.     /* If there is no specific implementation of Tel, assume it is SSFT */
  314.     platResult = LoadDynLibrary(QATEL_LIB_NAME, &gblResAPI.dynTelLib);
  315.     /* Ignore previous error in case SSFT's impl not found,
  316.        try to load OpenVXI Tel implementation */  
  317.     if( platResult != 0 ) {
  318.       platResult = LoadDynLibrary(VXITEL_LIB_NAME, &gblResAPI.dynTelLib);
  319.       CHECK_RESULT_RETURN(NULL, "LoadDynLibrary()", platResult);                
  320.     }
  321.   }
  322.     
  323.   /* Load Tel symbols */
  324.   {  
  325.     platResult = LoadDynSymbol(gblResAPI.dynTelLib, "VXItelInit", 
  326.                               (void **)&gblResAPI.TelInit);
  327.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  328.     platResult = LoadDynSymbol(gblResAPI.dynTelLib, "VXItelShutDown", 
  329.                               (void **)&gblResAPI.TelShutDown);
  330.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  331.     platResult = LoadDynSymbol(gblResAPI.dynTelLib, "VXItelCreateResource", 
  332.                               (void **)&gblResAPI.TelCreateResource);
  333.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);
  334.     platResult = LoadDynSymbol(gblResAPI.dynTelLib, "VXItelDestroyResource", 
  335.                               (void **)&gblResAPI.TelDestroyResource);
  336.     CHECK_RESULT_RETURN(NULL, "LoadDynSymbol()", platResult);    
  337.   }           
  338.       
  339.   return VXIplatform_RESULT_SUCCESS;   
  340. }
  341. /**
  342.  * Initialize the platform.  
  343.  *
  344.  * This function initializes all the components in the OSB PIK in the
  345.  * required order.  The order can be changed quite a bit, but logging
  346.  * must be initialized first. Also VXI requires that all the
  347.  * components be initialized and set before it can be created.
  348.  */
  349. VXIplatformResult VXIplatformInit(VXIMap *configArgs, VXIunsigned *nbChannels)
  350. {
  351.   VXItrdResult trdResult;
  352.   VXIlogResult logResult;
  353.   VXIpromptResult promptResult;
  354.   VXIinetResult inetResult;
  355.   VXItelResult telResult;
  356.   VXIcacheResult cacheResult;
  357.   VXIjsiResult jsiResult;
  358.   VXIobjResult objResult;
  359.   VXIrecResult recResult;
  360.   VXIinterpreterResult interpreterResult;
  361.   VXIplatformResult platResult;
  362.   VXIint32 diagLogBase;
  363.   VXIint32 tempInt = 0;
  364.   
  365.   if (gblPlatformInitialized)
  366.     return VXIplatform_RESULT_ALREADY_INITIALIZED;
  367.   /* initialized dynamic loading structure */
  368.   memset(&gblResAPI, 0, sizeof(gblResAPI));
  369.    
  370.   /* Initialize the low-level TRD utilities library */
  371.   {
  372.     if( GetVXIInt(configArgs, CLIENT_TRD_THREAD_STACKSIZE, &tempInt) )
  373.     {
  374.       trdResult = VXItrdInit(tempInt);
  375.       CHECK_RESULT_RETURN(NULL, "VXItrdInit()", trdResult);
  376.     }
  377.   }
  378.   
  379.   /* Initialize log */
  380.   {
  381.     const VXIchar *lfname = L"log.txt";
  382.     const VXIchar *ldname = L"logContent";
  383.     const VXIchar *lfmime = L"text/plain;charset=ISO-8859-1";
  384.     VXIint32 lmsize = 50, dmsize = 10;
  385.     VXIbool logToStdout = FALSE, keepLogFileOpen = FALSE;
  386.     VXIbool reportErrorText = FALSE;
  387.     const VXIVector *errorMapFiles = NULL;
  388.     VXIVector *loadedErrorMapFiles = NULL;
  389.     VXIlogInterface *logResource = NULL;
  390.     
  391.     /* Get VXIClient diag log base */
  392.     if( GetVXIInt(configArgs, CLIENT_CLIENT_DIAG_BASE, &tempInt) )      
  393.       gblDiagLogBase = (VXIunsigned) tempInt;
  394.     /* Initialize the logging interface */
  395.     logResult = SBlogInit(); 
  396.     CHECK_RESULT_RETURN(NULL, "SBlogInit()", logResult);
  397.     /* Create a global log stream with channel number -1 which is not
  398.        used as a real channel number. This log is used for global
  399.        operations. */
  400.     logResult = SBlogCreateResource(&logResource);
  401.     CHECK_RESULT_RETURN(NULL, "SBlogCreateResource()", logResult);
  402.     /* Load configuration parameters */
  403.     GetVXIString(configArgs, CLIENT_LOG_FILE_NAME, &lfname);
  404.     GetVXIInt(configArgs, CLIENT_LOG_MAX_SIZE_MB, &lmsize);
  405.     GetVXIString(configArgs, CLIENT_LOG_FILE_MIME_TYPE, &lfmime);
  406.     GetVXIString(configArgs, CLIENT_LOG_CONTENT_DIR, &ldname);
  407.     GetVXIInt(configArgs, CLIENT_LOG_CONTENT_TOTAL_SIZE_MB, &dmsize);
  408.     GetVXIBool(configArgs, CLIENT_LOG_LOG_TO_STDOUT, &logToStdout);
  409.     GetVXIBool(configArgs, CLIENT_LOG_KEEP_LOG_FILE_OPEN, &keepLogFileOpen);
  410.     GetVXIBool(configArgs, CLIENT_LOG_REPORT_ERROR_TEXT, &reportErrorText);
  411.     GetVXIVector(configArgs, CLIENT_LOG_ERROR_MAP_FILES, &errorMapFiles);
  412.     /* If no error mapping files loaded yet, they may be directly present
  413.        in the top-level configuration map, scan for them */
  414.     if (!errorMapFiles) {
  415.       const VXIchar *key;
  416.       VXIchar *ptr;
  417.       const VXIValue *val;
  418.       int prefixlen = wcslen(CLIENT_LOG_ERROR_MAP_FILE_PREFIX);
  419.       
  420.       VXIMapIterator *iter = VXIMapGetFirstProperty(configArgs,&key,&val);
  421.       if (iter) {
  422.         do {
  423.           if (wcsncmp(key, CLIENT_LOG_ERROR_MAP_FILE_PREFIX, prefixlen)==0) {
  424.             /* get the error map index from the key */
  425.             VXIunsigned index = (VXIunsigned) wcstol(key + prefixlen, &ptr,10);
  426.             if (*ptr == L'') {
  427.               if (loadedErrorMapFiles == NULL) {
  428.                 loadedErrorMapFiles = VXIVectorCreate();
  429.                 CHECK_MEMALLOC_RETURN(NULL, loadedErrorMapFiles, L"SBlogInit");
  430.               }
  431.               
  432.               VXIVectorAddElement(loadedErrorMapFiles, VXIValueClone(val));
  433.             }
  434.           }
  435.         } while (VXIMapGetNextProperty(iter, &key, &val) == 0);
  436.       }
  437.       VXIMapIteratorDestroy(&iter);
  438.       if (loadedErrorMapFiles)
  439.         errorMapFiles = loadedErrorMapFiles;
  440.       /* Initialize SBlogListener */
  441.       logResult = SBlogListenerInitEx3(lfname, lfmime, lmsize*1024*1000, ldname, 
  442.                                        dmsize*1024*1000, logToStdout, 
  443.                                        keepLogFileOpen, FALSE, reportErrorText, 
  444.                                        errorMapFiles);
  445.       CHECK_RESULT_RETURN(NULL, "SBlogListenerInitEx3()", logResult);
  446.       if (loadedErrorMapFiles)
  447.         VXIVectorDestroy(&loadedErrorMapFiles);
  448.     }
  449.     /* Create a global log data to register the listeners */
  450.     gblLogData = (SBlogListenerChannelData *) 
  451.                  malloc(sizeof(SBlogListenerChannelData));
  452.     CHECK_MEMALLOC_RETURN(NULL, gblLogData, L"SBlogListenerInit");
  453.     memset (gblLogData, 0, sizeof (SBlogListenerChannelData));
  454.     gblLogData->channel = -1;  /* for global log, there's no real channel */
  455.     /* Register listeners */
  456.     RegisterDiagnosticListener(logResource,DiagnosticListener,gblLogData);
  457.     RegisterErrorListener(logResource,ErrorListener,gblLogData);
  458.     RegisterEventListener(logResource,EventListener,gblLogData);
  459.     RegisterContentListener(logResource,ContentListener,gblLogData);
  460.     gblLog = logResource;
  461.   }
  462.   /**
  463.    * Initialize Write-back cache
  464.    */
  465.   {
  466.     /* Load configuration parameters */
  467.     const VXIchar *cachePath      = L"cache";
  468.     VXIint32 cacheTotalSizeMB     = 200;
  469.     VXIint32 cacheEntryMaxSizeMB  = 20;
  470.     VXIint32 cacheEntryExpTimeSec = 3600;
  471.     VXIint32 cacheLowWaterMark    = 180;
  472.     VXIbool unlockEntries         = TRUE;
  473.     diagLogBase                   = 0;
  474.     GetVXIString(configArgs, CLIENT_CACHE_CACHE_DIR, &cachePath);
  475.     GetVXIInt(configArgs, CLIENT_CACHE_CACHE_TOTAL_SIZE_MB, &cacheTotalSizeMB);
  476.     GetVXIInt(configArgs, CLIENT_CACHE_CACHE_LOW_WATER_MARK_MB, &cacheLowWaterMark);
  477.     GetVXIInt(configArgs, CLIENT_CACHE_CACHE_ENTRY_MAX_SIZE_MB, &cacheEntryMaxSizeMB);
  478.     GetVXIInt(configArgs, CLIENT_CACHE_CACHE_ENTRY_EXP_TIME_SEC,&cacheEntryExpTimeSec);
  479.     GetVXIBool(configArgs, CLIENT_CACHE_UNLOCK_ENTRIES, &unlockEntries);
  480.     GetVXIInt(configArgs, CLIENT_CACHE_DIAG_BASE, &diagLogBase);    
  481.     /* Initialize the caching interface */
  482.     cacheResult = SBcacheInit(gblLog, (VXIunsigned) diagLogBase, 
  483.                               cachePath, cacheTotalSizeMB, 
  484.                               cacheEntryMaxSizeMB,
  485.                               cacheEntryExpTimeSec, unlockEntries, cacheLowWaterMark);
  486.     CHECK_RESULT_RETURN(NULL, "SBcacheInit()", cacheResult);
  487.   }
  488.   /**
  489.    * Initialize the Internet fetch component
  490.    */
  491.   {
  492.     /* Load configuration parameters */
  493.     const VXIchar *proxyServer    = NULL;
  494.     VXIint32 proxyPort            = 0;
  495.     const VXIMap *extensionRules  = NULL;
  496.     const VXIVector *proxyRules   = NULL;
  497.     VXIMap *loadedExtensionRules  = NULL;
  498.     VXIVector *loadedProxyRules   = NULL;
  499.     diagLogBase                   = 0;
  500.     GetVXIMap(configArgs, CLIENT_INET_EXTENSION_RULES, &extensionRules);
  501.     GetVXIVector(configArgs, CLIENT_INET_PROXY_RULES, &proxyRules);
  502.     GetVXIInt(configArgs, CLIENT_INET_DIAG_BASE, &diagLogBase);
  503.     GetVXIString(configArgs, CLIENT_INET_USER_AGENT, &gblUserAgentName);
  504.     
  505. if( !gblUserAgentName ) gblUserAgentName = L"OpenVXI/3.0";
  506.     /* If no proxy rules loaded yet, they may be directly present in
  507.        the top-level configuration map, scan for them */
  508.     if (!proxyRules)
  509.     {
  510.       const VXIchar *key = NULL;
  511.       const VXIValue *val = NULL;
  512.       VXIchar *ptr = NULL;
  513.       int prefixlen = wcslen(CLIENT_INET_PROXY_RULE_PREFIX);
  514.       
  515.       VXIMapIterator *iter = VXIMapGetFirstProperty(configArgs,&key,&val);
  516.       if (iter) {
  517.         do {
  518.           if (wcsncmp(key, CLIENT_INET_PROXY_RULE_PREFIX, prefixlen)==0) {
  519.             /* get the resource index and property from the key */
  520.             VXIunsigned index = (VXIunsigned) wcstol(key + prefixlen, &ptr,10);
  521.             if( index >= 0 ) {
  522.               VXIString* res = NULL;
  523.               if (loadedProxyRules == NULL) {
  524.                 loadedProxyRules = VXIVectorCreate();
  525.                 CHECK_MEMALLOC_RETURN(NULL, loadedProxyRules, L"SBinetInit");
  526.               }
  527.               
  528.               // overwrite the old value if exists
  529.               res = (VXIString*) VXIVectorGetElement(loadedProxyRules, index);
  530.               if( res == NULL ) {
  531.                 while (VXIVectorLength(loadedProxyRules) < index + 1) {
  532.                   res = VXIStringCreate(L"");
  533.                   CHECK_MEMALLOC_RETURN(NULL, res, L"SBinetInit");                 
  534.                   VXIVectorAddElement(loadedProxyRules, (VXIValue *)res);
  535.                 }
  536.               }
  537.               VXIStringSetValue(res, VXIStringCStr((const VXIString*)val));
  538.             } 
  539.           }
  540.         } while (VXIMapGetNextProperty(iter, &key, &val) == 0);
  541.       }
  542.       VXIMapIteratorDestroy(&iter);     
  543.       if (loadedProxyRules)
  544.         proxyRules = loadedProxyRules;   
  545.     }
  546.     /* If no extension rules loaded yet, they may be directly present in
  547.        the top-level configuration map, scan for them */
  548.     if (!extensionRules) {
  549.       const VXIchar *key;
  550.       const VXIValue *val;
  551.       int prefixlen = wcslen(CLIENT_INET_EXTENSION_RULE_PREFIX);
  552.       
  553.       VXIMapIterator *iter = VXIMapGetFirstProperty(configArgs,&key,&val);
  554.       if (iter) {
  555.         do {
  556.           if (wcsncmp(key, CLIENT_INET_EXTENSION_RULE_PREFIX, prefixlen)==0) {
  557.             if (VXIValueGetType(val) == VALUE_STRING) {
  558.               /* get extension from the key */
  559.               const VXIchar *ext = key + prefixlen - 1;
  560.               if (wcslen(ext) > 1) {   
  561.                 if (loadedExtensionRules == NULL) {
  562.                   loadedExtensionRules = VXIMapCreate();
  563.                   CHECK_MEMALLOC_RETURN(NULL, loadedExtensionRules, L"SBinetInit");                                  
  564.                 }
  565.                 VXIMapSetProperty(loadedExtensionRules, ext, VXIValueClone(val));
  566.               }
  567.             }
  568.           }
  569.         } while (VXIMapGetNextProperty(iter, &key, &val) == 0);
  570.       }
  571.       VXIMapIteratorDestroy(&iter);
  572.       if (loadedExtensionRules)
  573.         extensionRules = loadedExtensionRules;
  574.     }
  575.     /* The next three are optional */
  576.     GetVXIString(configArgs, CLIENT_INET_PROXY_SERVER, &proxyServer);
  577.     GetVXIInt(configArgs, CLIENT_INET_PROXY_PORT, &proxyPort);
  578.     /* Initialize the Internet component */
  579.     inetResult = SBinetInit(gblLog, (VXIunsigned) diagLogBase, NULL, 
  580.                             0, 0, 0, proxyServer, proxyPort,
  581.                             gblUserAgentName, extensionRules, proxyRules);
  582.     CHECK_RESULT_RETURN(NULL, "SBinetInit()", inetResult);
  583.     if (loadedExtensionRules)
  584.       VXIMapDestroy(&loadedExtensionRules);
  585.     if (loadedProxyRules)
  586.       VXIVectorDestroy(&loadedProxyRules);
  587.   }
  588.   /**
  589.    * Initialize the ECMAScript component
  590.    */
  591.   {
  592.     /* Load configuration information */
  593.     VXIint32 runtimeSize = 16384000;
  594.     VXIint32 contextSize = 131072;
  595.     VXIint32 maxBranches = 100000;
  596.     diagLogBase          = 0;
  597.     GetVXIInt(configArgs, CLIENT_JSI_RUNTIME_SIZE_BYTES, &runtimeSize);
  598.     GetVXIInt(configArgs, CLIENT_JSI_CONTEXT_SIZE_BYTES, &contextSize);
  599.     GetVXIInt(configArgs, CLIENT_JSI_MAX_BRANCHES, &maxBranches);
  600.     GetVXIInt(configArgs, CLIENT_JSI_DIAG_BASE, &diagLogBase);
  601.     
  602.     /* Initialize the ECMAScript engine */
  603.     jsiResult = SBjsiInit(gblLog, (VXIunsigned) diagLogBase, runtimeSize,
  604.                           contextSize, maxBranches);
  605.     CHECK_RESULT_RETURN(NULL, "OSBjsiInit()", jsiResult);
  606.   }
  607.   
  608.   /**
  609.    *  Dynamically load rec, prompt and tel libraries based
  610.    *  on specific implementation
  611.    */
  612.   {
  613.     platResult = LoadImplSpecificLibs(configArgs);
  614.     if( platResult != VXIplatform_RESULT_SUCCESS ) return platResult;
  615.   }
  616.   /**
  617.    * Initialize the telephony interface
  618.    */
  619.   {
  620.     diagLogBase = 0;
  621.     GetVXIInt(configArgs, CLIENT_TEL_DIAG_BASE, &diagLogBase);
  622.     telResult = gblResAPI.TelInit(gblLog, (VXIunsigned) diagLogBase, configArgs);
  623.     CHECK_RESULT_RETURN(NULL, "TelInit()", telResult);
  624.   }
  625.   /**
  626.    * Initialize the Prompt component
  627.    */
  628.   {
  629.     /* Load configuration parameters */
  630.     const VXIVector *resources = NULL;
  631.     VXIVector *loadedPromptResources = NULL;
  632.     GetVXIVector(configArgs, CLIENT_PROMPT_RESOURCES, &resources);
  633.     
  634.     /* If no prompt resources loaded yet, they may be directly present
  635.        in the top-level configuration map, scan for them */
  636.     if ( !resources ) {
  637.       const VXIchar *key;
  638.       VXIchar *ptr;
  639.       const VXIValue *val;
  640.       int prefixlen = wcslen(CLIENT_PROMPT_RESOURCE_PREFIX);
  641.       
  642.       VXIMapIterator *iter = VXIMapGetFirstProperty(configArgs,&key,&val);
  643.       if (iter) {
  644.         do {
  645.           if (wcsncmp(key, CLIENT_PROMPT_RESOURCE_PREFIX, prefixlen)==0) {
  646.             /* get the resource index and property from the key */
  647.             VXIunsigned index = (VXIunsigned) wcstol(key + prefixlen, &ptr,10);
  648.             if ((*ptr == L'.') && (wcslen(ptr) > 1)) {
  649.               VXIchar property[256];
  650.               VXIMap *res = NULL;
  651.               wcscpy(property, L"com.vocalocity.prompt.resource.");
  652.               wcscat(property, ptr + 1);
  653.               if (loadedPromptResources == NULL) {
  654.                 loadedPromptResources = VXIVectorCreate();
  655.                 CHECK_MEMALLOC_RETURN(NULL, loadedPromptResources, L"VXIpromptInit");                                  
  656.               }
  657.               
  658.               res = (VXIMap *)VXIVectorGetElement(loadedPromptResources,index);
  659.               if (res == NULL) {
  660.                 while (VXIVectorLength(loadedPromptResources) < index + 1) {
  661.                   res = VXIMapCreate();
  662.                   CHECK_MEMALLOC_RETURN(NULL, res, L"VXIpromptInit");                                                   
  663.                   VXIVectorAddElement(loadedPromptResources, (VXIValue *)res);
  664.                 }
  665.               }
  666.               VXIMapSetProperty(res, property, VXIValueClone(val));
  667.             } 
  668.             else {
  669.               VXIclientError(NULL, MODULE_VXICLIENT, 104, L"Invalid prompt "
  670.                             L"resource key suffix for configuration parameter",
  671.                             L"%s%s", L"PARAM", key);
  672.             }
  673.           }
  674.         } while (VXIMapGetNextProperty(iter, &key, &val) == 0);
  675.       }
  676.       VXIMapIteratorDestroy(&iter);
  677.       if (loadedPromptResources)
  678.         resources = loadedPromptResources;
  679.     }
  680.     /* Initialize prompting */
  681.     diagLogBase = 0;
  682.     GetVXIInt(configArgs, CLIENT_PROMPT_DIAG_BASE, &diagLogBase);
  683.     promptResult = gblResAPI.PromptInit(gblLog, (VXIunsigned) diagLogBase, resources, configArgs);
  684.     CHECK_RESULT_RETURN(NULL, "PromptInit()", promptResult);
  685.     if (loadedPromptResources)
  686.       VXIVectorDestroy(&loadedPromptResources);   
  687.   }
  688.   /**
  689.    * Initialize the Recognition component
  690.    */
  691.   {
  692.     diagLogBase = 0;
  693.     GetVXIInt(configArgs, CLIENT_REC_DIAG_BASE, &diagLogBase);
  694.     recResult = gblResAPI.RecInit(gblLog, diagLogBase, configArgs);
  695.     CHECK_RESULT_RETURN(NULL, "RecInit()", recResult);   
  696.   }
  697.   /**
  698.    * Initialize the Object component
  699.    */
  700.   {
  701.     /* Load configuration information */
  702.     diagLogBase = 0;
  703.     GetVXIInt(configArgs, CLIENT_OBJ_DIAG_BASE, &diagLogBase);
  704.     objResult = VXIobjectInit(gblLog, (VXIunsigned) diagLogBase);
  705.     CHECK_RESULT_RETURN(NULL, "VXIobjectInit()", objResult);
  706.   }
  707.   
  708.   /**
  709.    * Initialize the VoiceXML interpreter
  710.    */
  711.   {
  712.     /* Retrieve the VXI diagnosis base TAG ID */
  713.     diagLogBase = 0;
  714.     GetVXIInt(configArgs, CLIENT_VXI_DIAG_BASE, &diagLogBase);
  715.     /* Initialize the interpreter */
  716.     interpreterResult = VXIinterpreterInit(gblLog, (VXIunsigned) diagLogBase, NULL);
  717.     CHECK_RESULT_RETURN(NULL, "VXIinterpreterInit()", interpreterResult);
  718.   }
  719.      
  720.   gblPlatformInitialized = TRUE;
  721.   return VXIplatform_RESULT_SUCCESS;
  722. }
  723. /**
  724.  * Shutdown the platform. 
  725.  *
  726.  * VXIplatformShutdown can only be called when all the resources have
  727.  * been destroyed.  
  728.  */
  729. VXIplatformResult VXIplatformShutdown()
  730. {
  731.   VXItrdResult trdResult;
  732.   VXIlogResult logResult;
  733.   VXItelResult telResult;
  734.   VXIpromptResult promptResult;
  735.   VXIinetResult inetResult;
  736.   VXIcacheResult cacheResult;
  737.   VXIjsiResult jsiResult;
  738.   VXIobjResult objResult;
  739.   VXIrecResult recResult;
  740.   
  741.   /* Error if not already initialized */
  742.   if (!gblPlatformInitialized)
  743.     return VXIplatform_RESULT_NOT_INITIALIZED;
  744.   /* Do everything in reverse.  Shutdown the VXI first */
  745.   VXIinterpreterShutDown(gblLog);
  746.   /* Now shutdown Object */
  747.   objResult = VXIobjectShutDown(gblLog);
  748.   CHECK_RESULT_RETURN(NULL, "VXIobjectShutDown()", objResult); 
  749.   /* Now shutdown ECMAScript */
  750.   jsiResult = SBjsiShutDown(gblLog);
  751.   CHECK_RESULT_RETURN(NULL, "SBjsiShutDown()", jsiResult);
  752.   /* Shutdown Rec */
  753.   recResult = gblResAPI.RecShutDown(gblLog);
  754.   CHECK_RESULT_RETURN(NULL, "RecShutDown()", recResult);  
  755.   /* Shutdown Prompt */
  756.   promptResult = gblResAPI.PromptShutDown(gblLog);
  757.   CHECK_RESULT_RETURN(NULL, "PromptShutDown()", recResult);  
  758.   /* Shutdown Tel */
  759.   telResult = gblResAPI.TelShutDown(gblLog);
  760.   CHECK_RESULT_RETURN(NULL, "TelShutDown()", recResult);  
  761.   /* Shutdown the internet fetching component */
  762.   inetResult = SBinetShutDown(gblLog);
  763.   CHECK_RESULT_RETURN(NULL, "SBinetShutDown()", inetResult);
  764.   /* Shutdown the caching component */
  765.   cacheResult = SBcacheShutDown(gblLog);
  766.   CHECK_RESULT_RETURN(NULL, "SBcacheShutDown()", cacheResult);
  767.   /* unregister all listners */
  768.   UnregisterDiagnosticListener(gblLog,DiagnosticListener,gblLogData);
  769.   UnregisterErrorListener(gblLog,ErrorListener,gblLogData);
  770.   UnregisterEventListener(gblLog,EventListener,gblLogData);
  771.   UnregisterContentListener(gblLog,ContentListener,gblLogData);
  772.   free(gblLogData);
  773.   logResult = SBlogDestroyResource(&gblLog);
  774.   CHECK_RESULT_RETURN(NULL, "SBlogDestroyResource()", logResult);
  775.   /* Shutdown the logging API. */
  776.   logResult = SBlogShutDown();
  777.   CHECK_RESULT_RETURN(NULL, "SBlogShutDown()", logResult);
  778.   /* Shutdown the TRD library. At this point the system should just
  779.      be returning and no OpenVXI PIK component functions should be run. */
  780.   trdResult = VXItrdShutDown();
  781.   CHECK_RESULT_RETURN(NULL, "VXItrdShutDown()", trdResult);
  782.   /* Finally close the loaded dynamic libraries */
  783.   CloseDynLibrary(&gblResAPI.dynRecLib);
  784.   CloseDynLibrary(&gblResAPI.dynPromptLib);
  785.   CloseDynLibrary(&gblResAPI.dynTelLib);
  786.   
  787.   gblPlatformInitialized = FALSE;
  788.   return VXIplatform_RESULT_SUCCESS;
  789. }
  790. /**
  791.  * Create resources for the platform.
  792.  *
  793.  * This function creates all the resources needed by the VXI to
  794.  * execute.  This includes both APIs that the VXI calls directly and
  795.  * the APIS that those components call.  All components in the OpenVXI PIK are
  796.  * exposed here.<p>
  797.  *
  798.  * The resources will be written into the platform pointer which is
  799.  * allocated in this function.  
  800.  */
  801. VXIplatformResult VXIplatformCreateResources(VXIunsigned channelNum, 
  802.                                              VXIMap *configArgs,
  803.                                              VXIplatform **platform)
  804. {
  805.   VXIplatform *newPlatform;
  806.   VXItelResult telResult;
  807.   VXIlogResult logResult;
  808.   VXIcacheResult cacheResult;
  809.   VXIinetResult inetResult;
  810.   VXIpromptResult promptResult;
  811.   VXIjsiResult jsiResult;
  812.   VXIobjResult objResult;
  813.   VXIrecResult recResult;
  814.   VXIinterpreterResult interpreterResult;
  815.   VXIchar *connectionPropScript = NULL;
  816.   VXIchar tempScript[STRINGLEN];
  817.   if (!gblPlatformInitialized) {
  818.     return VXIplatform_RESULT_NOT_INITIALIZED;
  819.   }
  820.   if (platform == NULL) {
  821.     return VXIplatform_RESULT_INVALID_ARGUMENT;
  822.   }
  823.   
  824.   /* initialize variables */
  825.   memset(tempScript, 0, sizeof(tempScript));
  826.   /* set platform to NULL and then initialize it to all NULL
  827.      components once it is created */
  828.   *platform = NULL; 
  829.   newPlatform = (VXIplatform *) malloc(sizeof(VXIplatform));
  830.   CHECK_MEMALLOC_RETURN(NULL, newPlatform, L"Platform Allocation");                                                   
  831.   memset(newPlatform, 0, sizeof(VXIplatform)); 
  832.   newPlatform->channelNum = channelNum;
  833.   /* Create a channel logging resource.  A logging interface, per
  834.      channel, is required to do the logging.  The channel number is
  835.      bound at the creation time and will appear in any log message
  836.      generated through this interface instance. */
  837.   logResult = SBlogCreateResource(&newPlatform->VXIlog);
  838.   CHECK_RESULT_RETURN(NULL, "SBlogCreateResource()", logResult);
  839.   /* Create a channel specific logging user data */
  840.   newPlatform->logData = (SBlogListenerChannelData *)
  841.                           malloc(sizeof(SBlogListenerChannelData));
  842.   CHECK_MEMALLOC_RETURN(NULL, newPlatform->logData, L"Channel Log-data Allocation");                                                   
  843.   memset (newPlatform->logData, 0, sizeof (SBlogListenerChannelData));
  844.   newPlatform->logData->channel = channelNum;
  845.   
  846.   /* Register logging listeners for this channel */
  847.   RegisterDiagnosticListener(newPlatform->VXIlog, DiagnosticListener,
  848.                              newPlatform->logData);
  849.   RegisterErrorListener(newPlatform->VXIlog,ErrorListener,
  850.                         newPlatform->logData);
  851.   RegisterEventListener(newPlatform->VXIlog,EventListener,
  852.                         newPlatform->logData);
  853.   RegisterContentListener(newPlatform->VXIlog,ContentListener,
  854.                           newPlatform->logData);
  855.   /* Turn on/off diagnostic tags based on the configuration settings,
  856.      we have to log the implementation name after this otherwise
  857.      we'll never see the message */
  858.   VXIclientControliagnosticTags (configArgs, newPlatform);
  859.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIlog", newPlatform->VXIlog);
  860.   
  861.   /* Store properties for session connection default values.  The values are
  862.      platform-specific and therefore platform's responsibility. 
  863.      They can be referenced as connection.* (technically
  864.      session.connection.* but since the session scope is the global
  865.      scope, connection.* will be found, and the connection.* form is
  866.      what is universally used to query this information for HTML
  867.      browsers). */
  868.   {
  869.     const VXIchar* scString = NULL;
  870.     /* create connection object */
  871.     AppendStringAlloc(&connectionPropScript, L"var connection = new Object();n");
  872.     
  873.     /* local uri */
  874.     GetVXIString(configArgs, CLIENT_SESSION_CONNECTION_LOCAL_URI, &scString);
  875.     if( scString ) 
  876.     {
  877.       SWIswprintf(tempScript, STRINGLEN, L"connection.local = new Object();n"
  878.                                        L"connection.local.uri = '%s'n",
  879.                                        scString);
  880.       AppendStringAlloc(&connectionPropScript, tempScript);
  881.     }
  882.     
  883.     // remote uri
  884.     scString = NULL;
  885.     GetVXIString(configArgs, CLIENT_SESSION_CONNECTION_REMOTE_URI, &scString);
  886.     if( scString )
  887.     {
  888.       SWIswprintf(tempScript, STRINGLEN, L"connection.remote = new Object();n"
  889.                                        L"connection.remote.uri = '%s';n",
  890.                                        scString);
  891.       AppendStringAlloc(&connectionPropScript, tempScript);
  892.     }
  893.     
  894.     // protocol name
  895.     scString = NULL;
  896.     GetVXIString(configArgs, CLIENT_SESSION_CONNECTION_PROTOCOL_NAME, &scString);
  897.     if( scString )
  898.     {
  899.       SWIswprintf(tempScript, STRINGLEN, L"connection.protocol = new Object();n"
  900.                                        L"connection.protocol.name = '%s';n"
  901.                                        L"connection.protocol.%s = new Object();n"
  902.                                        L"connection.protocol.%s.uui = 'User-to-User';n",
  903.                                        scString, scString, scString);
  904.       AppendStringAlloc(&connectionPropScript, tempScript);
  905.       // protocol version
  906.       scString = NULL;
  907.       GetVXIString(configArgs, CLIENT_SESSION_CONNECTION_PROTOCOL_VERSION, &scString);
  908.       if( scString )
  909.       {        
  910.         SWIswprintf(tempScript, STRINGLEN, L"connection.protocol.version = '%s';n", scString);
  911.         AppendStringAlloc(&connectionPropScript, tempScript);
  912.       }                         
  913.     }
  914.     // application-to-application information
  915.     scString = NULL;
  916.     GetVXIString(configArgs, CLIENT_SESSION_CONNECTION_AAI, &scString);
  917.     if( scString )
  918.     { 
  919.       SWIswprintf(tempScript, STRINGLEN, L"connection.aai = '%s';n", scString);
  920.       AppendStringAlloc(&connectionPropScript, tempScript);
  921.     }
  922.     // originator 
  923.     scString = NULL;
  924.     GetVXIString(configArgs, CLIENT_SESSION_CONNECTION_ORIGINATOR, &scString);
  925.     if( scString )
  926.     {        
  927.       SWIswprintf(tempScript, STRINGLEN, L"connection.originator = %s;n", scString);
  928.       AppendStringAlloc(&connectionPropScript, tempScript);
  929.     }
  930.     // Add the channel number
  931.     SWIswprintf(tempScript, STRINGLEN, L"connection.channel = %d;n", channelNum);
  932.     AppendStringAlloc(&connectionPropScript, tempScript);
  933.     // redirect: a bit tricky to get the array of redirect,
  934.     // first we build a vector of redirect then using the vector to
  935.     // create the ECMAScript
  936.     scString = NULL;
  937.     {
  938.       VXIVector *loadedRedirectResources = NULL;
  939.       const VXIchar *key;
  940.       VXIchar *ptr;
  941.       const VXIValue *val;
  942.       int prefixlen = wcslen(CLIENT_SESSION_CONNECTION_REDIRECT_DOT);
  943.   
  944.       VXIMapIterator *iter = VXIMapGetFirstProperty(configArgs,&key,&val);
  945.       if (iter) 
  946.       {
  947.         do 
  948.         {
  949.           if( wcsncmp(key, CLIENT_SESSION_CONNECTION_REDIRECT_DOT, prefixlen) == 0 )
  950.           {
  951.             /* get the resource index and property from the key */
  952.             VXIunsigned index = (VXIunsigned) wcstol(key + prefixlen, &ptr,10);
  953.             if ((*ptr == L'.') && (wcslen(ptr) > 1)) 
  954.             {
  955.               VXIchar property[256];
  956.               VXIMap *res = NULL;
  957.               wcscpy(property, ptr+1);
  958.               if (loadedRedirectResources == NULL) 
  959.               {
  960.                 loadedRedirectResources = VXIVectorCreate();
  961.                 CHECK_MEMALLOC_RETURN(NULL, loadedRedirectResources, "Redirect");
  962.               }
  963.               
  964.               res = (VXIMap *)VXIVectorGetElement(loadedRedirectResources,index);
  965.               if (res == NULL) 
  966.               {
  967.                 while (VXIVectorLength(loadedRedirectResources) < index + 1) 
  968.                 {
  969.                   res = VXIMapCreate();
  970.                   CHECK_MEMALLOC_RETURN(newPlatform, res, L"Construction Redirect Session Vars.");                                                   
  971.                   VXIVectorAddElement(loadedRedirectResources, (VXIValue *)res);
  972.                 }
  973.               }
  974.               VXIMapSetProperty(res, property, VXIValueClone(val));
  975.             } 
  976.             else 
  977.             {
  978.               VXIclientError(newPlatform, MODULE_VXICLIENT, 104, L"Invalid redirect "
  979.                             L"property key suffix for configuration parameter",
  980.                             L"%s%s", L"PARAM", key);
  981.             }
  982.           }
  983.         } while (VXIMapGetNextProperty(iter, &key, &val) == 0);
  984.       }
  985.       VXIMapIteratorDestroy(&iter);
  986.       /* Use the vector to create ECMAScript */
  987.       if( loadedRedirectResources )
  988.       {
  989.         int idx , vlen = VXIVectorLength(loadedRedirectResources);
  990.         /* create redirect array object */
  991.         AppendStringAlloc(&connectionPropScript, L"connection.redirect = new Array();n");
  992.         for( idx = 0; idx < vlen; idx++)
  993.         {
  994.           const VXIMap *v = (const VXIMap*) VXIVectorGetElement (loadedRedirectResources, idx);
  995.           if( v )
  996.           {
  997.             VXIvalueResult ret = VXIvalue_RESULT_SUCCESS;
  998.             const wchar_t* key;
  999.             const VXIValue *value;
  1000.             VXIMapIterator *it = VXIMapGetFirstProperty(v, &key, &value);
  1001.             /* create redirect[i] object */
  1002.             SWIswprintf(tempScript, STRINGLEN, 
  1003.                         L"connection.redirect[%d] = new Object();n", idx);
  1004.             AppendStringAlloc(&connectionPropScript, tempScript);
  1005.   
  1006.             /* create redirect[i].* (.uri, .pi, .si, .reason) */
  1007.             while( ret == VXIvalue_RESULT_SUCCESS)
  1008.             {
  1009.               if( key && value && VXIValueGetType(value) == VALUE_STRING)
  1010.               {
  1011.                 SWIswprintf(tempScript, STRINGLEN, 
  1012.                             L"connection.redirect[%d].%s = '%s';n",
  1013.                             idx, key, VXIStringCStr((const VXIString*)value));
  1014.                 AppendStringAlloc(&connectionPropScript, tempScript);
  1015.               }
  1016.               ret = VXIMapGetNextProperty(it, &key, &value);
  1017.             }
  1018.             VXIMapIteratorDestroy(&it);            
  1019.           } /* end-if */
  1020.         } /* end-for */
  1021.         
  1022.         /* destroy the vector */
  1023.         VXIVectorDestroy(&loadedRedirectResources);
  1024.       }
  1025.     } // end-scope Redirect   
  1026.   }  
  1027.   
  1028.   /* Create the cache resource.  The cache resource will be used by
  1029.      the recognizer and prompting components for caching of computed
  1030.      data like compiled grammars and text-to-speech prompts. */
  1031.   cacheResult = SBcacheCreateResource(newPlatform->VXIlog, &newPlatform->VXIcache);
  1032.   CHECK_RESULT_RETURN(newPlatform, "SBcacheCreateResource()", cacheResult);
  1033.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIcache", newPlatform->VXIcache);
  1034.   
  1035.   /* Lookup whether cookies should be accepted */
  1036.   GetVXIBool(configArgs, CLIENT_INET_ACCEPT_COOKIES, &newPlatform->acceptCookies);
  1037.   
  1038.   /* Create the internet component for fetching URLs */
  1039.   inetResult = SBinetCreateResource(newPlatform->VXIlog, 
  1040.                                    newPlatform->VXIcache,
  1041.                                    &newPlatform->VXIinet);
  1042.   CHECK_RESULT_RETURN(newPlatform, "SBinetCreateResource()", inetResult);
  1043.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIinet", newPlatform->VXIinet);
  1044.   /* Now create the jsi resource.  This is used for storing and
  1045.      computing ECMAScript results by the VXI. Internal component
  1046.      required by VXI */
  1047.   jsiResult = SBjsiCreateResource(newPlatform->VXIlog, &newPlatform->VXIjsi);
  1048.   CHECK_RESULT_RETURN(newPlatform, "SBjsiCreateResource()", jsiResult);
  1049.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIjsi", newPlatform->VXIjsi);
  1050.   /* Now loading ECMAScript file if specified in the config file */
  1051.   {
  1052.     const VXIchar * jsFile = NULL;
  1053.     GetVXIString(configArgs, CLIENT_JSI_GLOBAL_SCRIPT_FILE, &jsFile);
  1054.     if( jsFile ) {
  1055.       /* Use inet to open this file */
  1056.       VXIinetResult res;
  1057.       VXIinetStream *stream;
  1058.       VXIulong nread, wcsize = 0;
  1059.       VXIint totalRead = 0;
  1060.       VXIbyte buffer[STRINGLEN];  /* Hopefully the buffer won't overflow */
  1061.       VXIinetInterface *inet = NULL;
  1062.       /* Create the internet component for fetching URLs */
  1063.       inetResult = SBinetCreateResource(newPlatform->VXIlog, newPlatform->VXIcache, &inet);
  1064.       CHECK_RESULT_RETURN(newPlatform, "SBinetCreateResource()", inetResult);
  1065.       res = inet->Open(inet,
  1066.                        MODULE_VXICLIENT, jsFile,
  1067.                        INET_MODE_READ, 0, NULL, 
  1068.                        NULL, &stream);      
  1069.       // successfully open the uri, now try to read the content
  1070.       if( res == VXIinet_RESULT_SUCCESS ) {
  1071.         while(res == VXIinet_RESULT_SUCCESS) {
  1072.           nread = 0;
  1073.           res = inet->Read(inet, buffer, sizeof(buffer), &nread, stream);
  1074.           totalRead += nread;
  1075.         }
  1076.         tempScript[0] = L'';
  1077.         buffer[totalRead] = L'';
  1078.         if (char2wchar(tempScript, (const char*)buffer, STRINGLEN)
  1079.             == VXIplatform_RESULT_BUFFER_TOO_SMALL )
  1080.         {
  1081.           VXIclientError(newPlatform, L"testClient", 9999, L"", L"%s%s", L"buffer", L"too small");
  1082.         }
  1083.         // append to session script
  1084.         AppendStringAlloc(&connectionPropScript, tempScript);
  1085.       } 
  1086.       else {
  1087.        VXIclientError(newPlatform, MODULE_VXICLIENT, 9999, L"", L"%s%s", L"uri not found", jsFile);
  1088.       }
  1089.       // Close Inet Stream
  1090.       inet->Close(inet, &stream);            
  1091.       // Destroy inet
  1092.       SBinetDestroyResource(&inet);        
  1093.     }
  1094.   }
  1095.   // save the connection properties
  1096.   if( connectionPropScript )
  1097.     newPlatform->connectionPropScript = connectionPropScript;
  1098.   /* Create the VXItel implementation resource.  This is required by
  1099.      the VXI for handling telephony functions. The telephony resource
  1100.      uses the session control resource to perform its functions so it
  1101.      must be passed in. */
  1102.   telResult = gblResAPI.TelCreateResource(newPlatform->VXIlog, &newPlatform->VXItel);
  1103.   CHECK_RESULT_RETURN(newPlatform, "VXItelCreateResource()", telResult);
  1104.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXItel", newPlatform->VXItel);
  1105.   
  1106.   /* Now create the prompt resource. The prompting resource takes a
  1107.      logging interface for logging and the inet interface for getting
  1108.      prompts from URIs. */
  1109.   promptResult = gblResAPI.PromptCreateResource(newPlatform->VXIlog, 
  1110.                                                 newPlatform->VXIinet,
  1111.                                                 newPlatform->VXIcache,
  1112.                                                 &newPlatform->VXIprompt);
  1113.   CHECK_RESULT_RETURN(newPlatform, "VXIpromptCreateResource()", promptResult);
  1114.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIprompt", newPlatform->VXIprompt);
  1115.   /* Now create the recognizer resource. The recognizer resource takes
  1116.      a logging interface for logging and the inet interface for
  1117.      getting grammars from URIs. */
  1118.   recResult = gblResAPI.RecCreateResource(newPlatform->VXIlog,
  1119.                                           newPlatform->VXIinet,
  1120.                                           newPlatform->VXIcache,
  1121.                                           newPlatform->VXIprompt,
  1122.                                           newPlatform->VXItel,
  1123.                                           &newPlatform->VXIrec);
  1124.   CHECK_RESULT_RETURN(newPlatform, "VXIrecCreateResource()", recResult);
  1125.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIrec", newPlatform->VXIrec);
  1126.   /* Now create the object resource.  This is used for executing
  1127.      VoiceXML <object> elements */
  1128.   newPlatform->objectResources.log     = newPlatform->VXIlog;
  1129.   newPlatform->objectResources.inet    = newPlatform->VXIinet;
  1130.   newPlatform->objectResources.jsi     = newPlatform->VXIjsi;
  1131.   newPlatform->objectResources.rec     = newPlatform->VXIrec;
  1132.   newPlatform->objectResources.prompt  = newPlatform->VXIprompt;
  1133.   newPlatform->objectResources.tel     = newPlatform->VXItel;
  1134.   newPlatform->objectResources.platform = newPlatform;
  1135.   objResult = VXIobjectCreateResource(&newPlatform->objectResources,
  1136.                                       &newPlatform->VXIobject);
  1137.   CHECK_RESULT_RETURN(newPlatform, "VXIobjectCreateResource()", objResult);
  1138.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIobject", newPlatform->VXIobject);
  1139.   /* Now copy the components required by the VXI into its resource
  1140.      structure for the VXI initialization */
  1141.   newPlatform->resources.log     = newPlatform->VXIlog;
  1142.   newPlatform->resources.inet    = newPlatform->VXIinet;
  1143.   newPlatform->resources.jsi     = newPlatform->VXIjsi;
  1144.   newPlatform->resources.rec     = newPlatform->VXIrec;
  1145.   newPlatform->resources.prompt  = newPlatform->VXIprompt;
  1146.   newPlatform->resources.tel     = newPlatform->VXItel;
  1147.   newPlatform->resources.object  = newPlatform->VXIobject;
  1148.   newPlatform->resources.cache   = newPlatform->VXIcache;
  1149.   interpreterResult = VXIinterpreterCreateResource(&newPlatform->resources,
  1150.                                                    &newPlatform->VXIinterpreter);
  1151.   CHECK_RESULT_RETURN(newPlatform, "VXIinterpreterCreateResource()", interpreterResult);
  1152.   CLIENT_LOG_IMPLEMENTATION(newPlatform, L"VXIinterpreter", newPlatform->VXIinterpreter);
  1153.   /* Set interpreter properties. */
  1154.   {
  1155.     const VXIchar *vxiBeepURI = NULL;
  1156.     const VXIchar *vxiDefaultsURI = NULL;
  1157.     VXIMap *vxiProperties = VXIMapCreate();
  1158.     CHECK_MEMALLOC_RETURN(newPlatform, vxiProperties, "VXI properties");
  1159.     GetVXIString(configArgs, CLIENT_VXI_BEEP_URI, &vxiBeepURI);
  1160.     if (vxiBeepURI != NULL) {
  1161.       VXIString * val = VXIStringCreate(vxiBeepURI);
  1162.       CHECK_MEMALLOC_RETURN(newPlatform, val, "VXI properties beep URI");
  1163.       VXIMapSetProperty(vxiProperties, VXI_BEEP_AUDIO, (VXIValue *) val);
  1164.     }
  1165.     GetVXIString(configArgs, CLIENT_VXI_DEFAULTS_URI, &vxiDefaultsURI);
  1166.     if (vxiDefaultsURI != NULL) {
  1167.       VXIString * val = VXIStringCreate(vxiDefaultsURI);
  1168.       CHECK_MEMALLOC_RETURN(newPlatform, val, "VXI properties beep URI");
  1169.       VXIMapSetProperty(vxiProperties, VXI_PLATFORM_DEFAULTS, (VXIValue*) val);
  1170.     }
  1171.     if (VXIMapNumProperties(vxiProperties) != 0)
  1172.       newPlatform->VXIinterpreter->SetProperties(newPlatform->VXIinterpreter,
  1173.                                                  vxiProperties);
  1174.     VXIMapDestroy(&vxiProperties);
  1175.   }
  1176.   VXIclientDiag(newPlatform, CLIENT_API_TAG, L"VXIplatformCreateResources",
  1177.                 L"exiting: rc = %d, 0x%p",
  1178.                 VXIplatform_RESULT_SUCCESS, newPlatform);
  1179.   /* Return the platform resources that have been created */
  1180.   *platform = newPlatform;  
  1181.   return VXIplatform_RESULT_SUCCESS;
  1182. }
  1183. /**
  1184.  * Destroy resources for the platform.
  1185.  *
  1186.  * This function destroys all the resources needed by the VXI to
  1187.  * execute.  This includes both APIs that the VXI calls directly and
  1188.  * the APIS that those components call.  All components in the OpenVXI PIK are
  1189.  * exposed here.<p>
  1190.  *
  1191.  * The resources will be freed from the platform pointer which is
  1192.  * deleted and set to NULL in this function.  
  1193.  */
  1194. VXIplatformResult VXIplatformDestroyResources(VXIplatform **platform)
  1195. {
  1196.   
  1197.   VXItelResult telResult;
  1198.   VXIlogResult logResult;
  1199.   VXIpromptResult promptResult;
  1200.   VXIjsiResult jsiResult;
  1201.   VXIrecResult recResult;
  1202.   VXIcacheResult cacheResult;
  1203.   VXIinetResult inetResult;
  1204.   VXIobjResult objResult;
  1205.   VXIplatform *pPlatform = NULL;
  1206.   if ((platform == NULL) || (*platform == NULL)) {
  1207.     return VXIplatform_RESULT_INVALID_ARGUMENT;
  1208.   }
  1209.   if (!gblPlatformInitialized) {
  1210.     return VXIplatform_RESULT_NOT_INITIALIZED;
  1211.   }
  1212.   pPlatform = *platform;
  1213.   
  1214.   VXIclientDiag(pPlatform, CLIENT_API_TAG, L"VXIplatformDestroyResources",
  1215.                 L"entering: 0x%p", platform);
  1216.   
  1217.   /* Destroy the VoiceXML interpreter */
  1218.   VXIinterpreterDestroyResource(&pPlatform->VXIinterpreter);
  1219.   /* Destroy the object handler */
  1220.   objResult = VXIobjectDestroyResource(&pPlatform->VXIobject);
  1221.   CHECK_RESULT_RETURN(pPlatform, "VXIobjectDestroyResource()", objResult);
  1222.   /* Destroy the recognizer */
  1223.   recResult = gblResAPI.RecDestroyResource(&pPlatform->VXIrec);
  1224.   CHECK_RESULT_RETURN(pPlatform, "VXIrecDestroyResource()", recResult);
  1225.   /* Destroy the prompt engine */
  1226.   promptResult = gblResAPI.PromptDestroyResource(&pPlatform->VXIprompt);
  1227.   CHECK_RESULT_RETURN(pPlatform, "VXIpromptDestroyResource()", promptResult);
  1228.   /* Destroy the telephony component */
  1229.   telResult = gblResAPI.TelDestroyResource(&pPlatform->VXItel);
  1230.   CHECK_RESULT_RETURN(pPlatform, "VXItelDestroyResource()", telResult);
  1231.   /* Destroy the ECMAScript interpreter */
  1232.   jsiResult = SBjsiDestroyResource(&pPlatform->VXIjsi);
  1233.   CHECK_RESULT_RETURN(pPlatform, "SBjsiDestroyResource()", jsiResult);
  1234.   /* Destroy the internet component */
  1235.   inetResult = SBinetDestroyResource(&pPlatform->VXIinet);
  1236.   CHECK_RESULT_RETURN(pPlatform, "SBinetDestroyResource()", inetResult);
  1237.   
  1238.   /* Destroy the cache component */
  1239.   cacheResult = SBcacheDestroyResource(&pPlatform->VXIcache);
  1240.   CHECK_RESULT_RETURN(pPlatform, "SBcacheDestroyResource()", cacheResult);
  1241.   /* unregister all listners */
  1242.   UnregisterDiagnosticListener(pPlatform->VXIlog,DiagnosticListener,pPlatform->logData);
  1243.   UnregisterErrorListener(pPlatform->VXIlog,ErrorListener,pPlatform->logData);
  1244.   UnregisterEventListener(pPlatform->VXIlog,EventListener,pPlatform->logData);
  1245.   UnregisterContentListener(pPlatform->VXIlog,ContentListener,pPlatform->logData);
  1246.   if( pPlatform->logData ) free(pPlatform->logData);
  1247.   pPlatform->logData = NULL;
  1248.   /* Destroy the log component */
  1249.   logResult = SBlogDestroyResource(&pPlatform->VXIlog);
  1250.   CHECK_RESULT_RETURN(NULL, "SBlogDestroyResource()", logResult);
  1251.   /* release session connection ECMAScript */
  1252.   if( pPlatform->connectionPropScript )
  1253.   {
  1254.     free(pPlatform->connectionPropScript);
  1255.     pPlatform->connectionPropScript = NULL;
  1256.   }
  1257.   /* Release the platform resource handle */
  1258.   free(*platform);
  1259.   *platform = NULL;
  1260.   VXIclientDiag(NULL, CLIENT_API_TAG, L"VXIplatformDestroyResources",
  1261.                 L"exiting: rc = %d", VXIplatform_RESULT_SUCCESS);
  1262.   
  1263.   return VXIplatform_RESULT_SUCCESS;
  1264. }
  1265. /**
  1266.  * Enables the hardware to wait for a call
  1267.  *
  1268.  * This function enables the hardware to wait for a call using the
  1269.  * resources specified by the passed platform pointer. It blocks until
  1270.  * the hardware is enabled and then returns
  1271.  * VXIplatform_RESULT_SUCCESS.  This must be calld before
  1272.  * VXIplatformWaitForCall.
  1273.  */
  1274. VXIplatformResult VXIplatformEnableCall(VXIplatform *platform)
  1275. {
  1276.   VXItelResult telResult;
  1277.   VXItelInterfaceEx *telIntfEx;  /* extension of VXItel API */
  1278.   VXIclientDiag(platform, CLIENT_API_TAG, L"VXIplatformEnableCall",
  1279.                 L"entering: 0x%p", platform);
  1280.   if (!gblPlatformInitialized)
  1281.     return VXIplatform_RESULT_NOT_INITIALIZED;
  1282.   if (platform == NULL)
  1283.     return VXIplatform_RESULT_INVALID_ARGUMENT;
  1284.   VXIclientDiag(platform, CLIENT_GEN_TAG, L"Entering EnableCall", NULL);
  1285.   /* Enable calls using the telephony interface */
  1286.   if (wcsstr(platform->VXItel->GetImplementationName( ), L".VXItel")) {
  1287.     telIntfEx = (VXItelInterfaceEx*) platform->VXItel;
  1288.     telResult = telIntfEx->EnableCall(telIntfEx);
  1289.   } else {
  1290.     telResult = VXItel_RESULT_UNSUPPORTED;
  1291.   }
  1292.   if (telResult != VXItel_RESULT_SUCCESS){
  1293.     VXIclientError(platform, MODULE_VXICLIENT, 100, L"VXItel EnableCall failed",
  1294.                    L"%s%d", L"rc", telResult);
  1295.     return (telResult > 0 ? VXIplatform_RESULT_FAILURE : 
  1296.                             VXIplatform_RESULT_TEL_ERROR);
  1297.   }
  1298.   VXIclientDiag(platform, CLIENT_API_TAG, L"VXIplatformEnableCall",
  1299.                 L"exiting: rc = %d", VXIplatform_RESULT_SUCCESS);
  1300.   VXIclientDiag(platform, CLIENT_GEN_TAG, L"Leaving EnableCall", NULL);
  1301.   return VXIplatform_RESULT_SUCCESS;
  1302. }
  1303. /**
  1304.  * Wait for a call.
  1305.  *
  1306.  * This function waits for a call and then answers it using the
  1307.  * resources specified by the passed platform pointer. It blocks until
  1308.  * a call is recieved and then returns VXIplatform_RESULT_SUCCESS.
  1309.  */
  1310. VXIplatformResult VXIplatformWaitForCall(VXIplatform *platform)
  1311. {
  1312.   VXItelResult telResult;
  1313.   VXItelInterfaceEx *telIntfEx;  /* extension of VXItel API */
  1314.   VXIclientDiag(platform, CLIENT_API_TAG, L"VXIplatformWaitForCall",
  1315.                 L"entering: 0x%p", platform);
  1316.   if (platform == NULL)
  1317.     return VXIplatform_RESULT_INVALID_ARGUMENT;
  1318.   /* Clean up from prior calls if necessary */
  1319.   if (platform->telephonyProps) {
  1320.     VXIMapDestroy(&platform->telephonyProps);
  1321.     platform->telephonyProps = NULL;
  1322.   }
  1323.   /* Wait for calls using the telephony interface */
  1324.   if (wcsstr(platform->VXItel->GetImplementationName( ), L".VXItel")) {
  1325.     telIntfEx = (VXItelInterfaceEx *) platform->VXItel;
  1326.     telResult = telIntfEx->WaitForCall(telIntfEx, &platform->telephonyProps);
  1327.   } else {
  1328.     telResult = VXItel_RESULT_UNSUPPORTED;
  1329.   }
  1330.   if (telResult != VXItel_RESULT_SUCCESS){
  1331.     VXIclientError(platform, MODULE_VXICLIENT, 100, 
  1332.                    L"VXItel WaitForCall failed", L"%s%d", L"rc", telResult);
  1333.     return (telResult > 0 ? VXIplatform_RESULT_FAILURE : 
  1334.                             VXIplatform_RESULT_TEL_ERROR);
  1335.   }
  1336.   VXIclientDiag(platform, CLIENT_API_TAG, L"VXIplatformWaitForCall",
  1337.                 L"exiting: rc = %d", VXIplatform_RESULT_SUCCESS);
  1338.   VXIclientDiag(platform, CLIENT_GEN_TAG, L"Leaving WaitForCall", NULL);
  1339.   return VXIplatform_RESULT_SUCCESS;
  1340. }
  1341. /**
  1342.  * Process a VoiceXML document.
  1343.  *
  1344.  * This function processes a VoiceXML document using the resources
  1345.  * specified by the passed platform pointer. It blocks until the
  1346.  * processing is complete and then returns VXIplatform_RESULT_SUCCESS.
  1347.  */
  1348. VXIplatformResult VXIplatformProcessDocument(const VXIchar *url,
  1349.                VXIchar **sessionScript,
  1350.                VXIValue **documentResult,
  1351.                VXIplatform *platform)
  1352. {
  1353.   VXIinterpreterResult interpreterResult;
  1354.   VXIinetResult inetResult;
  1355.   VXItelResult telResult;
  1356.   VXIpromptResult promptResult;
  1357.   VXIrecResult recResult;
  1358.   VXIchar *allocatedUrl = NULL;
  1359.   const VXIchar *finalUrl = NULL;
  1360.   VXIchar ani[128], dnis[128];
  1361.   VXIVector *cookieJar = NULL;
  1362.   VXIchar tempScript[STRINGLEN];
  1363.   
  1364.   if (!gblPlatformInitialized) {
  1365.     return VXIplatform_RESULT_NOT_INITIALIZED;
  1366.   }
  1367.   VXIclientDiag(platform, CLIENT_API_TAG, L"VXIplatformProcessDocument",
  1368.                 L"entering: %s, 0x%p, 0x%p", 
  1369.                 url, documentResult, platform);
  1370.   /* initialization of variables */
  1371.   memset(ani, 0, sizeof(ani));
  1372.   memset(dnis, 0, sizeof(dnis));
  1373.   memset(tempScript, 0, sizeof(tempScript));
  1374.   
  1375.   /* If the URL is really a local file path, change it to be a full
  1376.      path so relative URL references in it can be resolved */
  1377.   finalUrl = url;
  1378.   if (wcschr(url, L':') == NULL) {
  1379.     allocatedUrl = (VXIchar *) calloc(MAX_PATH + 1, sizeof(VXIchar));
  1380.     CHECK_MEMALLOC_RETURN(platform, allocatedUrl, "Allocated URL");
  1381. #ifdef WIN32
  1382.     /* Win32 version */
  1383.     {
  1384.       
  1385. #ifdef UNICODE
  1386.       VXIchar *ignored;
  1387.       if (!allocatedUrl)
  1388.         CHECK_RESULT_RETURN(platform, "full path allocation", -1);      
  1389.       if (GetFullPathName(url, MAX_PATH, allocatedUrl, &ignored) <= 0)
  1390.         CHECK_RESULT_RETURN(platform, "Win32 GetFullPathName()", -1);
  1391. #else
  1392.       int len = wcslen(url);
  1393.       char *ignored;
  1394.       char fpath[MAX_PATH+1];
  1395.       char *turl = (char*)malloc(sizeof(char*)*(len+1));
  1396.       CHECK_MEMALLOC_RETURN(platform, turl, "Allocated temp. URL");
  1397.       wchar2char(turl, url, len+1);
  1398.       if (GetFullPathName(turl, MAX_PATH, fpath, &ignored) <= 0)
  1399.         CHECK_RESULT_RETURN(platform, "Win32 GetFullPathName()", -1);
  1400.       char2wchar(allocatedUrl, fpath, MAX_PATH);  
  1401.       free( turl );    
  1402. #endif
  1403.     }
  1404. #else
  1405.     {
  1406.       /* Unix version */
  1407.       char cwd[MAX_PATH + 1];
  1408.       cwd[0] = '';
  1409.       
  1410.       getcwd (cwd, MAX_PATH);
  1411.       if (!cwd[0])
  1412.         CHECK_RESULT_RETURN(platform, "getcwd()", -1);      
  1413.       if (strlen(cwd) + wcslen(url) + 1 > MAX_PATH)
  1414.         CHECK_RESULT_RETURN(platform, 
  1415.           "MAX_PATH exceeded for getting full path", -1);      
  1416.       char2wchar(allocatedUrl, cwd, MAX_PATH + 1);
  1417.       wcscat (allocatedUrl, L"/");
  1418.       wcscat (allocatedUrl, url);
  1419.     }
  1420. #endif
  1421.     finalUrl = allocatedUrl;
  1422.   }
  1423.   /* Set up SBinet for a new call by enabling or disabling cookies as
  1424.      configured for the resource. When cookies are enabled, this
  1425.      implementation establishes a new cookie jar for each new call,
  1426.      and destroys it at the end of the call. This makes it so cookies
  1427.      do not persist across calls, meaning applications can use cookies
  1428.      to keep track of in-call state but not track state and callers
  1429.      across calls.
  1430.      Fully persistant cookies require a highly accurate mechanism for
  1431.      identifying individual callers (caller ID is not usually
  1432.      sufficient), a database for storing the cookie jar for each
  1433.      caller, and a way for individual callers to establish their
  1434.      privacy policy (web site or VoiceXML pages that allow them to
  1435.      configure whether cookies are enabled and cookie filters). Once
  1436.      in place, merely store the cookie jar at the end of the call,
  1437.      then once the caller is identified set the cookie jar to the
  1438.      previously stored one.  
  1439.   */
  1440.   if (platform->acceptCookies) {
  1441.     cookieJar = VXIVectorCreate();
  1442.     CHECK_MEMALLOC_RETURN(platform, cookieJar, "VXIinet cookie jar");
  1443.   }
  1444.   inetResult = platform->VXIinet->SetCookieJar (platform->VXIinet, cookieJar);
  1445.   CHECK_RESULT_RETURN(platform, "VXIinet->SetCookieJar()", inetResult);
  1446.   VXIVectorDestroy (&cookieJar);
  1447.   /* Set up the telephony interface for a new call. Begin session has to 
  1448.      be called at the start of every call.  End session has to be
  1449.      called at the end of every call. */
  1450.   telResult = platform->VXItel->BeginSession(platform->VXItel, NULL);
  1451.   CHECK_RESULT_RETURN(platform, "VXItel->BeginSession()", telResult);
  1452.   /* Set up the prompt interface for a new call. Begin session has to 
  1453.      be called at the start of every call.  End session has to be
  1454.      called at the end of every call. */
  1455.   {     
  1456.     VXIMap * pProps = VXIMapCreate();
  1457.     // Create call num property
  1458.     VXIMapSetProperty(pProps, CLIENT_CURRENT_NUMCALL, 
  1459.                       (VXIValue*)VXIULongCreate(platform->numCall));
  1460.     promptResult = platform->VXIprompt->BeginSession(platform->VXIprompt, pProps);
  1461.     VXIMapDestroy(&pProps);
  1462.     CHECK_RESULT_RETURN(platform, "VXIprompt->BeginSession()", promptResult);
  1463.   }
  1464.   /* Set up the recognizer for a new call. Begin session has to 
  1465.      be called at the start of every call.  End session has to be
  1466.      called at the end of every call. */
  1467.   recResult = platform->VXIrec->BeginSession(platform->VXIrec, NULL);
  1468.   CHECK_RESULT_RETURN(platform, "VXIrec->BeginSession()", recResult);
  1469.   /* Put the telephony map into the session ECMAScript so they will be
  1470.      referenced as session.telephone.*. */
  1471.   if (platform->telephonyProps) {
  1472.     const VXIValue *val;
  1473.     val = VXIMapGetProperty(platform->telephonyProps, L"ani");
  1474.     if ((val) && (VXIValueGetType(val) == VALUE_STRING))
  1475.       wcscpy(ani, VXIStringCStr((const VXIString *) val));
  1476.     val = VXIMapGetProperty(platform->telephonyProps, L"dnis");
  1477.     if ((val) && (VXIValueGetType(val) == VALUE_STRING))
  1478.       wcscpy(dnis, VXIStringCStr((const VXIString *) val));
  1479.     
  1480.     /* Create a ECMAScript for telephony properties in session scope */
  1481.     SWIswprintf(tempScript, STRINGLEN, 
  1482.                             L"var telephone = new Object();n"
  1483.                             L"telephone.ani = '%s';n"
  1484.                             L"telephone.dnis = '%s';n", ani, dnis);
  1485.     /* Append to sessionScript */
  1486.     AppendStringAlloc(sessionScript, tempScript);                            
  1487.     VXIMapDestroy(&platform->telephonyProps);                              
  1488.     platform->telephonyProps = NULL;
  1489.   }
  1490.   
  1491.   /* Store properties for querying the browser implementation in the
  1492.      session ECMAScript, they can be referenced as navigator.* (technically
  1493.      session.navigator.* but since the session scope is the global
  1494.      scope, navigator.* will be found, and the navigator.* form is
  1495.      what is universally used to query this information for HTML
  1496.      browsers). */
  1497.   {
  1498.     /* User agent name is configured */
  1499.     const VXIchar *start, *end;
  1500.     VXIchar ac[128], av[128];
  1501.     /* Code name is the portion of the user agent up to the slash */
  1502.     end = wcschr(gblUserAgentName, L'/');
  1503.     if ((end) && (*end)) {
  1504.       memset(ac, 0, sizeof(ac));
  1505.       wcsncpy(ac, gblUserAgentName, end - gblUserAgentName);
  1506.     }
  1507.     else
  1508.       CHECK_RESULT_RETURN(platform, "User Agent Name parse",
  1509.                           VXIplatform_RESULT_INVALID_ARGUMENT);
  1510.     /* Version is the portion of the user agent after the slash and up
  1511.        through the alphanumeric sequence that follows it */
  1512.     start = end + 1;
  1513.     while (ISWSPACE(*start)) start++;
  1514.     end = start;
  1515.     while ((ISWALPHA(*end)) || (ISWDIGIT(*end)) ||
  1516.            (*end == L'.')) end++;    
  1517.     if( start && *start )
  1518.     {
  1519.       memset(av, 0, sizeof(av));
  1520.       wcsncpy(av, start, end-start);
  1521.     }
  1522.     /* Create a ECMAScript for navigator properties in session scope */
  1523.     SWIswprintf(tempScript, STRINGLEN, 
  1524.                 L"var navigator = new Object();n"
  1525.                 L"navigator.appName = 'Vocalocity OpenVXI';n"
  1526.                 L"navigator.userAgent = '%s';n"
  1527.                 L"navigator.appCodeName = '%s';n"
  1528.                 L"navigator.appVersion = '%s';n",
  1529.                 gblUserAgentName, ac, av );
  1530.     AppendStringAlloc(sessionScript, tempScript);  
  1531.   }  
  1532.   /* Set session connection properties */
  1533.   /* the connection ECMAScript has been created at platform creation */
  1534.   AppendStringAlloc(sessionScript, platform->connectionPropScript);
  1535.   /* Ready to run the VXI.  This will return with a result of one of
  1536.      the following:
  1537.      a) a VoiceXML page hits an <exit> tag. In this case result will
  1538.         contain the value of the exit.
  1539.      b) A page simply has no where to go.  The application falls out
  1540.         of VoiceXML and ends. result will be NULL in this case.
  1541.      c) An error occurs.  result will be NULL in this case.
  1542.      Note that the session arguments contain all the information that
  1543.      the platform wants to put into the ECMAScript variable session at
  1544.      channel startup.
  1545.      
  1546.      The initial URL will be fetched with a POST sending the session
  1547.      arguments in the initial POST.  
  1548.   */
  1549.   interpreterResult = platform->VXIinterpreter->Run(platform->VXIinterpreter,
  1550.                                                     finalUrl, *sessionScript,
  1551.                                                     documentResult);
  1552.   CHECK_RESULT_NO_RETURN(platform, "VXIinterpreter->Run()", interpreterResult);
  1553.   if (allocatedUrl)
  1554.     free(allocatedUrl);
  1555.   /* Now end the recognizer, prompt, and tel session */
  1556.   recResult = platform->VXIrec->EndSession(platform->VXIrec, NULL);
  1557.   CHECK_RESULT_RETURN(platform, "VXIrec->EndSession()", recResult);
  1558.   promptResult = platform->VXIprompt->EndSession(platform->VXIprompt, NULL);
  1559.   CHECK_RESULT_RETURN(platform, "VXIprompt->EndSession()", promptResult);
  1560.   telResult = platform->VXItel->EndSession(platform->VXItel, NULL);
  1561.   CHECK_RESULT_RETURN(platform, "VXItel->EndSession()", telResult);
  1562.   VXIclientDiag(platform, CLIENT_API_TAG, L"VXIplatformProcessDocument",
  1563.                 L"exiting: rc = %d, 0x%p", interpreterResult, 
  1564.                 (documentResult ? *documentResult : NULL));
  1565.           
  1566.   /* Do a map of the interpreter result to a platform result */
  1567.   return ConvertInterpreterResult (0);
  1568. }
  1569. /**
  1570.  * Enable/disable diagnostic tags based on the passed configuration data
  1571.  */
  1572. VXIplatformResult VXIclientControliagnosticTags
  1573. (
  1574.   const VXIMap *configArgs,
  1575.   VXIplatform  *platform
  1576. )
  1577. {
  1578.   VXIplatformResult rc = VXIplatform_RESULT_SUCCESS;
  1579.   const VXIchar *key;
  1580.   const VXIValue *val;
  1581.   int prefixlen = wcslen(CLIENT_LOG_DIAG_TAG_KEY_PREFIX);
  1582.   VXIMapIterator *iter;
  1583.   VXIlogInterface *log = NULL;
  1584.   SBlogInterface *sbLog = NULL;
  1585.   if (!configArgs)
  1586.     rc = VXIplatform_RESULT_INVALID_ARGUMENT;
  1587.   if ((platform) && (platform->VXIlog))
  1588.     log = platform->VXIlog;
  1589.   else if (gblLog)
  1590.     log = gblLog;
  1591.   else
  1592.     return VXIlog_RESULT_NON_FATAL_ERROR;
  1593.   /* Determine the implementation */
  1594.   if (wcsstr(log->GetImplementationName( ), L".SBlog")) {
  1595.     sbLog = (SBlogInterface *) log;
  1596.   } else {
  1597.     VXIclientError(platform, MODULE_VXICLIENT, 105,
  1598.       L"Unknown log implementation"
  1599.       L" for for enabling diagnostic tags", L"%s%s", 
  1600.       L"implementationName", log->GetImplementationName( ));
  1601.     return VXIlog_RESULT_FAILURE;
  1602.   }
  1603.   /* Configure the diagnostic tags */
  1604.   iter = VXIMapGetFirstProperty(configArgs,&key,&val);
  1605.   if (iter) {
  1606.     do {
  1607.       if (wcsncmp(key, CLIENT_LOG_DIAG_TAG_KEY_PREFIX, prefixlen)==0) {
  1608.         if (VXIValueGetType(val) == VALUE_INTEGER) {
  1609.           VXIint tflag = VXIIntegerValue((const VXIInteger*)val);
  1610.           /* get suffix TAG ID from the key */
  1611.           VXIchar *ptr;
  1612.           VXIunsigned tagID = (VXIunsigned) wcstol (key + prefixlen,&ptr,10);
  1613.           sbLog->ControlDiagnosticTag(sbLog, tagID, tflag ? TRUE : FALSE);
  1614.         }
  1615.         else {
  1616.           VXIclientError(platform, MODULE_VXICLIENT, 103, L"Invalid type for "
  1617.                         L"configuration parameter, VXIInteger required", 
  1618.                         L"%s%s", L"PARAM", key);
  1619.         }
  1620.       }
  1621.     } while (VXIMapGetNextProperty(iter, &key, &val) == 0);
  1622.   }
  1623.   VXIMapIteratorDestroy(&iter);
  1624.   return rc;
  1625. }
  1626. /**
  1627.  * Convert VXIinterpreterResult codes to VXIplatformResult codes
  1628.  */
  1629. VXIplatformResult ConvertInterpreterResult(VXIinterpreterResult result)
  1630. {
  1631.   VXIplatformResult rc;
  1632.   switch (result) {
  1633.   case VXIinterp_RESULT_FATAL_ERROR:
  1634.     rc = VXIplatform_RESULT_INTERPRETER_ERROR;
  1635.     break;
  1636.   case VXIinterp_RESULT_OUT_OF_MEMORY:
  1637.     rc = VXIplatform_RESULT_OUT_OF_MEMORY;
  1638.     break;
  1639.   case VXIinterp_RESULT_PLATFORM_ERROR:
  1640.     rc = VXIplatform_RESULT_PLATFORM_ERROR;
  1641.     break;
  1642.   case VXIinterp_RESULT_INVALID_PROP_NAME:
  1643.     rc = VXIplatform_RESULT_INVALID_PROP_NAME;
  1644.     break;
  1645.   case VXIinterp_RESULT_INVALID_PROP_VALUE:
  1646.     rc = VXIplatform_RESULT_INVALID_PROP_VALUE;
  1647.     break;
  1648.   case VXIinterp_RESULT_INVALID_ARGUMENT:
  1649.     rc = VXIplatform_RESULT_INVALID_ARGUMENT;
  1650.     break;
  1651.   case VXIinterp_RESULT_SUCCESS:
  1652.   case VXIinterp_RESULT_STOPPED:
  1653.     rc = VXIplatform_RESULT_SUCCESS;
  1654.     break;
  1655.   case VXIinterp_RESULT_FAILURE:
  1656.     rc = VXIplatform_RESULT_FAILURE;
  1657.     break;
  1658.   case VXIinterp_RESULT_FETCH_TIMEOUT:
  1659.   case VXIinterp_RESULT_FETCH_ERROR:
  1660.   case VXIinterp_RESULT_INVALID_DOCUMENT:
  1661.     rc = VXIplatform_RESULT_NON_FATAL_ERROR;
  1662.     break;
  1663.   case VXIinterp_RESULT_UNSUPPORTED:
  1664.     rc = VXIplatform_RESULT_UNSUPPORTED;
  1665.     break;
  1666.   default:
  1667.     if (result > 0)
  1668.       rc = VXIplatform_RESULT_NON_FATAL_ERROR;
  1669.     else
  1670.       rc = VXIplatform_RESULT_INTERPRETER_ERROR;
  1671.   }  
  1672.   return rc;
  1673. }
  1674. /**
  1675.  * Log an error
  1676.  */
  1677. VXIlogResult VXIclientError
  1678. (
  1679.   VXIplatform *platform, 
  1680.   const VXIchar *moduleName,
  1681.   VXIunsigned errorID, 
  1682.   const VXIchar *errorIDText,
  1683.   const VXIchar *format, ...
  1684. )
  1685. {
  1686.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  1687.   VXIlogInterface *log = NULL;
  1688.   va_list arguments;
  1689.   if ((platform) && (platform->VXIlog))
  1690.     log = platform->VXIlog;
  1691.   if (format) {
  1692.     va_start(arguments, format);
  1693.     if ( log )
  1694.       rc = (*log->VError)(log, moduleName, errorID, format, arguments);
  1695.     else
  1696.       rc = VXIclientVErrorToConsole(moduleName, errorID, errorIDText, format,
  1697.               arguments);
  1698.     va_end(arguments);
  1699.   } else {
  1700.     if ( log )
  1701.       rc = (*log->Error)(log, moduleName, errorID, NULL);
  1702.     else
  1703.       rc = VXIclientErrorToConsole(moduleName, errorID, errorIDText);
  1704.   }
  1705.   return rc;
  1706. }
  1707. /**
  1708.  * Log a diagnostic message
  1709.  */
  1710. VXIlogResult 
  1711. VXIclientDiag
  1712. (
  1713.   VXIplatform *platform, 
  1714.   VXIunsigned tag, 
  1715.   const VXIchar *subtag, 
  1716.   const VXIchar *format, ...
  1717. )
  1718. {
  1719.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  1720.   VXIlogInterface *log = NULL;
  1721.   va_list arguments;
  1722.   if ((platform) && (platform->VXIlog))
  1723.     log = platform->VXIlog;
  1724.   if (format) {
  1725.     va_start(arguments, format);
  1726.     if( log )
  1727.       rc = (*log->VDiagnostic)(log, tag, subtag, format, arguments);
  1728.     va_end(arguments);
  1729.   } else {
  1730.     if( log )
  1731.       rc = (*log->Diagnostic)(log, tag, subtag, NULL);
  1732.   }
  1733.   return rc;
  1734. }
  1735. /**
  1736.  * Log errors to the console, only used for errors that occur prior
  1737.  * to initializing the log subsystem
  1738.  */
  1739. VXIlogResult VXIclientErrorToConsole
  1740. (
  1741.   const VXIchar *moduleName,
  1742.   VXIunsigned errorID,
  1743.   const VXIchar *errorIDText
  1744. )
  1745. {
  1746.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  1747.   /* Get the severity */
  1748.   const VXIchar *severity;
  1749.   if (errorID < 200)
  1750.     severity = L"CRITICAL";
  1751.   else if (errorID < 300)
  1752.     severity = L"SEVERE";
  1753.   else
  1754.     severity = L"WARNING";
  1755.   /* OS-dependent routines to handle wide chars. */
  1756. #ifdef WIN32
  1757.   fwprintf(stderr, L"%ls: %ls|%u|%lsn", severity, moduleName, errorID,
  1758.      errorIDText);
  1759. #else
  1760.   fprintf(stderr, "%ls: %ls|%u|%lsn", severity, moduleName, errorID,
  1761.     errorIDText);
  1762. #endif
  1763.   return rc;
  1764. }
  1765. VXIlogResult 
  1766. VXIclientVErrorToConsole
  1767. (
  1768.   const VXIchar *moduleName, 
  1769.   VXIunsigned errorID,
  1770.   const VXIchar *errorIDText, 
  1771.   const VXIchar *format,
  1772.   va_list arguments
  1773. )
  1774. {
  1775.   int argCount;
  1776.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  1777.   const VXIchar *in;
  1778.   VXIchar *out, tempFormat[256];
  1779.   /* Get the severity */
  1780.   const VXIchar *severity;
  1781.   if (errorID < 200)
  1782.     severity = L"CRITICAL";
  1783.   else if (errorID < 300)
  1784.     severity = L"SEVERE";
  1785.   else
  1786.     severity = L"WARNING";
  1787.   /* Properly delimit the format arguments for human consumption */
  1788.   argCount = 0;
  1789.   if (format) {
  1790.     for (in = format, out = tempFormat; *in != L''; in++, out++) {
  1791.       if (*in == L'%') {
  1792.         argCount++;
  1793.         *out = (argCount % 2 == 0 ? L'=' : L'|');
  1794.         out++;
  1795.       }
  1796.       *out = *in;
  1797.     }
  1798.     *out = L'n';
  1799.     out++;
  1800.     *out = L'';
  1801. #ifdef WIN32
  1802.     fwprintf(stderr, L"%ls: %ls|%u|%ls", severity, moduleName, errorID,
  1803.        errorIDText);
  1804.     vfwprintf(stderr, tempFormat, arguments);
  1805. #else
  1806.     /* VXIvswprintf( ) handles the format conversion if necessary
  1807.        from Microsoft Visual C++ run-time library/GNU gcc 2.x C
  1808.        library notation to GNU gcc 3.x C library (and most other UNIX
  1809.        C library) notation: %s -> %ls, %S -> %s. Unfortunately there
  1810.        is no single format string representation that can be used
  1811.        universally. */
  1812.     {
  1813.       VXIchar tempBuf[4096];
  1814.       VXIvswprintf(tempBuf, 4096, tempFormat, arguments);
  1815.       fprintf(stderr, "%ls: %ls|%u|%ls%lsn", severity, moduleName, errorID,
  1816.         errorIDText, tempBuf);
  1817.     }
  1818. #endif
  1819.   } else {
  1820. #ifdef WIN32
  1821.     fwprintf(stderr, L"%ls: %ls|%u|%lsn", severity, moduleName, errorID,
  1822.        errorIDText);
  1823. #else
  1824.     fprintf(stderr, "%ls: %ls|%u|%lsn", severity, moduleName, errorID,
  1825.       errorIDText);
  1826. #endif
  1827.   }
  1828.   
  1829.   return rc;
  1830. }