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

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. #ifndef _SB_USE_STD_NAMESPACE
  23. #define _SB_USE_STD_NAMESPACE
  24. #endif
  25. #define SBINET_EXPORTS
  26. #include "VXItypes.h"
  27. #include "VXIvalue.h"
  28. #include "VXIinet.h"
  29. #include "VXItrd.h"
  30. #include "VXIlog.h"
  31. #include <SBinet.h>
  32. #include "SBinetLog.h"
  33. #include "SBinetHttpCacheStream.hpp"
  34. #include "SBinetTimedStream.hpp"
  35. #include "SBinetFileStream.hpp"
  36. #include "SBinetChannel.h"
  37. #include "SBinetURL.h"
  38. #include "SBinetCookie.h"
  39. #include "SBinetProxyMatcher.hpp"
  40. #include "SBinetUtils.hpp"
  41. #include "SBinetHttpConnection.hpp"
  42. #include "SBinetSSLsocket.hpp"
  43. #include <SWIList.hpp>
  44. #include <SWIinputStream.hpp>
  45. #include <SWIoutputStream.hpp>
  46. #include <SWIdataOutputStream.hpp>
  47. #include <SWIipAddress.hpp>
  48. /*****************************************************************************
  49.  *****************************************************************************
  50.  * SBinetChannel Implementation
  51.  *****************************************************************************
  52.  *****************************************************************************
  53.  */
  54. #include <stdexcept>
  55. #include <string>
  56. #include <map>
  57.  
  58. //
  59. // override < and == operators for SBinetMD5 type
  60. //
  61. inline bool operator< (const SBinetMD5 & x,
  62.                        const SBinetMD5 & y)
  63. { return memcmp(x.raw, y.raw, 16 * sizeof(unsigned char)) < 0; }
  64. inline bool operator==(const SBinetMD5 & x,
  65.                        const SBinetMD5 & y)
  66. { return memcmp(x.raw, y.raw, 16 * sizeof(unsigned char)) == 0; }
  67. class VXItrdMutexRef {
  68. public:
  69.   VXItrdMutexRef()
  70.   : _refCount(1), _refMutex(NULL)
  71.   {
  72.     VXItrdMutexCreate(&_refMutex);
  73.   }
  74.   virtual ~VXItrdMutexRef()
  75.   {
  76.     VXItrdMutexDestroy(&_refMutex);
  77.   }  
  78.   
  79.   VXItrdMutex   *_refMutex;
  80.   VXIulong      _refCount;
  81.   SBinetMD5     _md5Key;
  82. };
  83. typedef std::map<SBinetMD5, VXItrdMutexRef*> SBINETLOCKMAP;
  84. typedef std::map<SBinetMD5, SBinetHttpCacheStream* > SBINETMD5CACHEMAP;
  85. //Static data members
  86. VXItrdMutex *SBinetChannel::_extensionRulesMutex = NULL;
  87. VXIMap *SBinetChannel::_extensionRules = NULL;
  88. SBinetNString *SBinetChannel::_userAgent = NULL;
  89. double SBinetChannel::_freshnessFraction = SBINET_FRESHNESS_FRACTION_DEFAULT;
  90. time_t SBinetChannel::_freshnessLifetime = (time_t) SBINET_FRESHNESS_LIFETIME_DEFAULT;
  91. time_t SBinetChannel::_maxLifetime = (time_t) SBINET_MAX_LIFETIME_DEFAULT;
  92. VXIint32 SBinetChannel::_pageLoadTimeout = SBINET_PAGE_LOADING_TIMEOUT_DEFAULT;
  93. VXIint32 SBinetChannel::_postContinueTimeout = SBINET_POST_CONTINUE_TIMEOUT_DEFAULT;
  94. SWIList SBinetChannel::_proxyMatcherList;
  95. bool SBinetChannel::_usePersistentConnections = true;
  96. SBinetString *SBinetChannel::_defaultMimeType = NULL;
  97. VXItrdMutex *SBinetChannel::_globalMapMutex = NULL;
  98. VXItrdMutex *SBinetChannel::_globalMD5Mutex = NULL;
  99. static SBINETLOCKMAP _globalLockMap = SBINETLOCKMAP();
  100. static SBINETMD5CACHEMAP _globalMD5CacheMap = SBINETMD5CACHEMAP();
  101. SBinetChannel::SBinetChannel( VXIlogInterface* pVXILog,
  102.       VXIunsigned diagLogBase,
  103.                               VXIcacheInterface *pVXIcache):
  104.   SWIutilLogger(MODULE_SBINET, pVXILog, diagLogBase), _cookieList(),
  105.   _jarChanged(true), _cookiesEnabled(false),
  106.   _connectionCount(0), _pVXILog(pVXILog), _pVXICache(pVXIcache),
  107.   _echoStream(NULL)
  108. {
  109.   Diag (MODULE_SBINET_CHANNEL_TAGID, L"SBinetChannel::SBinetChannel",
  110. L"0x%p", pVXILog);
  111.   // Init interface
  112.   VXIinetInterface::GetVersion = SBinetChannel::GetVersion;
  113.   VXIinetInterface::GetImplementationName =
  114.     SBinetChannel::GetImplementationName;
  115.   VXIinetInterface::Prefetch = staticPrefetch;
  116.   VXIinetInterface::Open = staticOpen;
  117.   VXIinetInterface::Read = staticRead;
  118.   VXIinetInterface::Write = staticWrite;
  119.   VXIinetInterface::Close = staticClose;
  120.   VXIinetInterface::SetCookieJar = staticSetCookieJar;
  121.   VXIinetInterface::GetCookieJar = staticGetCookieJar;
  122.   VXIinetInterface::GetAbsoluteName = staticGetAbsoluteName;
  123.   if ((DiagIsEnabled(MODULE_SBINET_DUMP_HTTP_MSGS)) &&
  124.       (LOG_CONTENT_METHODS_SUPPORTED(_pVXILog)))
  125.   {
  126.     VXIString *logKey = NULL, *logValue = NULL;
  127.     if (_pVXILog->ContentOpen(_pVXILog, MODULE_SBINET, VXI_MIME_TEXT, &logKey,
  128.       &logValue, &_echoStream) ==
  129. VXIlog_RESULT_SUCCESS)
  130.     {
  131.       Diag(MODULE_SBINET_DUMP_HTTP_MSGS, NULL,
  132.    L"Dumping HTTP messages, %s=%s", VXIStringCStr(logKey),
  133.    VXIStringCStr(logValue));
  134.       VXIStringDestroy(&logKey);
  135.       VXIStringDestroy(&logValue);
  136.     }
  137.   }
  138. }
  139. SBinetChannel::~SBinetChannel( )
  140. {
  141.   Diag (MODULE_SBINET_CHANNEL_TAGID, L"SBinetChannel::~SBinetChannel", NULL);
  142.   closeHttpConnections();
  143.   closeAllStreams();
  144.   deleteAllCookies();
  145.   if (_echoStream)
  146.   {
  147.     _pVXILog->ContentClose(_pVXILog, &_echoStream);
  148.   }
  149.   // NOP //    // NOP //    // NOP //
  150. }
  151. /*
  152.  * Prefetch: For now punt, eventually spawn thread to call Open() into /dev/null
  153.  */
  154. VXIinetResult
  155. SBinetChannel::prefetch(const VXIchar*  pszModuleName,
  156.                         const VXIchar*  pszName,
  157.                         VXIinetOpenMode eMode,
  158.                         VXIint32        nFlags,
  159.                         const VXIMap*   pProperties )
  160. {
  161. #if 0 // NOT YET IMPLEMENTED
  162.   /*
  163.    * Add prefetch request to prefetch queue. These requests are
  164.    * processed when the fetch engine is idle, and the fetched
  165.    * documents are stored in the Inet cache until retrieved by
  166.    * a subsequent Open call. Note that in order for prefetching
  167.    * to work, caching must be enabled, the fetched document must
  168.    * be cachable (server must not return a 'no-cache' directive)
  169.    * and the caching mode must not be SAFE.
  170.    */
  171.   Diag( MODULE_SBINET_CHANNEL_TAGID, L"SBinetChannel::Prefetch",
  172.     L"(%s)", pszName );
  173. #endif
  174.   return VXIinet_RESULT_SUCCESS;
  175. }
  176. VXIinetResult
  177. SBinetChannel::closeAllStreams()
  178. {
  179.   // should interate over open stream and close gracefully
  180.   // closeHttpConnections() already remove all open streams
  181.   return(VXIinet_RESULT_SUCCESS);
  182. }
  183. static VXIinetResult parseURL(const VXIchar *pszName,
  184.                               const VXIMap *properties,
  185.                               SWIutilLogger *logger,
  186.                               SBinetURL *& url)
  187. {
  188.   const VXIchar *pszUrlBase = SBinetUtils::getString(properties,
  189.                                                      INET_URL_BASE);
  190.   VXIinetResult rc = SBinetURL::create(pszName,pszUrlBase,url);
  191.   if (rc == VXIinet_RESULT_OUT_OF_MEMORY)
  192.   {
  193.     logger->Error(103, NULL);
  194.   }
  195.   else if (rc != VXIinet_RESULT_SUCCESS)
  196.   {
  197.     logger->Error(200, L"%s%s%s%s", L"Operation", L"Open",
  198.                   L"URL", (pszName != NULL) ? pszName : L"NULL");
  199.   }
  200.   return rc;
  201. }
  202. VXIinetStream* SBinetChannel::createHttpStream(SBinetURL *url,
  203.                                                const VXIMap *properties)
  204. {
  205.   SBinetHttpStream::SubmitMethod method = SBinetHttpStream::GET_METHOD;
  206.   const VXIchar *methodStr = SBinetUtils::getString(properties,
  207.                                                     INET_SUBMIT_METHOD);
  208.   if (methodStr == NULL)
  209.     methodStr = INET_SUBMIT_METHOD_DEFAULT;
  210.   if (!::wcscmp(methodStr, INET_SUBMIT_METHOD_POST))
  211.     method = SBinetHttpStream::POST_METHOD;
  212.   SBinetStoppableStream *stream = NULL;
  213.   if (method == SBinetHttpStream::GET_METHOD)
  214.   {
  215.     // Get method, append the query arguments to the URL and create a cache
  216.     // stream.
  217.     const VXIMap *queryArgs =
  218.       (const VXIMap *)VXIMapGetProperty(properties, INET_URL_QUERY_ARGS);
  219.     url->appendQueryArgsToURL(queryArgs);
  220.     stream = new SBinetHttpCacheStream(url, method, this, getCache(),
  221.                                        GetLog(), GetDiagBase());
  222.   }
  223.   else
  224.   {
  225.     // No caching for POST operations.
  226.     stream = new SBinetHttpStream(url, method, this, NULL, GetLog(), GetDiagBase());
  227.   }
  228.   if (stream != NULL)
  229.     return new SBinetTimedStream(stream, GetLog(), GetDiagBase());
  230.   else
  231.     return NULL;
  232. }
  233. VXIinetResult SBinetChannel::createStream(SBinetURL *url,
  234.                                           const VXIMap *properties,
  235.                                           VXIinetStream* &stream)
  236. {
  237.   /*
  238.    * Note: Stream now owns url and must delete on cleanup
  239.    */
  240.   switch (url->getProtocol())
  241.   {
  242.    case SBinetURL::HTTP_PROTOCOL:
  243.    case SBinetURL::HTTPS_PROTOCOL:
  244.      stream = createHttpStream(url, properties);
  245.      break;
  246.    case SBinetURL::FILE_PROTOCOL:
  247.      stream = new SBinetFileStream(url, this, GetLog(), GetDiagBase());
  248.      break;
  249.    default:
  250.      // Can't really happen.
  251.      stream = NULL;
  252.      break;
  253.   }
  254.   if (!stream)
  255.   {
  256.     Error(103, NULL);
  257.     delete url;
  258.     return VXIinet_RESULT_OUT_OF_MEMORY;
  259.   }
  260.   return VXIinet_RESULT_SUCCESS;
  261. }
  262. /*
  263.  * Open: Serious work here.
  264.  *   Parse URL and combine with base
  265.  *   Collect properties and query args
  266.  *   Call appropriate Stream constructor base on URL scheme (http or file)
  267.  *   Call Open() on stream
  268.  */
  269. VXIinetResult
  270. SBinetChannel::open(const VXIchar*   pszModuleName,
  271.     const  VXIchar*  pszName,
  272.                     VXIinetOpenMode  eMode,
  273.                     VXIint32         nFlags,
  274.                     const VXIMap*    pProperties,
  275.                     VXIMap*          pmapStreamInfo,
  276.                     VXIinetStream**  ppStream)
  277. {
  278.   if (eMode != INET_MODE_READ)
  279.     return(VXIinet_RESULT_UNSUPPORTED);
  280.   if(!ppStream)
  281.   {
  282.     Error(200, L"%s%s%s%s", L"Operation", L"Open",
  283.           L"URL", (pszName != NULL) ? pszName : L"NULL");
  284.     return(VXIinet_RESULT_INVALID_ARGUMENT);
  285.   }
  286.   Diag (MODULE_SBINET_CHANNEL_TAGID, L"SBinetChannel::Open",
  287. L"(%s)", pszName != NULL ? pszName : L"NULL");
  288.   SBinetURL *url;
  289.   VXIinetResult rc = ::parseURL(pszName, pProperties, this, url);
  290.   if (rc != VXIinet_RESULT_SUCCESS)
  291.     return rc;
  292.   rc = createStream(url, pProperties, *ppStream);
  293.   if (rc != VXIinet_RESULT_SUCCESS)
  294.     return rc;
  295.   rc = (*ppStream)->Open(nFlags, pProperties, pmapStreamInfo);
  296.   switch (rc)
  297.   {
  298.    case VXIinet_RESULT_SUCCESS:
  299.    case VXIinet_RESULT_NOT_MODIFIED:
  300.      return rc;
  301.      break;
  302.    case VXIinet_RESULT_LOCAL_FILE:
  303.      // no logging to perform.
  304.      break;
  305.    case VXIinet_RESULT_FETCH_TIMEOUT:
  306.      Error(228, L"%s%s", L"URL", url->getAbsolute());
  307.      // no break: intentional
  308.    default:
  309.      Error(204, L"%s%s%s%d",
  310.            L"URL", url->getAbsolute(),
  311.            L"rc",rc);
  312.      break;
  313.   }
  314.   delete (*ppStream);
  315.   *ppStream = NULL;
  316.   return rc;
  317. }
  318. VXIinetResult
  319. SBinetChannel::close(VXIinetStream**  ppStream)
  320. {
  321.   if (ppStream == NULL)
  322.   {
  323.     Error(200, L"%s%s", L"Operation", L"Close");
  324.     return(VXIinet_RESULT_INVALID_ARGUMENT);
  325.   }
  326.   VXIinetStream* st = *ppStream;
  327.   VXIinetResult err;
  328.   if(st != NULL)
  329.   {
  330.     err = st->Close();
  331.     delete st;
  332.     st = NULL;
  333.   }
  334.   else
  335.   {
  336.     Error(200, L"%s%s", L"Operation", L"Close");
  337.     err = VXIinet_RESULT_INVALID_ARGUMENT;
  338.   }
  339.   *ppStream = NULL;
  340.   return(err);
  341. }
  342. VXIinetResult SBinetChannel::setCookieJar( const VXIVector* pJar )
  343. {
  344.   deleteAllCookies();
  345.   if (pJar == NULL)
  346.   {
  347.     // NULL jar means 'disable cookie usage'
  348.     _jarChanged = false;
  349.     _cookiesEnabled = false;
  350.     return VXIinet_RESULT_SUCCESS;
  351.   }
  352.   _cookiesEnabled = true; // Enable cookie usage
  353.   VXIunsigned numElements = VXIVectorLength(pJar);
  354.   for (VXIunsigned i = 0; i < numElements; i++)
  355.   {
  356.     const VXIMap *cookie_map = (const VXIMap *) VXIVectorGetElement(pJar, i);
  357.     if (cookie_map == NULL)
  358.     {
  359.       Error (212, NULL);
  360.       continue;
  361.     }
  362.     if (VXIValueGetType((const VXIValue *) cookie_map) != VALUE_MAP)
  363.     {
  364.       Error (213, L"%s%d", L"VXIValueType",
  365.              VXIValueGetType((const VXIValue *) cookie_map));
  366.       continue;
  367.     }
  368.     VXIint32 tempInt = 0;
  369.     SBinetUtils::getInteger(cookie_map, INET_COOKIE_EXPIRES, tempInt);
  370.     time_t expires = (time_t) tempInt;
  371.     // Check if the cookie is expired, if so don't add it, zero
  372.     // expiration time means the cookie is not persistent and should not be added.
  373.     // For now, add a cookie whose expiration time is 0.
  374.     if(expires != 0 && expires < time(0))
  375.       continue;
  376.     // Get the name
  377.     const VXIchar *tempStr = SBinetUtils::getString(cookie_map, INET_COOKIE_NAME);
  378.     if (tempStr == NULL)
  379.     {
  380.       Error(106, NULL);
  381.       continue;
  382.     }
  383.     // convert to narrow string.
  384.     SBinetNString name = tempStr;
  385.     // Get the domain
  386.     tempStr = SBinetUtils::getString(cookie_map, INET_COOKIE_DOMAIN);
  387.     SBinetNString domain;
  388.     if(tempStr != NULL)
  389.     {
  390.       domain = tempStr;
  391.     }
  392.     // Get the path
  393.     tempStr = SBinetUtils::getString(cookie_map, INET_COOKIE_PATH);
  394.     SBinetNString path;
  395.     if(tempStr != NULL)
  396.     {
  397.       path = tempStr;
  398.     }
  399.     // Get the secure flag
  400.     bool secure = SBinetUtils::getInteger(cookie_map, INET_COOKIE_SECURE, tempInt) && tempInt;
  401.     // AC: Why would it be an error to have a cookie withouth the secure attribute?
  402.     //        if(tempInt == NULL)
  403.     //        {
  404.     //          Error(200, NULL);
  405.     //          continue;
  406.     //        }
  407.     // Get the value
  408.     tempStr = SBinetUtils::getString(cookie_map,INET_COOKIE_VALUE);
  409.     SBinetNString value;
  410.     if(tempStr != NULL)
  411.     {
  412.       value = tempStr;
  413.     }
  414.     // Create the cookie
  415.     SBinetCookie* pSBinetCookie = new SBinetCookie(domain.c_str(), path.c_str(), name.c_str(),
  416.                                                    value.c_str(), expires, secure);
  417.     // Add the cookie to the channel's list
  418.     if (pSBinetCookie  && !addCookie(pSBinetCookie))
  419.       delete pSBinetCookie; // Could not add
  420.   }
  421.   _jarChanged = false;
  422.   return VXIinet_RESULT_SUCCESS;
  423. }
  424. VXIinetResult SBinetChannel::getCookieJar( VXIVector** ppJar,
  425.                                            VXIbool* ppfChanged )
  426. {
  427.   time_t now = time(NULL);
  428.   if (ppJar == NULL)
  429.   {
  430.     Error(200, L"%s%s", L"Operation", L"GetCookieJar");
  431.     return VXIinet_RESULT_INVALID_ARGUMENT;
  432.   }
  433.   *ppJar = VXIVectorCreate();
  434.   if(*ppJar == NULL)
  435.   {
  436.     Error(103, NULL);
  437.     return VXIinet_RESULT_OUT_OF_MEMORY;
  438.   }
  439.   // Parse the channel's cookie list
  440.   SWIList::Iterator iter(_cookieList);
  441.   while (iter.hasNext())
  442.   {
  443.     SBinetCookie *cookie = (SBinetCookie *) iter.next();
  444.     // Get session specific cookies as well as cookies that haven't
  445.     // expired.
  446.     if (cookie->getExpires() != 0 && cookie->getExpires() < now )
  447.       continue;
  448.     VXIMap *cookie_map = VXIMapCreate();
  449.     if(cookie_map == NULL)
  450.     {
  451.       VXIVectorDestroy(ppJar);
  452.       Error(103, NULL);
  453.       return VXIinet_RESULT_OUT_OF_MEMORY;
  454.     }
  455.     // Set the domain
  456.     SBinetString tmpStr = cookie->getDomain();
  457.     VXIMapSetProperty(cookie_map, INET_COOKIE_DOMAIN,
  458.                       (VXIValue *)VXIStringCreate(tmpStr.c_str()));
  459.     // Set the path
  460.     tmpStr = cookie->getPath();
  461.     VXIMapSetProperty(cookie_map, INET_COOKIE_PATH,
  462.                       (VXIValue *)VXIStringCreate(tmpStr.c_str()));
  463.     // Set the expiration date
  464.     VXIMapSetProperty(cookie_map, INET_COOKIE_EXPIRES,
  465.                       (VXIValue *)VXIIntegerCreate(cookie->getExpires()));
  466.     // Set the secure flag
  467.     VXIMapSetProperty(cookie_map, INET_COOKIE_SECURE,
  468.                       (VXIValue *)VXIIntegerCreate(cookie->getSecure()));
  469.     // Set the value
  470.     tmpStr = cookie->getValue();
  471.     VXIMapSetProperty(cookie_map, INET_COOKIE_VALUE,
  472.                       (VXIValue *)VXIStringCreate(tmpStr.c_str()));
  473.     // Set the name
  474.     tmpStr = cookie->getName();
  475.     VXIMapSetProperty(cookie_map, INET_COOKIE_NAME,
  476.       (VXIValue *)VXIStringCreate(tmpStr.c_str()));
  477.     // Set the version, TBD currently a hack, should get the version
  478.     // from the incoming cookie
  479.     VXIMapSetProperty(cookie_map, INET_COOKIE_VERSION,
  480.       (VXIValue *)VXIIntegerCreate(1));
  481.     // Add the cookie to the jar
  482.     VXIVectorAddElement(*ppJar, (VXIValue *)cookie_map);
  483.   }
  484.   if (ppfChanged != NULL)
  485.   {
  486.     *ppfChanged = _jarChanged;
  487.   }
  488.   return VXIinet_RESULT_SUCCESS;
  489. }
  490. void
  491. SBinetChannel::deleteAllCookies()
  492. {
  493.   SBinetCookie *cookie;
  494.   while ((cookie = (SBinetCookie *) _cookieList.removeFirst()) != NULL)
  495.   {
  496.     delete cookie;
  497.   }
  498.   _jarChanged = true;
  499. }
  500. bool SBinetChannel::updateCookie(SBinetCookie *newCookie)
  501. {
  502.   if (newCookie == NULL)
  503.     return true;
  504.   time_t now = time(NULL);
  505.   SWIList::Iterator iter(_cookieList);
  506.   while (iter.hasNext())
  507.   {
  508.     SBinetCookie *cookie = (SBinetCookie *) iter.next();
  509.     if (cookie->matchExact(newCookie))
  510.     {
  511.       // If the newCookie is expired, we actually remove both cookies
  512.       // from the jar.
  513.       time_t expires = newCookie->getExpires();
  514.       if (expires != (time_t) 0 && expires < now)
  515.       {
  516.         delete newCookie;
  517.         iter.removeBack();
  518.       }
  519.       else
  520.         iter.set(newCookie);
  521.       _jarChanged = true;
  522.       delete cookie;
  523.       return true;
  524.     }
  525.   }
  526.   // If we get here, it means the cookie was not already in the list.
  527.   // Just add it.
  528.   return addCookie(newCookie);
  529. }
  530. VXIint SBinetChannel::cleanCookies()
  531. {
  532.   VXIint deleted = 0;
  533.   time_t now = time(NULL);
  534.   // Delete expired cookies first
  535.   SWIList::Iterator iter(_cookieList);
  536.   while (iter.hasNext())
  537.   {
  538.     SBinetCookie *cookie = (SBinetCookie *) iter.next();
  539.     // remove expired cookie.
  540.     time_t expires = cookie->getExpires();
  541.     if (expires != (time_t) 0 && expires < now)
  542.     {
  543.       iter.removeBack();
  544.       delete cookie;
  545.       deleted++;
  546.       _jarChanged = true;
  547.     }
  548.   }
  549.   if (deleted > 0) return deleted;
  550.   // No cookies were expired, so delete the least recently used
  551.   time_t oldestDate = 0;
  552.   // Find the oldest timestamp
  553.   iter.setPos(SWIList::Iterator::BEG);
  554.   while (iter.hasNext())
  555.   {
  556.     SBinetCookie *cookie = (SBinetCookie *) iter.next();
  557.     if (oldestDate == 0 || cookie->getTimeStamp() < oldestDate)
  558.       oldestDate = cookie->getTimeStamp();
  559.   }
  560.   // Now delete all 'old' cookies
  561.   iter.setPos(SWIList::Iterator::BEG);
  562.   while (iter.hasNext())
  563.   {
  564.     SBinetCookie *cookie = (SBinetCookie *) iter.next();
  565.     if (cookie->getTimeStamp() == oldestDate)
  566.     {
  567.       iter.removeBack();
  568.       delete cookie;
  569.       deleted++;
  570.       _jarChanged = true;
  571.     }
  572.   }
  573.   return deleted;
  574. }
  575. // Minimum from Cookie spec is 300
  576. #define MAX_COOKIES 500
  577. bool SBinetChannel::addCookie(SBinetCookie* cookie)
  578. {
  579.   if (cookie != NULL)
  580.   {
  581.     if (_cookieList.size() < MAX_COOKIES)
  582.     {
  583.       _cookieList.addLast(cookie);
  584.       _jarChanged = true;
  585.     }
  586.     else
  587.     {
  588.       cleanCookies(); // Delete old cookies
  589.       if (_cookieList.size() >= MAX_COOKIES)
  590.       {
  591.         Error(210, NULL);
  592.         return false;
  593.       }
  594.       else
  595.       {
  596.         _cookieList.addLast(cookie);
  597.         _jarChanged = true;
  598.       }
  599.     }
  600.   }
  601.   return true;
  602. }
  603. void SBinetChannel::collectCookies(SWIoutputStream* output,
  604.                                    const char *domain,
  605.                                    const char *path)
  606. {
  607.   time_t now = time(NULL);
  608.   SWIList::Iterator iter(_cookieList);
  609.   while (iter.hasNext())
  610.   {
  611.     SBinetCookie *cookie = (SBinetCookie *) iter.next();
  612.     time_t expires = cookie->getExpires();
  613.     if ((expires == (time_t) 0 || expires >= now) &&
  614.         cookie->matchRequest(domain, path, this))
  615.     {
  616.       writeString(output, "Cookie: ");
  617.       writeString(output, "$Version=1; ");
  618.       writeString(output, cookie->getName());
  619.       writeString(output, "=");
  620.       writeString(output, cookie->getValue());
  621.       //writeString(output, """);
  622.       const char *tmp = cookie->getPath();
  623.       if (tmp && *tmp)
  624.       {
  625.         writeString(output, "; $Path=");
  626.         writeString(output, tmp);
  627.         //writeString(output, """);
  628.       }
  629.       tmp = cookie->getDomain();
  630.       if (tmp && *tmp)
  631.       {
  632.         writeString(output, "; $Domain=");
  633.         writeString(output, tmp);
  634.         //writeString(output, """);
  635.       }
  636.       writeString(output, "rn");
  637.       cookie->updateTimeStamp();
  638.     }
  639.   }
  640. }
  641. /*
  642.  * GetAbsoluteName
  643.  */
  644. typedef std::basic_string<VXIchar> vxistring;
  645. static VXIinetResult getAbsUri
  646. (
  647.   const VXIchar*   pszName,
  648.   const VXIMap*    pProperties,
  649.   vxistring & finalUri
  650. )
  651. {
  652.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  653.   const VXIValue * val = NULL; 
  654.   
  655.   if( pszName && !pProperties ) {
  656.     // Just return the name since there is no additional
  657.     // information to calculate absolute uri
  658.     finalUri = pszName;
  659.     return VXIinet_RESULT_SUCCESS;
  660.   }
  661.   else {
  662.     if( pProperties ) 
  663.     {
  664.       val = VXIMapGetProperty(pProperties, INET_INFO_ABSOLUTE_NAME);
  665.       // If the absolute URI does not exist, retrieve the base url
  666.       if( !val && (!pszName || *pszName == L'') )
  667.         return VXIinet_RESULT_FAILURE;
  668.       if( !val )        
  669.         val = VXIMapGetProperty(pProperties, INET_URL_BASE);
  670.     }
  671.   
  672.     if( (!pszName || *pszName == L'') && val ) 
  673.     {
  674.       // The user wants to get the existing absolute URI
  675.       // None of the information is available to get absolute url
  676.       if( !val || VXIValueGetType(val) != VALUE_STRING)
  677.         return VXIinet_RESULT_FAILURE;
  678.       // We got one
  679.       const VXIchar * uri = VXIStringCStr((const VXIString*)val);
  680.       // Bad uri
  681.       if( !uri || *uri == L'' ) 
  682.         return VXIinet_RESULT_FAILURE;
  683.               
  684.       // remove query args if exists
  685.       vxistring uristr = uri;
  686.       vxistring::size_type pos = uristr.find(L"?");
  687.       if( pos != vxistring::npos )
  688.         uristr.erase(pos);  
  689.       finalUri = uristr;
  690.       return VXIinet_RESULT_SUCCESS;
  691.     }
  692.   }  
  693.   
  694.   // Otherwise retrieve base url to combine with relative url
  695.   const VXIchar* baseUri = NULL;
  696.   SBinetURL * url = NULL;
  697.   if( val && VXIValueGetType(val) == VALUE_STRING )
  698.     baseUri = VXIStringCStr((const VXIString*)val);
  699.     
  700.   rc = SBinetURL::create(pszName, baseUri, url);  
  701.   if( rc == VXIinet_RESULT_SUCCESS )
  702.     finalUri = url->getAbsolute();
  703.   if( url ) delete url;    
  704.   return rc;  
  705. }
  706. VXIinetResult SBinetChannel::getAbsoluteName
  707. (
  708.   const VXIchar*   pszModuleName,
  709. const VXIchar*   pszName,
  710.   const VXIMap*    pProperties,
  711.   VXIString**      absoluteName
  712. )
  713. {
  714.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  715.   
  716.   if(!absoluteName || ((!pszName || *pszName == L'') && !pProperties))
  717.   {
  718.     Error(200, L"%s%s%s%s", L"Operation", L"Open",
  719.           L"URL", (pszName != NULL) ? pszName : L"NULL");
  720.     return(VXIinet_RESULT_INVALID_ARGUMENT);
  721.   }
  722.   Diag (MODULE_SBINET_CHANNEL_TAGID, L"SBinetChannel::GetAbsoluteName",
  723. L"(%s)", pszName != NULL ? pszName : L"NULL");
  724.   vxistring finalUrl;
  725.   *absoluteName = NULL;
  726.   
  727.   rc = getAbsUri(pszName, pProperties, finalUrl);
  728.   if( rc == VXIinet_RESULT_SUCCESS ) {
  729.     // Remove file:// part if it is local file
  730.     vxistring::size_type pos = finalUrl.find(L"file://");
  731.     if( pos != vxistring::npos )
  732.       finalUrl.erase(0, strlen("file://"));  
  733.     *absoluteName = VXIStringCreate(finalUrl.c_str());         
  734.   }
  735.   return rc;
  736. }
  737. SWIstream::Result SBinetChannel::writeString(SWIoutputStream* output, const char *data)
  738. {
  739.   SWIstream::Result rc = output->printString(data);
  740.   if (rc == SWIstream::CONNECTION_ABORTED)
  741.     throw std::runtime_error("CONNECTION_ABORTED");
  742.   else if (rc == SWIstream::WRITE_ERROR)
  743.     throw std::runtime_error("SOCKET_ERROR");
  744.   if (_echoStream)
  745.   {
  746.     echoStreamWrite(data, strlen(data));
  747.   }
  748.   return rc;
  749. }
  750. SWIstream::Result SBinetChannel::writeInt(SWIoutputStream* output, int value)
  751. {
  752.   SWIstream::Result rc = output->printInt(value);
  753.   if (rc == SWIstream::CONNECTION_ABORTED)
  754.     throw std::runtime_error("CONNECTION_ABORTED");
  755.   else if (rc == SWIstream::WRITE_ERROR)
  756.     throw std::runtime_error("SOCKET_ERROR");
  757.     
  758.   if (_echoStream)
  759.   {
  760.     char valStr[20];
  761.     sprintf(valStr, "%d", value);
  762.     echoStreamWrite(valStr, strlen(valStr));
  763.   }
  764.   return rc;
  765. }
  766. int SBinetChannel::writeData(SWIoutputStream* output,
  767.                              const void *data, int dataSize)
  768. {
  769.   int rc = output->writeBytes(data, dataSize);
  770.   if (rc == SWIstream::CONNECTION_ABORTED)
  771.     throw std::runtime_error("CONNECTION_ABORTED");
  772.   else if (rc == SWIstream::WRITE_ERROR)
  773.     throw std::runtime_error("SOCKET_ERROR");
  774.   if (_echoStream)
  775.   {
  776.     echoStreamWrite(data, rc);
  777.   }
  778.   return rc;
  779. }
  780. // Strictly for writing debug info to the log
  781. void SBinetChannel::writeDebugString(const char *data)
  782. {
  783.   if (_echoStream)
  784.   {
  785.     echoStreamWrite(data, strlen(data));
  786.   }
  787. }
  788. int SBinetChannel::readChar(SWIinputStream* input)
  789. {
  790.   int k = input->read();
  791.   if (k >= 0)
  792.   {
  793.     char c = (char) k;
  794.     if (_echoStream) echoStreamWrite(&c, 1);
  795.   }
  796.   return k;
  797. }
  798. SWIstream::Result SBinetChannel::readLine(SWIinputStream* input, SWIdataOutputStream* line)
  799. {
  800.   line->reset();
  801.   int rc = input->readLine(*line);
  802.   if (rc < 0) return SWIstream::Result(rc);
  803.   if (_echoStream)
  804.   {
  805.     echoStreamWrite(line->getString(), line->getSize());
  806.     echoStreamWrite("rn", 2);
  807.   }
  808.   return SWIstream::SUCCESS;
  809. }
  810. int SBinetChannel::readData(SWIinputStream* input, void *buffer, int toRead)
  811. {
  812.   int rc = input->readBytes(buffer, toRead);
  813.   if (rc >= 0 && _echoStream)
  814.     echoStreamWrite(buffer, rc);
  815.   return rc;
  816. }
  817. /*
  818.  * Call Channel method
  819.  */
  820. VXIint32 SBinetChannel::GetVersion()
  821. {
  822.   return VXI_CURRENT_VERSION;
  823. }
  824. const VXIchar* SBinetChannel::GetImplementationName()
  825. {
  826.   return SBINET_IMPLEMENTATION_NAME;
  827. }
  828. VXIinetResult
  829. SBinetChannel::staticPrefetch(/* [IN]  */ VXIinetInterface*      pThis,
  830.                               /* [IN]  */ const VXIchar*   pszModuleName,
  831.                               /* [IN]  */ const VXIchar*   pszName,
  832.                               /* [IN]  */ VXIinetOpenMode  eMode,
  833.                               /* [IN]  */ VXIint32         nFlags,
  834.                               /* [IN]  */ const VXIMap*    pProperties  )
  835. {
  836.   SBinetChannel* chan = static_cast<SBinetChannel *>(pThis);
  837.   if (!chan)
  838.   {
  839.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  840.   }
  841.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  842.   SBinetLogFunc apiTrace (chan->GetLog(), chan->GetDiagBase() +
  843.   MODULE_SBINET_API_TAGID,
  844.   L"SBinetChannel::Prefetch", (int *) &rc,
  845.   L"entering: 0x%p, %s, %s, 0x%x, 0x%x, 0x%p",
  846.   pThis, pszModuleName, pszName, eMode, nFlags,
  847.   pProperties);
  848.   rc = chan->prefetch(pszModuleName, pszName, eMode, nFlags, pProperties);
  849.   if (rc != VXIinet_RESULT_SUCCESS)
  850.   {
  851.     chan->Error(203,L"%s%d",L"rc",rc);
  852.   }
  853.   return (rc);
  854. }
  855. /*
  856.  * Call Channel method
  857.  */
  858. VXIinetResult
  859. SBinetChannel::staticOpen(/* [IN]  */ VXIinetInterface*      pThis,
  860.                           /* [IN]  */ const VXIchar*   pszModuleName,
  861.                           /* [IN]  */ const  VXIchar*  pszName,
  862.                           /* [IN]  */ VXIinetOpenMode  eMode,
  863.                           /* [IN]  */ VXIint32         nFlags,
  864.                           /* [IN]  */ const VXIMap*    pProperties,
  865.                           /* [OUT] */ VXIMap*          pmapStreamInfo,
  866.                           /* [OUT] */ VXIinetStream**  ppStream     )
  867. {
  868.   SBinetChannel* chan = static_cast<SBinetChannel *>(pThis);
  869.   if (!chan)
  870.   {
  871.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  872.   }
  873.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  874.   SBinetLogFunc apiTrace (chan->GetLog(), chan->GetDiagBase() +
  875.   MODULE_SBINET_API_TAGID,
  876.   L"SBinetChannel::Open", (int *) &rc,
  877.   L"entering: 0x%p, %s, %s, 0x%x, 0x%x, 0x%p, 0x%p, 0x%p",
  878.   pThis, pszModuleName, pszName, eMode, nFlags,
  879.   pProperties, pmapStreamInfo, ppStream);
  880.   rc = chan->open(pszModuleName, pszName, eMode, nFlags,
  881.                   pProperties, pmapStreamInfo, ppStream);
  882.   return rc;
  883. }
  884. /*
  885.  * We must call channel method so we can GC the stream
  886.  */
  887. VXIinetResult
  888. SBinetChannel::staticClose(/* [IN]  */ VXIinetInterface* pThis,
  889.                            /* [IN]  */ VXIinetStream** ppStream     )
  890. {
  891.   SBinetChannel* chan = static_cast<SBinetChannel*>(pThis);
  892.   if (!chan)
  893.   {
  894.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  895.   }
  896.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  897.   SBinetLogFunc apiTrace (chan->GetLog(), chan->GetDiagBase() +
  898.   MODULE_SBINET_API_TAGID,
  899.   L"SBinetChannel::Close", (int *) &rc,
  900.   L"entering: 0x%p, 0x%p (0x%p)", pThis, ppStream,
  901.   (ppStream ? *ppStream : NULL));
  902.   rc = chan->close(ppStream);
  903.   if (rc != VXIinet_RESULT_SUCCESS)
  904.   {
  905.     chan->Error(205,L"%s%d",L"rc",rc);
  906.   }
  907.   return (rc);
  908. }
  909. /*
  910.  * Actually, we are simply going to go and call Stream routine directly here
  911.  */
  912. VXIinetResult
  913. SBinetChannel::staticRead(/* [IN]  */ VXIinetInterface*      pThis,
  914.                           /* [OUT] */ VXIbyte*         pBuffer,
  915.                           /* [IN]  */ VXIulong         nBuflen,
  916.                           /* [OUT] */ VXIulong*        pnRead,
  917.                           /* [IN]  */ VXIinetStream*   pStream      )
  918. {
  919.   SBinetChannel* chan = static_cast<SBinetChannel*>(pThis);
  920.   if (!chan || VXIlong(nBuflen) < 0 || !pBuffer)
  921.   {
  922.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  923.   }
  924.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  925.   SBinetLogFunc apiTrace (chan->GetLog(), chan->GetDiagBase() +
  926.   MODULE_SBINET_API_TAGID,
  927.   L"SBinetChannel::Read", (int *) &rc,
  928.   L"entering: 0x%p, 0x%p, %lu, %lu, 0x%p",
  929.   pThis, pBuffer, nBuflen, pnRead, pStream);
  930.   if (pStream == NULL)
  931.   {
  932.     chan->Error(200, L"%s%s", L"Operation", L"Read");
  933.     return (rc = VXIinet_RESULT_INVALID_ARGUMENT);
  934.   }
  935.   rc = (pStream->Read)(pBuffer,nBuflen, pnRead);
  936.   switch (rc)
  937.   {
  938.    case VXIinet_RESULT_SUCCESS:
  939.    case VXIinet_RESULT_WOULD_BLOCK:
  940.    case VXIinet_RESULT_END_OF_STREAM:
  941.      // no logging to perform.
  942.      break;
  943.    case VXIinet_RESULT_FETCH_TIMEOUT:
  944.      chan->Error(228, NULL);
  945.      // no break: intentional
  946.    default:
  947.      chan->Error(206, L"%s%d", L"rc", rc);
  948.      break;
  949.   }
  950.   return (rc);
  951. }
  952. VXIinetResult
  953. SBinetChannel::staticWrite(/* [IN]  */ VXIinetInterface*      pThis,
  954.                            /* [OUT] */ const VXIbyte*   pBuffer,
  955.                            /* [IN]  */ VXIulong         nBuflen,
  956.                            /* [OUT] */ VXIulong*        pnWritten,
  957.                            /* [IN]  */ VXIinetStream*   pStream      )
  958. {
  959.   SBinetChannel* chan = static_cast<SBinetChannel*>(pThis);
  960.   if (!chan || VXIlong(nBuflen) < 0 || !pBuffer)
  961.   {
  962.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  963.   }
  964.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  965.   SBinetLogFunc apiTrace(chan->GetLog(),
  966.                          chan->GetDiagBase() + MODULE_SBINET_API_TAGID,
  967.                          L"SBinetChannel::Write", (int *) &rc,
  968.                          L"entering: 0x%p, 0x%p, %lu, 0x%p, 0x%p",
  969.                          pThis, pBuffer, nBuflen, pnWritten, pStream);
  970.   if (pStream == NULL)
  971.   {
  972.     chan->Error(200, L"%s%s", L"Operation", L"Write");
  973.     return (rc = VXIinet_RESULT_INVALID_ARGUMENT);
  974.   }
  975.   rc = (pStream->Write)(pBuffer, nBuflen, pnWritten);
  976.   if ((rc != VXIinet_RESULT_SUCCESS) &&
  977.       (rc != VXIinet_RESULT_WOULD_BLOCK))
  978.   {
  979.     chan->Error(207,L"%s%d",L"rc",rc);
  980.   }
  981.   return rc;
  982. }
  983. /*
  984.  * Call Channel method
  985.  */
  986. VXIinetResult
  987. SBinetChannel::staticSetCookieJar( /* [IN]  */ VXIinetInterface*      pThis,
  988.                                    /* [IN]  */ const VXIVector*       pJar )
  989. {
  990.   SBinetChannel* chan = static_cast<SBinetChannel*>(pThis);
  991.   if (!chan)
  992.   {
  993.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  994.   }
  995.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  996.   SBinetLogFunc apiTrace (chan->GetLog(), chan->GetDiagBase() +
  997.   MODULE_SBINET_API_TAGID,
  998.   L"SBinetChannel::SetCookieJar", (int *) &rc,
  999.   L"entering: 0x%p, 0x%p", pThis, pJar);
  1000.   rc = chan->setCookieJar(pJar);
  1001.   if (rc != VXIinet_RESULT_SUCCESS) {
  1002.     chan->Error(208,L"%s%d",L"rc",rc);
  1003.   }
  1004.   return (rc);
  1005. }
  1006. /*
  1007.  * Call Channel method
  1008.  */
  1009. VXIinetResult
  1010. SBinetChannel::staticGetCookieJar( /* [IN]  */ VXIinetInterface*      pThis,
  1011.                                    /* [OUT] */ VXIVector**            ppJar,
  1012.                                    /* [OUT] */ VXIbool*               pfChanged   )
  1013. {
  1014.   SBinetChannel* chan = static_cast<SBinetChannel*>(pThis);
  1015.   if (!chan)
  1016.   {
  1017.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  1018.   }
  1019.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  1020.   SBinetLogFunc apiTrace (chan->GetLog(), chan->GetDiagBase() +
  1021.   MODULE_SBINET_API_TAGID,
  1022.   L"SBinetChannel::GetCookieJar", (int *) &rc,
  1023.   L"entering: 0x%p, 0x%p, 0x%p", pThis, ppJar,
  1024.   pfChanged);
  1025.   rc = chan->getCookieJar(ppJar,pfChanged);
  1026.   if (rc != VXIinet_RESULT_SUCCESS)
  1027.   {
  1028.     chan->Error(209, L"%s%d", L"rc", rc);
  1029.   }
  1030.   return (rc);
  1031. }
  1032. /*
  1033.  * Call Channel method
  1034.  */
  1035. VXIinetResult SBinetChannel::staticGetAbsoluteName
  1036. (
  1037.   /* [IN]  */ VXIinetInterface* pThis,
  1038.   /* [IN]  */ const VXIchar *pszModuleName,
  1039.   /* [IN]  */ const VXIchar *pszName,
  1040.   /* [IN]  */ const VXIMap  *properties,
  1041.   /* [OUT] */ VXIString     **absoluteName
  1042. )  
  1043. {
  1044.   SBinetChannel* chan = static_cast<SBinetChannel *>(pThis);
  1045.   if (!chan)
  1046.   {
  1047.     return (VXIinet_RESULT_INVALID_ARGUMENT);
  1048.   }
  1049.   VXIinetResult rc = VXIinet_RESULT_SUCCESS;
  1050.   SBinetLogFunc apiTrace (chan->GetLog(), chan->GetDiagBase() +
  1051.   MODULE_SBINET_API_TAGID,
  1052.   L"SBinetChannel::GetAbsoluteName", (int *) &rc,
  1053.   L"entering: 0x%p, %s, %s, 0x%x, 0x%x",
  1054.   pThis, pszModuleName, pszName, properties, absoluteName);
  1055.   rc = chan->getAbsoluteName(pszModuleName, pszName, properties, absoluteName);
  1056.   if (rc != VXIinet_RESULT_SUCCESS)
  1057.   {
  1058.     chan->Error(220, L"%s%d", L"rc", rc);
  1059.   }
  1060.   return (rc);
  1061. }
  1062. // Init class at startup
  1063. VXIinetResult SBinetChannel::init(const VXIMap *configParams, const SWIutilLogger *logger)
  1064. {
  1065.   // User agent
  1066.   const VXIchar *userAgent = SBinetUtils::getString(configParams, SBINET_USER_AGENT_NAME);
  1067.   if (!userAgent || !*userAgent)
  1068.   {
  1069.     // Have to parse the user agent name
  1070. #ifdef OPENVXI
  1071.      userAgent = OSBINET_USER_AGENT_NAME_DEFAULT;
  1072. #else
  1073.      userAgent = SBINET_USER_AGENT_NAME_DEFAULT;
  1074. #endif
  1075.   }
  1076.   if (!_userAgent)
  1077.     _userAgent = new SBinetNString(userAgent);
  1078.   else
  1079.     _userAgent->operator=(userAgent);
  1080.   // Proxy rules.
  1081.   const VXIValue * tmp = VXIMapGetProperty(configParams, SBINET_PROXY_RULES);
  1082.   if (tmp != NULL && VXIValueGetType(tmp) == VALUE_VECTOR)
  1083.   {
  1084.     const VXIVector *proxyRules = (const VXIVector *) tmp;
  1085.     VXIunsigned n = VXIVectorLength(proxyRules);
  1086.     for (VXIunsigned i = 0; i < n; i++)
  1087.     {
  1088.       tmp = VXIVectorGetElement(proxyRules, i);
  1089.       if (tmp != NULL && VXIValueGetType(tmp) == VALUE_STRING)
  1090.       {
  1091.         SBinetNString rule = VXIStringCStr((const VXIString *) tmp);
  1092.         SBinetProxyMatcher *p = SBinetProxyMatcher::createMatcher(rule.c_str(), logger);
  1093.         if (p != NULL)
  1094.         {
  1095.           _proxyMatcherList.addLast(p);
  1096.         }
  1097.       }
  1098.     }
  1099.   }
  1100.   
  1101.   // Global Map Mutex
  1102.   if( !_globalMapMutex ) VXItrdMutexCreate(&_globalMapMutex);
  1103.   // Create global MD5 mutex
  1104.   if( !_globalMD5Mutex ) VXItrdMutexCreate(&_globalMD5Mutex);
  1105.   // Extension rules
  1106.   if (! _extensionRulesMutex)
  1107.     VXItrdMutexCreate(&_extensionRulesMutex);
  1108.   if (VXItrdMutexLock(_extensionRulesMutex) == VXItrd_RESULT_SUCCESS)
  1109.   {
  1110.     if (_extensionRules)
  1111.       VXIMapDestroy(&_extensionRules);
  1112.     const VXIValue *tmp = VXIMapGetProperty(configParams, SBINET_EXTENSION_RULES);
  1113.     const VXIMap *extensionRules = NULL;
  1114.     if (tmp != NULL && VXIValueGetType(tmp) == VALUE_MAP)
  1115.       extensionRules = (const VXIMap *) tmp;
  1116.     if (extensionRules)
  1117.       _extensionRules = VXIMapClone(extensionRules);
  1118.     else
  1119.       _extensionRules = NULL;
  1120.     VXItrdMutexUnlock(_extensionRulesMutex);
  1121.   }
  1122.   VXIint32 itmp;
  1123.   // page load time out.
  1124.   itmp = SBINET_PAGE_LOADING_TIMEOUT_DEFAULT;
  1125.   SBinetUtils::getInteger(configParams, SBINET_PAGE_LOADING_TIMEOUT, itmp);
  1126.   setPageLoadTimeout(itmp);
  1127.   // freshness fraction
  1128.   VXIflt32 ftmp = (VXIflt32) SBINET_FRESHNESS_FRACTION_DEFAULT;
  1129.   SBinetUtils::getFloat(configParams, SBINET_FRESHNESS_FRACTION, ftmp);
  1130.   setFreshnessFraction(ftmp);
  1131.   // freshness lifetime
  1132.   itmp = SBINET_FRESHNESS_LIFETIME_DEFAULT;
  1133.   SBinetUtils::getInteger(configParams, SBINET_FRESHNESS_LIFETIME, itmp);
  1134.   setFreshnessLifetime((time_t) itmp);
  1135.   // max lifetime
  1136.   itmp = SBINET_MAX_LIFETIME_DEFAULT;
  1137.   SBinetUtils::getInteger(configParams, SBINET_MAX_LIFETIME, itmp);
  1138.   setMaxLifetime((time_t) itmp);
  1139.   // post continue timeout.
  1140.   itmp = SBINET_POST_CONTINUE_TIMEOUT_DEFAULT;
  1141.   SBinetUtils::getInteger(configParams, SBINET_POST_CONTINUE_TIMEOUT, itmp);
  1142.   setPostContinueTimeout(itmp);
  1143.   const VXIchar* defaultMimeType = SBinetUtils::getString(configParams, SBINET_DEFAULT_MIME_TYPE);
  1144.   if (!defaultMimeType)
  1145.     defaultMimeType = L"application/octet-stream";
  1146.   if (!_defaultMimeType)
  1147.     _defaultMimeType = new SBinetString(defaultMimeType);
  1148.   else
  1149.     _defaultMimeType->operator=(defaultMimeType);
  1150.   itmp = 1;
  1151.   SBinetUtils::getInteger(configParams, SBINET_PERSISTENT_CONNECTIONS, itmp);
  1152.   setUsePersistentConnections(itmp != 0);
  1153.   if (SBinetSSLsocket::initialize() == 0)
  1154.     return VXIinet_RESULT_SUCCESS;
  1155.   else
  1156.     return VXIinet_RESULT_PLATFORM_ERROR;
  1157. }
  1158. // Shutdown class
  1159. void SBinetChannel::shutdown()
  1160. {
  1161.   delete _userAgent;
  1162.   _userAgent = NULL;
  1163.   if (VXItrdMutexLock(_extensionRulesMutex) == VXItrd_RESULT_SUCCESS)
  1164.   {
  1165.     if (_extensionRules)
  1166.       VXIMapDestroy(&_extensionRules);
  1167.     VXItrdMutexUnlock(_extensionRulesMutex);
  1168.     VXItrdMutexDestroy(&_extensionRulesMutex);
  1169.   }
  1170.   // Global Map Mutex
  1171.   if( VXItrdMutexLock(_globalMapMutex ) == VXItrd_RESULT_SUCCESS ) 
  1172.   {
  1173.     // Destroy any left-over lock
  1174.     if( !_globalLockMap.empty() ) {
  1175.       for( SBINETLOCKMAP::iterator i = _globalLockMap.begin();
  1176.            i != _globalLockMap.end(); ++i)
  1177.       {
  1178.         delete ((*i).second);
  1179.       }
  1180.       _globalLockMap.clear();
  1181.     }
  1182.     VXItrdMutexUnlock(_globalMapMutex);
  1183.     VXItrdMutexDestroy(&_globalMapMutex);
  1184.   }
  1185.   // Destroy global MD5 mutex
  1186.   if( _globalMD5Mutex ) VXItrdMutexDestroy(&_globalMD5Mutex);
  1187.   _globalMD5Mutex = NULL;
  1188.   
  1189.   SBinetSSLsocket::shutdown();
  1190. }
  1191. bool SBinetChannel::getCacheExistence(const SBinetMD5 & md5k)
  1192. {
  1193.   bool rc = false;
  1194.   // Gain access to global mutex
  1195.   if( VXItrdMutexLock(_globalMD5Mutex) == VXItrd_RESULT_SUCCESS ) {
  1196.     // Search for this md5
  1197.     SBINETMD5CACHEMAP::iterator i = _globalMD5CacheMap.find(md5k);
  1198.     // If NOT found, the cache is existed
  1199.     // Otherwise the cache is not existed yet
  1200.     if( i == _globalMD5CacheMap.end() )
  1201.       rc = true;
  1202.     
  1203.     VXItrdMutexUnlock(_globalMD5Mutex);
  1204.     // Release global mutex  
  1205.   }
  1206.   return rc;
  1207. }
  1208. bool SBinetChannel::setCacheExistence(const SBinetMD5 & md5k, 
  1209.                                       SBinetHttpCacheStream* p, bool done)
  1210. {
  1211.   bool rc = false;
  1212.   // Gain access to global mutex
  1213.   if( VXItrdMutexLock(_globalMD5Mutex) == VXItrd_RESULT_SUCCESS ) {
  1214.     // The first thread/channel that is going to write the cache
  1215.     // will get hold to this mutex first.  An md5 will be created
  1216.     // for the uri to indicate that its
  1217.     // cache is going to be avail. once this thread/channel fetch successfully
  1218.     // Search for this md5
  1219.     SBINETMD5CACHEMAP::iterator i = _globalMD5CacheMap.find(md5k);
  1220.     
  1221.     if( i == _globalMD5CacheMap.end() ) {
  1222.       // If NOT found, and done == false, meaning this channe/thread
  1223.       // start to write its cache, make it the first to write cache
  1224.       if( !done ) {
  1225.         _globalMD5CacheMap[md5k] = p;
  1226.         rc = true;
  1227.       }
  1228.       else {
  1229.         // This should not happen!!! maybe the function is called incorrectly
  1230.         rc = false;  
  1231.       }
  1232.     }
  1233.     else {
  1234.       // If FOUND, and done == true, this thread/channel finishes writing
  1235.       // cache succesfully.  Remove the previously stored md5 to let other
  1236.       // thread/channel to read directly from its cache
  1237.       if( done && (*i).second == p ) {
  1238.         _globalMD5CacheMap.erase(i);
  1239.         rc = true;
  1240.       }
  1241.       else {
  1242.         // Should never happen!!! maybe race-condition, ignore!
  1243.         rc = false;    
  1244.       }        
  1245.     }
  1246.     
  1247.     VXItrdMutexUnlock(_globalMD5Mutex);
  1248.     // Release global mutex  
  1249.   }  
  1250.   return rc;  
  1251. }
  1252. //VXItrdMutexRef* SBinetChannel::acquireEntryLock(const SBinetMD5 & md5k)
  1253. VXItrdMutexRef* SBinetChannel::acquireEntryLock(const VXIchar* absurl, 
  1254.                                                 SWIutilLogger *logger)
  1255. {
  1256.   const VXIchar* fnname = L"SBinetChannel::acquireEntryLock";
  1257.   VXItrdMutexRef* e_lock = NULL;
  1258.   if( !logger || !absurl || *absurl == L'' ) return NULL;
  1259.   
  1260.   // Generate MD5 key for this absolute url
  1261.   SBinetMD5 md5k(absurl);
  1262.   logger->Diag(MODULE_SBINET_CHANNEL_TAGID, fnname, L"%s%s", 
  1263.                L"Acquiring Lock: ", absurl);
  1264.   
  1265.   // Lock the global map
  1266.   VXItrdMutexLock(_globalMapMutex);
  1267.   // Search the global map for the lock of the given URI
  1268.   SBINETLOCKMAP::iterator i = _globalLockMap.find(md5k);
  1269.   if( i != _globalLockMap.end() )
  1270.   {
  1271.     e_lock = (*i).second;  
  1272.     ++e_lock->_refCount;
  1273.   }
  1274.   else {
  1275.     // If the lock does not exist, create one
  1276.     e_lock = new VXItrdMutexRef();
  1277.     if( e_lock ) {
  1278.       e_lock->_md5Key = md5k; // make a copy of this md5
  1279.       _globalLockMap[md5k] = e_lock;    
  1280.     }
  1281.   }
  1282.   // Unlock 
  1283.   VXItrdMutexUnlock(_globalMapMutex);
  1284.   // If the lock is found, Lock the entry now!
  1285.   if( e_lock ) VXItrdMutexLock(e_lock->_refMutex);
  1286.   logger->Diag(MODULE_SBINET_CHANNEL_TAGID, fnname, L"%s%s%s%p%s%d", 
  1287.                L"Got Lock: ", absurl, L", ", e_lock, L", ref: ", 
  1288.                e_lock->_refCount);
  1289.   return e_lock;
  1290. }
  1291. void SBinetChannel::releaseEntryLock(VXItrdMutexRef* e_lock,
  1292.                                      SWIutilLogger *logger)
  1293. {
  1294.   const VXIchar* fnname = L"SBinetChannel::releaseEntryLock";
  1295.   // Unlock the URL entry to allow other channel to gain access  
  1296.   if( e_lock ) {
  1297.     logger->Diag(MODULE_SBINET_CHANNEL_TAGID, fnname, L"%s%p%s%d", 
  1298.                L"Releasing Lock: ", e_lock, L", ref: ", e_lock->_refCount);              
  1299.     VXItrdMutexUnlock(e_lock->_refMutex);
  1300.     logger->Diag(MODULE_SBINET_CHANNEL_TAGID, fnname, L"%s%p", 
  1301.                L"Lock Released: ", e_lock);              
  1302.     
  1303.     // Lock the global map and remove the mutex ref
  1304.     VXItrdMutexLock(_globalMapMutex);
  1305.     if( --e_lock->_refCount == 0 ) {
  1306.       SBINETLOCKMAP::iterator i = _globalLockMap.find(e_lock->_md5Key);
  1307.       if( i != _globalLockMap.end() ) {
  1308.         _globalLockMap.erase(i);
  1309.       }
  1310.       delete e_lock;
  1311.     }
  1312.     //Unlock
  1313.     VXItrdMutexUnlock(_globalMapMutex);
  1314.   }
  1315. }
  1316. // --------------------------------------------------
  1317. void SBinetChannel::addExtensionRule(const VXIchar* ext,
  1318.      const VXIchar* mimeType)
  1319. {
  1320.   if (! mimeType) return;
  1321.   if (VXItrdMutexLock(_extensionRulesMutex) == VXItrd_RESULT_SUCCESS) {
  1322.     if (! _extensionRules)
  1323.       _extensionRules = VXIMapCreate();
  1324.     if (_extensionRules)
  1325.       VXIMapSetProperty(_extensionRules, ext,
  1326. (VXIValue *) VXIStringCreate(mimeType));
  1327.     VXItrdMutexUnlock(_extensionRulesMutex);
  1328.   }
  1329. }
  1330. const VXIchar *SBinetChannel::mapExtension(const VXIchar* ext)
  1331. {
  1332.   if (ext == NULL) return NULL;
  1333.   const VXIchar *ret = NULL;
  1334.   if (VXItrdMutexLock(_extensionRulesMutex) == VXItrd_RESULT_SUCCESS) {
  1335.     if (_extensionRules)
  1336.       ret = SBinetUtils::getString(_extensionRules, ext);
  1337.     VXItrdMutexUnlock(_extensionRulesMutex);
  1338.   }
  1339.   return ret;
  1340. }
  1341. const char *SBinetChannel::getUserAgent()
  1342. {
  1343.   return _userAgent ? _userAgent->c_str() : "";
  1344. }
  1345. const VXIchar *SBinetChannel::getDefaultMimeType()
  1346. {
  1347.   return _defaultMimeType ? _defaultMimeType->c_str() : L"";
  1348. }
  1349. VXIlogResult SBinetChannel::echoStreamWrite(const void *buffer, size_t buflen)
  1350. {
  1351.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  1352.   VXIulong totWritten = 0;
  1353.   while ((rc == VXIlog_RESULT_SUCCESS) && (totWritten < buflen)) {
  1354.     VXIulong nWritten = 0;
  1355.     rc = _pVXILog->ContentWrite(_pVXILog,
  1356.                                 reinterpret_cast<const VXIbyte *>(buffer) + totWritten,
  1357.                                 buflen - totWritten, &nWritten, _echoStream);
  1358.     totWritten += nWritten;
  1359.   }
  1360.   return rc;
  1361. }
  1362. // void SBinetChannel::eraseCookie(SBinetChannel::CookieList::iterator &vi)
  1363. // {
  1364. // #if defined(__GNUC__) && ((__GNUC__ <= 2) || (__GLIBCPP__ <= 20011023)) || (_decunix_)
  1365. //   // Old STL has erase return void
  1366. //   CookieList::iterator vi2 = vi;
  1367. //   vi2++;
  1368. //   _cookieList.erase (vi);
  1369. //   vi = vi2;
  1370. // #else
  1371. //   // ISO C++ standard has erase return an iterator to the next
  1372. //   // item
  1373. //   vi = _cookieList.erase (vi);
  1374. // #endif
  1375. // }
  1376. void SBinetChannel::setUsePersistentConnections(bool flag)
  1377. {
  1378.   _usePersistentConnections = flag;
  1379. }
  1380. bool SBinetChannel::getUsePersistentConnections()
  1381. {
  1382.   return _usePersistentConnections;
  1383. }
  1384. bool SBinetChannel::setPageLoadTimeout(VXIint32 timeout)
  1385. {
  1386.   if (timeout <= 0)
  1387.     return false;
  1388.   _pageLoadTimeout = timeout;
  1389.   return true;
  1390. }
  1391. VXIint32 SBinetChannel::getPageLoadTimeout()
  1392. {
  1393.   return _pageLoadTimeout;
  1394. }
  1395. bool SBinetChannel::setPostContinueTimeout(VXIint32 timeout)
  1396. {
  1397.   if (timeout <= 0)
  1398.     return false;
  1399.   _postContinueTimeout = timeout;
  1400.   return true;
  1401. }
  1402. VXIint32 SBinetChannel::getPostContinueTimeout()
  1403. {
  1404.   return _postContinueTimeout;
  1405. }
  1406. time_t SBinetChannel::getFreshnessLifetime()
  1407. {
  1408.   return _freshnessLifetime;
  1409. }
  1410. bool SBinetChannel::setFreshnessLifetime(time_t freshnessLifetime)
  1411. {
  1412.   if (freshnessLifetime >= (time_t) 0)
  1413.   {
  1414.     _freshnessLifetime = freshnessLifetime;
  1415.     return true;
  1416.   }
  1417.   return false;
  1418. }
  1419. double SBinetChannel::getFreshnessFraction()
  1420. {
  1421.   return _freshnessFraction;
  1422. }
  1423. bool SBinetChannel::setFreshnessFraction(double freshnessFraction)
  1424. {
  1425.   if (freshnessFraction >= 0.0 && freshnessFraction <= 1.0)
  1426.   {
  1427.     _freshnessFraction = freshnessFraction;
  1428.     return true;
  1429.   }
  1430.   return false;
  1431. }
  1432. time_t SBinetChannel::getMaxLifetime()
  1433. {
  1434.   return _maxLifetime;
  1435. }
  1436. bool SBinetChannel::setMaxLifetime(time_t maxLifetime)
  1437. {
  1438.   if (maxLifetime >= (time_t) 0)
  1439.   {
  1440.     _maxLifetime = maxLifetime;
  1441.     return true;
  1442.   }
  1443.   return false;
  1444. }
  1445. SBinetProxyMatcher *SBinetChannel::getProxyMatcher(const char *domain,
  1446.                                                    const char *path)
  1447. {
  1448.   SWIList::Iterator iter(_proxyMatcherList);
  1449.   while (iter.hasNext())
  1450.   {
  1451.     SBinetProxyMatcher *p = static_cast<SBinetProxyMatcher *>(iter.next());
  1452.     if (p->matches(domain, path))
  1453.     {
  1454.       return p;
  1455.     }
  1456.   }
  1457.   return NULL;
  1458. }
  1459. SBinetHttpConnection *SBinetChannel::getHttpConnection(const SBinetURL *url,
  1460.                                                        const VXIMap *properties)
  1461. {
  1462.   VXIint32 newConnection = !getUsePersistentConnections();
  1463.   const char *hostname = url->getNHost();
  1464.   const char *path = url->getNPath();
  1465.   int port = url->getPort();
  1466.   SBinetUtils::getInteger(properties, INET_NEW_CONNECTION, newConnection);
  1467.   const SBinetProxyMatcher *proxyMatcher = getProxyMatcher(hostname, path);
  1468.   const char *proxyServer = NULL;
  1469.   if (proxyMatcher != NULL)
  1470.     proxyServer = proxyMatcher->getProxyServer();
  1471.   // Ignore empty proxy server.
  1472.   if (proxyServer && !*proxyServer)
  1473.     proxyServer = NULL;
  1474.   bool usesProxy;
  1475.   if (proxyServer)
  1476.   {
  1477.     hostname = proxyServer;
  1478.     port = proxyMatcher->getProxyPort();
  1479.     usesProxy = true;
  1480.   }
  1481.   else
  1482.     usesProxy = false;
  1483.   SWIipAddress remoteAddress(hostname, port, this);
  1484.   // FIXME: This code should be protected by a Mutex once we have the cleaning
  1485.   // thread
  1486.   SBinetHttpConnection *conn = (SBinetHttpConnection *) _connectionMap.remove(remoteAddress);
  1487.   if (newConnection && conn)
  1488.   {
  1489.     delete conn;
  1490.     conn = NULL;
  1491.   }
  1492.   // FIXME: End of code section that should be protected.
  1493.   if (!conn)
  1494.   {
  1495.     char buf[10];
  1496.     sprintf(buf, "%d", _connectionCount++);
  1497.     conn = new SBinetHttpConnection(url->getProtocol(), remoteAddress,
  1498.                                     usesProxy, this, buf);
  1499.   }
  1500.   return conn;
  1501. }
  1502. void SBinetChannel::putHttpConnection(SBinetHttpConnection *connection)
  1503. {
  1504.   // Ideally, we should check whether we own the connection.
  1505.   // FIXME: This code should be protected by a Mutex once we have the cleaning  thread
  1506.   const SWIipAddress *addr = connection->getRemoteAddress();
  1507.   SBinetHttpConnection *oldconn = (SBinetHttpConnection *)
  1508.     _connectionMap.putValue(*addr, connection);
  1509.   // FIXME: End of code section that should be protected.
  1510.   delete oldconn;
  1511. }
  1512. void SBinetChannel::closeHttpConnections()
  1513. {
  1514.   // Iterate saved connections and dispose of them all
  1515.   SWIHashMap::Iterator it(_connectionMap);
  1516.   while (it.hasNext()) {
  1517.     const SBinetHttpConnection *conn = static_cast<const SBinetHttpConnection*>(it.next()->getValue());
  1518.     delete conn;
  1519.   }
  1520. }