preftran.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:51k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxcom.h"
  36. #include "hxtypes.h"
  37. #include "hlxclib/string.h"
  38. #include "hlxclib/stdio.h"
  39. #ifdef _MACINTOSH
  40. //#include <stat.mac.h> // Not needed on Mac and doesn't exist in CW Pro 7.
  41. #else
  42. #include "hlxclib/sys/types.h"
  43. #include "hlxclib/sys/stat.h"
  44. #endif
  45. #include "hlxclib/time.h"
  46. #if defined(_AIX)
  47. #include <ctype.h>
  48. #endif
  49. #if defined(_WINDOWS)  
  50. #include <windows.h>
  51. #ifndef _WINCE
  52. #include <winsock2.h>
  53. #include <ws2tcpip.h>
  54. #endif /* _WINCE */
  55. #endif /* _WINDOWS */
  56. #include "hlxclib/sys/socket.h"
  57. #include "hxresult.h"
  58. #include "hxslist.h"
  59. #include "ihxpckts.h"
  60. #include "hxstrutl.h"
  61. #include "dbcs.h"
  62. #include "dllpath.h"
  63. #include "hxprefs.h"
  64. #include "hxprefutil.h"
  65. #include "hxthread.h"
  66. #include "netbyte.h"
  67. #include "hxpxymgr.h"
  68. #include "portaddr.h"
  69. #include "prefdefs.h"
  70. #include "hxengin.h"
  71. #include "hxnetif.h"
  72. #include "pacutil.h"
  73. #include "preftran.h"
  74. #ifdef _UNIX
  75. #include <sys/types.h>
  76. #include <sys/stat.h>
  77. #include <netinet/in.h>
  78. #include <sys/socket.h>
  79. #if defined _SOLARIS || defined _FREEBSD || defined _OPENBSD || defined _NETBSD
  80. #include <sys/sockio.h>
  81. #endif
  82. #include <net/if.h>
  83. #include <sys/ioctl.h>
  84. #endif
  85. #include "hlxclib/stdlib.h" // for i64toa
  86. #if defined (_UNIX) && !defined(_SUN) && !defined(_SCO_UW) && !defined(_HPUX) && !defined(_IRIX) && !defined(_OSF1)
  87. #include <sys/file.h>
  88. #endif /* UNIX */
  89. #define RM_PREFTRAN_CAPTION "# RealMedia Preferred Transport Filen# This is a generated file!  Do not edit.nn"
  90. #define RM_PREFTRAN_DIR_NAME "preftran/"
  91. #define RM_PREFTRAN_FILE_LOCK "PrefTranFileLock"
  92. #include "hxdir.h" /* for OS_SEPARATOR_CHAR and OS_SEPARATOR_STRING */
  93. HXPreferredTransport::HXPreferredTransport(HXPreferredTransportManager* pOwner)
  94.      : m_lRefCount(0)
  95.      , m_pOwner(pOwner)
  96.      , m_bHTTPNG(FALSE)
  97.      , m_pHost(NULL)
  98.      , m_ulHost(0)
  99.      , m_ulParentPlaybacks(0)
  100.      , m_uPlaybacks(0)
  101.      , m_uCloakPort(0)
  102.      , m_state(PTS_UNKNOWN)
  103.      , m_lastUsedTime(0)
  104.      , m_prefTransportClass(PTC_UNKNOWN)
  105.      , m_prefTransportProtocol(PTP_UNKNOWN)
  106.      , m_prefTransportType(UnknownMode)
  107.      , m_pPrefTransportSinkList(NULL)
  108. {
  109.     HX_ADDREF(m_pOwner);
  110. }
  111. HXPreferredTransport::~HXPreferredTransport()
  112. {
  113.     Close();
  114. }
  115. STDMETHODIMP
  116. HXPreferredTransport::QueryInterface(REFIID riid, void**ppvObj)
  117. {
  118.     QInterfaceList qiList[] =
  119.         {
  120.             { GET_IIDHANDLE(IID_IHXPreferredTransport), (IHXPreferredTransport*)this },
  121.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPreferredTransport*)this },
  122.         };
  123.     
  124.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  125. }
  126. /////////////////////////////////////////////////////////////////////////
  127. //  Method:
  128. // IUnknown::AddRef
  129. //  Purpose:
  130. // Everyone usually implements this the same... feel free to use
  131. // this implementation.
  132. //
  133. STDMETHODIMP_(ULONG32) 
  134. HXPreferredTransport::AddRef()
  135. {
  136.     return InterlockedIncrement(&m_lRefCount);
  137. }
  138. /////////////////////////////////////////////////////////////////////////
  139. //  Method:
  140. // IUnknown::Release
  141. //  Purpose:
  142. // Everyone usually implements this the same... feel free to use
  143. // this implementation.
  144. //
  145. STDMETHODIMP_(ULONG32) 
  146. HXPreferredTransport::Release()
  147. {
  148.     if (InterlockedDecrement(&m_lRefCount) > 0)
  149.     {
  150.         return m_lRefCount;
  151.     }
  152.     delete this;
  153.     return 0;
  154. }
  155. /*
  156.  * IHXPreferredTransport methods
  157.  */
  158. STDMETHODIMP
  159. HXPreferredTransport::GetTransport (REF(TransportMode) /* OUT */   prefTransportType,
  160.     REF(UINT16) /* OUT */   ulCloakPort)
  161. {
  162.     HX_RESULT rc = HXR_OK;
  163.     prefTransportType = UnknownMode;
  164.     ulCloakPort = 0;
  165.     switch (m_state)
  166.     {
  167.     case PTS_CREATE:
  168. m_state = PTS_PENDING;
  169. prefTransportType = m_prefTransportType;
  170. ulCloakPort = m_uCloakPort;
  171. break;
  172.     case PTS_PENDING:
  173. rc = HXR_WOULD_BLOCK;
  174. break;
  175.     case PTS_READY:
  176. prefTransportType = m_prefTransportType;
  177. ulCloakPort = m_uCloakPort;
  178. break;
  179.     default:
  180. break;
  181.     }
  182.     return rc;
  183. }
  184.     
  185. STDMETHODIMP
  186. HXPreferredTransport::SetTransport(TransportMode   /* IN  */   prefTransportType,
  187.     UINT16     /* IN  */   ulCloakPort)
  188. {
  189.     HX_RESULT rc = HXR_OK;
  190.     BOOL bSave = FALSE;
  191.     UINT32 ulTransportMask = 0;
  192.     HX_ASSERT(UnknownMode != prefTransportType);
  193.     // we will mask UDP to Multicast if Multicast is selected given
  194.     // the fact the server will always try UDP along with Multicast request
  195.     if (UDPMode == prefTransportType && m_pOwner)
  196.     {
  197. if (PTP_RTSP == m_prefTransportProtocol)
  198. {
  199.     ulTransportMask = m_pOwner->m_ulRTSPTransportMask;
  200. }
  201. else
  202. {
  203.     ulTransportMask = m_pOwner->m_ulPNMTransportMask;
  204.      }
  205. if (ulTransportMask & ATTEMPT_MULTICAST)
  206. {
  207.     prefTransportType = MulticastMode;
  208. }
  209.     }
  210.     m_state = PTS_READY;
  211.     m_uCloakPort = ulCloakPort;
  212.     m_lastUsedTime = time(NULL);
  213.     if (m_prefTransportType != prefTransportType)
  214.     {
  215. bSave = TRUE;
  216. m_uPlaybacks = 0;
  217. m_prefTransportType = prefTransportType;
  218.     }
  219.     if (m_pPrefTransportSinkList)
  220.     {
  221. CHXSimpleList::Iterator i = m_pPrefTransportSinkList->Begin();
  222. for (; i != m_pPrefTransportSinkList->End(); ++i)
  223. {
  224.     IHXPreferredTransportSink* pSink = (IHXPreferredTransportSink*)*i;
  225.     pSink->TransportSucceeded(m_prefTransportType, m_uCloakPort);
  226. }
  227.     }
  228.     if (m_pOwner)
  229.     {
  230.         m_pOwner->TransportSet(this, bSave);
  231.     }
  232.     return rc;
  233. }
  234. STDMETHODIMP
  235. HXPreferredTransport::SwitchTransport(HX_RESULT     /* IN  */   error,
  236.       REF(TransportMode)    /* INOUT */ prefTransportType)
  237. {
  238.     if (m_pOwner)
  239.     {
  240.         return m_pOwner->DownShiftTransport(error, this, prefTransportType);
  241.     }
  242.     return HXR_FAILED;
  243. }
  244. STDMETHODIMP
  245. HXPreferredTransport::RemoveTransport()
  246. {
  247.     m_state = PTS_UNKNOWN;
  248.     m_uPlaybacks = 0;
  249.     m_uCloakPort = 0;
  250.     m_prefTransportType = UnknownMode;
  251.     m_lastUsedTime = 0;
  252.     if (m_pPrefTransportSinkList)
  253.     {
  254. CHXSimpleList::Iterator i = m_pPrefTransportSinkList->Begin();
  255. for (; i != m_pPrefTransportSinkList->End(); ++i)
  256. {
  257.     IHXPreferredTransportSink* pSink = (IHXPreferredTransportSink*)*i;
  258.     pSink->TransportFailed();
  259. }
  260.     }
  261.     return HXR_OK;
  262. }
  263.     
  264. STDMETHODIMP_(BOOL)
  265. HXPreferredTransport::ValidateTransport(TransportMode    /* IN */ prefTransportType)
  266. {
  267.     if (m_pOwner)
  268.     {
  269.         return m_pOwner->ValidateTransport(this, prefTransportType);
  270.     }
  271.     return FALSE;
  272. }
  273. STDMETHODIMP_(PreferredTransportState)
  274. HXPreferredTransport::GetState()
  275. {
  276.     return m_state;
  277. }
  278. STDMETHODIMP_(PreferredTransportClass)
  279. HXPreferredTransport::GetClass()
  280. {
  281.     return m_prefTransportClass;
  282. }
  283. STDMETHODIMP
  284. HXPreferredTransport::AddTransportSink(IHXPreferredTransportSink* /* IN  */   pPrefTransportSink)
  285. {
  286.     LISTPOSITION lPosition = 0;
  287.     if (!pPrefTransportSink)
  288.     {
  289. return HXR_FAILED;
  290.     }
  291.     if (!m_pPrefTransportSinkList)
  292.     {
  293. m_pPrefTransportSinkList = new CHXSimpleList;
  294.     }
  295.     else
  296.     {
  297. lPosition = m_pPrefTransportSinkList->Find(pPrefTransportSink);
  298.     }
  299.     if (!lPosition)
  300.     {
  301. pPrefTransportSink->AddRef();
  302. m_pPrefTransportSinkList->AddTail(pPrefTransportSink);
  303.     }
  304.     return HXR_OK;
  305. }
  306. STDMETHODIMP
  307. HXPreferredTransport::RemoveTransportSink(IHXPreferredTransportSink* /* IN  */   pPrefTransportSink)
  308. {
  309.     if (!m_pPrefTransportSinkList)
  310.     {
  311. return HXR_UNEXPECTED;
  312.     }
  313.     LISTPOSITION lPosition = m_pPrefTransportSinkList->Find(pPrefTransportSink);
  314.     if (!lPosition)
  315.     {
  316. return HXR_UNEXPECTED;
  317.     }
  318.     m_pPrefTransportSinkList->RemoveAt(lPosition);
  319.     HX_RELEASE(pPrefTransportSink);
  320.     
  321.     return HXR_OK;
  322. }
  323. STDMETHODIMP_(BOOL)
  324. HXPreferredTransport::GetHTTPNG()
  325. {
  326.     return m_bHTTPNG;
  327. }
  328. STDMETHODIMP
  329. HXPreferredTransport::SetHTTPNG(BOOL bHTTPNG)
  330. {
  331.     m_bHTTPNG = bHTTPNG;
  332.     return HXR_OK;
  333. }
  334. void
  335. HXPreferredTransport::Initialize()
  336. {
  337.     TransportMode upShiftToTransport = UnknownMode;
  338.     if (!m_pOwner)
  339.     {
  340.         return;
  341.     }
  342.     if (m_lastUsedTime && PTS_READY == m_state)
  343.     {
  344. // detect whether the preferences has been changed
  345. // since its last use
  346. if (PTP_RTSP == m_prefTransportProtocol &&
  347.     m_lastUsedTime < m_pOwner->m_lastRTSPPreferencesModifiedTime)
  348. {
  349.     m_state = PTS_CREATE;
  350.     m_uPlaybacks = 0;
  351.     m_prefTransportType = m_pOwner->m_rtspTransportTypeStartWith;
  352. }
  353. else if (PTP_PNM == m_prefTransportProtocol &&
  354.          m_lastUsedTime < m_pOwner->m_lastPNMPreferencesModifiedTime)
  355. {
  356.     m_state = PTS_CREATE;
  357.     m_uPlaybacks = 0;
  358.     m_prefTransportType = m_pOwner->m_pnmTransportTypeStartWith;
  359. }
  360. else if (m_pOwner->m_ulPlaybacks != m_ulParentPlaybacks)
  361. {
  362.     m_ulParentPlaybacks = m_pOwner->m_ulPlaybacks;   
  363.     m_uPlaybacks++;
  364.     // save the playback counter for UpShift
  365.     if (PTP_RTSP == m_prefTransportProtocol &&
  366. m_prefTransportType > m_pOwner->m_rtspTransportTypeStartWith)
  367.     {
  368. m_pOwner->m_bSave = TRUE;
  369.     }
  370.     else if (PTP_PNM == m_prefTransportProtocol &&
  371.      m_prefTransportType > m_pOwner->m_pnmTransportTypeStartWith)
  372.     {
  373. m_pOwner->m_bSave = TRUE;
  374.     }
  375.     // attempt transport upshift every 3rd play
  376.     m_uPlaybacks = m_uPlaybacks % 3;
  377.     if (0 == m_uPlaybacks)
  378.     {
  379. upShiftToTransport = m_prefTransportType;
  380. m_pOwner->UpShiftTransport(this, upShiftToTransport);
  381. if (upShiftToTransport != m_prefTransportType)
  382. {
  383.     m_state = PTS_CREATE;
  384.     m_prefTransportType = upShiftToTransport;
  385. }
  386.     }
  387. }
  388.     }
  389.     // this is the first use
  390.     else
  391.     {
  392. if (PTS_CREATE == m_state)
  393. {
  394.     m_uPlaybacks = 0;
  395.     m_prefTransportType = m_pOwner->GetTransportPreferred(this);
  396. }
  397. else
  398. {
  399.     HX_ASSERT(PTS_PENDING == m_state);
  400.     m_prefTransportType = UnknownMode;
  401. }
  402.     }
  403.     
  404.     // sanity check
  405.     if (UnknownMode != m_prefTransportType)
  406.     {
  407. if (PTP_RTSP == m_prefTransportProtocol)
  408. {
  409.     HX_ASSERT(m_prefTransportType >= m_pOwner->m_rtspTransportTypeStartWith);
  410. }
  411. else if (PTP_PNM == m_prefTransportProtocol)
  412. {
  413.     HX_ASSERT(m_prefTransportType >= m_pOwner->m_pnmTransportTypeStartWith);
  414. }
  415.     }
  416.     return;
  417. }
  418. void
  419. HXPreferredTransport::Close()
  420. {
  421.     HX_DELETE(m_pHost);
  422.     if (m_pPrefTransportSinkList)
  423.     {
  424. CHXSimpleList::Iterator i = m_pPrefTransportSinkList->Begin();
  425. for (; i != m_pPrefTransportSinkList->End(); ++i)
  426. {
  427.     IHXPreferredTransportSink* pSink = (IHXPreferredTransportSink*)*i;
  428.     HX_RELEASE(pSink);
  429. }
  430. HX_DELETE(m_pPrefTransportSinkList);
  431.     }
  432.     HX_RELEASE(m_pOwner);
  433. }
  434. HXPreferredTransportManager::HXPreferredTransportManager(IUnknown* pContext)
  435.     : m_lRefCount(0)
  436.     , m_bSave(FALSE)
  437.     , m_pszFile(NULL)
  438.     , m_ulRTSPTransportMask(ATTEMPT_AUTOTRANSPORT)
  439.     , m_ulPNMTransportMask(ATTEMPT_AUTOTRANSPORT)
  440.     , m_ulLocalHost(0)
  441.     , m_ulSubnetMask(0)
  442.     , m_ulSubnet(0)
  443.     , m_ulPlaybacks(0)
  444.     , m_lastRTSPPreferencesModifiedTime(0)
  445.     , m_lastPNMPreferencesModifiedTime(0)
  446.     , m_internalTransportType(MulticastMode)
  447.     , m_externalTransportType(MulticastMode)
  448.     , m_rtspTransportTypeStartWith(MulticastMode)
  449.     , m_pnmTransportTypeStartWith(MulticastMode)
  450.     , m_pPrefHostTransportList(NULL)
  451.     , m_pPrevPrefHostTransportList(NULL)
  452.     , m_pSubnetManager(NULL)
  453.     , m_pPreferences(NULL)
  454.     , m_pProxyManager(NULL)
  455.     , m_pHXNetInterface(NULL)
  456.     , m_bInitialized(FALSE)
  457. #ifdef _WINDOWS
  458.     , m_pLock(NULL)
  459. #elif _UNIX
  460.     , m_fileID(0)
  461. #endif /* _WINDOWS */
  462. {    
  463.     if (pContext)
  464.     {
  465. m_pContext = pContext;
  466. m_pContext->AddRef();
  467.     }
  468. }
  469. HXPreferredTransportManager::~HXPreferredTransportManager()
  470. {
  471.     Close();
  472. }
  473. STDMETHODIMP
  474. HXPreferredTransportManager::QueryInterface(REFIID riid, void**ppvObj)
  475. {
  476.     QInterfaceList qiList[] =
  477.         {
  478.             { GET_IIDHANDLE(IID_IHXPreferredTransportManager), (IHXPreferredTransportManager*)this },
  479.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPreferredTransportManager*)this },
  480.         };
  481.     
  482.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  483. }
  484. /////////////////////////////////////////////////////////////////////////
  485. //  Method:
  486. // IUnknown::AddRef
  487. //  Purpose:
  488. // Everyone usually implements this the same... feel free to use
  489. // this implementation.
  490. //
  491. STDMETHODIMP_(ULONG32) 
  492. HXPreferredTransportManager::AddRef()
  493. {
  494.     return InterlockedIncrement(&m_lRefCount);
  495. }
  496. /////////////////////////////////////////////////////////////////////////
  497. //  Method:
  498. // IUnknown::Release
  499. //  Purpose:
  500. // Everyone usually implements this the same... feel free to use
  501. // this implementation.
  502. //
  503. STDMETHODIMP_(ULONG32) 
  504. HXPreferredTransportManager::Release()
  505. {
  506.     if (InterlockedDecrement(&m_lRefCount) > 0)
  507.     {
  508.         return m_lRefCount;
  509.     }
  510.     delete this;
  511.     return 0;
  512. }
  513. HX_RESULT    
  514. HXPreferredTransportManager::_Initialize(void)
  515. {
  516.     HX_RESULT hr = HXR_OK;
  517.     HXNetInterface* pHXNI = NULL;
  518.     
  519.     if (!m_pContext)
  520.     {
  521. hr = HXR_FAILED;
  522. goto cleanup;
  523.     }
  524.     if (!m_pSubnetManager)
  525.     {
  526. m_pSubnetManager = new HXSubnetManager((IUnknown*)m_pContext);
  527.     }
  528. #if defined(HELIX_FEATURE_PROXYMGR)
  529.     if (!m_pProxyManager)
  530.     {
  531. m_pContext->QueryInterface(IID_IHXProxyManager, (void**)&m_pProxyManager);
  532. HX_ASSERT(m_pProxyManager);
  533.     }
  534. #endif /* #if defined(HELIX_FEATURE_PROXYMGR) */
  535.     CollectNetworkInfo();
  536.     PrepPrefTransport();
  537.     OpenPrefTransport();
  538.     m_bInitialized = TRUE;
  539. cleanup:
  540.     return hr;
  541. }
  542. HX_RESULT
  543. HXPreferredTransportManager::ReadPreferences(BOOL  bRTSPProtocol, UINT32& ulTransportMask)
  544. {
  545.     BOOL bAutoTransport = TRUE;
  546.     BOOL bMulticast = FALSE;
  547.     BOOL bUDP = FALSE;
  548.     BOOL bTCP = FALSE;
  549.     BOOL bHTTPCloak = FALSE; 
  550.     ulTransportMask = 0;
  551.     ReadPrefBOOL(m_pPreferences, "AutoTransport", bAutoTransport);
  552.     if (bAutoTransport)
  553.     {
  554. ulTransportMask = ATTEMPT_AUTOTRANSPORT;
  555.     }
  556.     else
  557.     {
  558.         ReadPrefBOOL(m_pPreferences, bRTSPProtocol?"AttemptRTSPvMulticast":"AttemptPNAvMulticast", bMulticast);
  559.         ReadPrefBOOL(m_pPreferences, bRTSPProtocol?"AttemptRTSPvUDP":"AttemptPNAvUDP", bUDP);
  560.         ReadPrefBOOL(m_pPreferences, bRTSPProtocol?"AttemptRTSPvTCP":"AttemptPNAvTCP", bTCP);
  561.         ReadPrefBOOL(m_pPreferences, bRTSPProtocol?"AttemptRTSPvHTTP":"AttemptPNAvHTTP", bHTTPCloak);
  562. if (bMulticast)
  563. {
  564.     ulTransportMask |= ATTEMPT_MULTICAST;
  565. }
  566. if (bUDP)
  567. {
  568.     ulTransportMask |= ATTEMPT_UDP;
  569. }
  570. if (bTCP)
  571. {
  572.     ulTransportMask |= ATTEMPT_TCP;
  573. }
  574. if (bHTTPCloak)
  575. {
  576.     ulTransportMask |= ATTEMPT_HTTPCLOAK;
  577. }
  578.     }
  579.     return HXR_OK;
  580. }
  581. void
  582. HXPreferredTransportManager::Close(void)
  583. {
  584.     if (m_bSave)
  585.     {
  586. SavePrefTransport();
  587.     }
  588.     ResetPrefTransport(m_pPrevPrefHostTransportList);
  589.     HX_DELETE(m_pPrevPrefHostTransportList);
  590.     ResetPrefTransport(m_pPrefHostTransportList);
  591.     HX_DELETE(m_pPrefHostTransportList);
  592.     HX_DELETE(m_pSubnetManager);
  593.     if (m_pHXNetInterface)
  594.     {
  595. m_pHXNetInterface->RemoveAdviseSink((IHXNetInterfacesAdviseSink*)this);
  596. HX_RELEASE(m_pHXNetInterface);
  597.     }
  598. #if defined(HELIX_FEATURE_PROXYMGR)
  599.     HX_RELEASE(m_pProxyManager);
  600. #endif /* HELIX_FEATURE_PROXYMGR */
  601.     HX_RELEASE(m_pPreferences);
  602.     HX_RELEASE(m_pContext);
  603.     HX_VECTOR_DELETE(m_pszFile);
  604.     m_bInitialized = FALSE;
  605. #ifdef _WINDOWS
  606.     HX_DELETE(m_pLock);
  607. #endif /* _WINDOWS */
  608. }
  609. void
  610. HXPreferredTransportManager::TransportSet(HXPreferredTransport* pPreferredTransport,
  611.    BOOL bSave)
  612. {
  613.     if (PTC_INTERNAL == pPreferredTransport->m_prefTransportClass)
  614.     {
  615. m_internalTransportType = pPreferredTransport->m_prefTransportType;
  616.     }
  617.     else if (PTC_EXTERNAL == pPreferredTransport->m_prefTransportClass)
  618.     {
  619. m_externalTransportType = pPreferredTransport->m_prefTransportType;
  620.     }
  621.     else
  622.     {
  623. HX_ASSERT(FALSE);
  624.     }
  625.     if (bSave)
  626.     {
  627. m_bSave = TRUE;
  628.     }
  629. }
  630.       
  631. /************************************************************************
  632.  * Method:
  633.  *     IHXPreferredTransportManager::Initialize
  634.  * Purpose:
  635.  *     Initialize the transport manager such as re-reading the preferences
  636.  */
  637. STDMETHODIMP
  638. HXPreferredTransportManager::Initialize()
  639. {
  640.     HX_RESULT rc = HXR_OK;
  641.     BOOL bPreferenceModified = FALSE;
  642.     UINT32 ulRTSPTransportMask = ATTEMPT_AUTOTRANSPORT;
  643.     UINT32 ulPNMTransportMask = ATTEMPT_AUTOTRANSPORT;
  644.     if (!m_bInitialized)
  645.     {
  646. rc = _Initialize();
  647.     }
  648.     HX_ASSERT(HXR_OK == rc);
  649.     ResetPrefTransport(m_pPrevPrefHostTransportList);
  650.     ReadPreferences(TRUE, ulRTSPTransportMask);
  651.     ReadPreferences(FALSE, ulPNMTransportMask);
  652.     if (ulRTSPTransportMask != m_ulRTSPTransportMask)
  653.     {
  654. bPreferenceModified = TRUE;
  655. m_ulRTSPTransportMask = ulRTSPTransportMask;
  656. m_lastRTSPPreferencesModifiedTime = time(NULL);
  657.     }
  658.     if (ulPNMTransportMask != m_ulPNMTransportMask)
  659.     {
  660. bPreferenceModified = TRUE;
  661. m_ulPNMTransportMask = ulPNMTransportMask;
  662. m_lastPNMPreferencesModifiedTime = time(NULL);
  663.     }
  664.     InitTransportTypeStartWith(m_ulRTSPTransportMask, m_rtspTransportTypeStartWith);
  665.     InitTransportTypeStartWith(m_ulPNMTransportMask, m_pnmTransportTypeStartWith);
  666.     // re-initialize internal/external transport type to its lowest start transport
  667.     // type when we detect the transport preference has been changed
  668.     if (bPreferenceModified)
  669.     {
  670. m_externalTransportType = m_internalTransportType = GetLowerTransport(m_rtspTransportTypeStartWith,
  671.       m_pnmTransportTypeStartWith);
  672.     }
  673.     m_pSubnetManager->Initialize();
  674. #if defined(HELIX_FEATURE_PROXYMGR)
  675.     m_pProxyManager->Initialize(m_pContext);
  676. #endif /* HELIX_FEATURE_PROXYMGR */
  677.     m_ulPlaybacks++;
  678.     return rc;
  679. }
  680. /************************************************************************
  681.  * Method:
  682.  *     IHXPreferredTransportManager::GetPrefTransport
  683.  * Purpose:
  684.  *     Get preferred host transport
  685.  */
  686. STDMETHODIMP
  687. HXPreferredTransportManager::GetPrefTransport(const char*     /* IN  */ pszHostName,
  688.       PreferredTransportProtocol    /* IN  */ prefTransportProtocol,
  689.       REF(IHXPreferredTransport*)   /* OUT */ pPrefTransport)
  690. {
  691.     HX_RESULT     rc = HXR_OK;
  692.     BOOL     bFound = FALSE;
  693.     UINT32     ulIAddress = 0;
  694.     UINT32     ulHostAddress = 0;
  695.     HXPreferredTransport*   pTransport = NULL;
  696.     PreferredTransportClass prefTransportClass = PTC_EXTERNAL;
  697.     CHXString*     pDomainHost = NULL;
  698.     CHXSimpleList::Iterator i;
  699.     pPrefTransport = NULL;
  700.     if (!m_bInitialized)
  701.     {
  702. rc = _Initialize();
  703. if (HXR_OK != rc)
  704. {
  705.     goto cleanup;
  706. }
  707.     }
  708.     if (pszHostName)
  709.     {
  710.         if(IsNumericAddr(pszHostName, strlen(pszHostName)))
  711.         {
  712.     ulIAddress = HXinet_addr(pszHostName);
  713.     ulHostAddress = DwToHost(ulIAddress);
  714.     pDomainHost = new CHXString(pszHostName);
  715.         }
  716.         else
  717.         {
  718.     pDomainHost = GetMasterDomain(pszHostName);
  719.         }
  720.         prefTransportClass = GetTransportClass(pszHostName, ulHostAddress);
  721.         if (m_pPrefHostTransportList)
  722.         {
  723.     i = m_pPrefHostTransportList->Begin();
  724.     for (; i != m_pPrefHostTransportList->End(); ++i)
  725.     {
  726.         pTransport = (HXPreferredTransport*)*i;
  727.         // based on host name for now
  728.         if (pTransport->m_pHost &&
  729.                     !pTransport->m_pHost->CompareNoCase((const char*)*pDomainHost)   &&
  730.     pTransport->m_prefTransportProtocol == prefTransportProtocol    &&
  731.     pTransport->m_prefTransportClass == prefTransportClass)
  732.         {
  733.     bFound = TRUE;
  734.     break;
  735.         }
  736.     }
  737.         }
  738.     }
  739.     if (bFound)
  740.     {
  741. // previous transport attempt is failed
  742. if (pTransport->m_state == PTS_UNKNOWN)
  743. {
  744.     pTransport->m_state = PTS_CREATE;
  745. }
  746.  
  747. pTransport->Initialize();
  748.         pPrefTransport = pTransport;
  749. pPrefTransport->AddRef();
  750.     }
  751.     else
  752.     {
  753. pTransport = new HXPreferredTransport(this);
  754. pTransport->AddRef();
  755. pTransport->m_pHost = pDomainHost;
  756. pTransport->m_ulHost = ulHostAddress;
  757. pTransport->m_prefTransportClass = prefTransportClass;
  758. pTransport->m_prefTransportProtocol = prefTransportProtocol; 
  759. pTransport->m_state = PTS_CREATE;
  760. pTransport->Initialize();
  761.         if (!m_pPrefHostTransportList)
  762.         {
  763.     m_pPrefHostTransportList = new CHXSimpleList();
  764.         }
  765. m_pPrefHostTransportList->AddTail(pTransport);
  766. rc = pTransport->QueryInterface(IID_IHXPreferredTransport, (void**)&pPrefTransport);
  767.     }
  768.     if (pTransport->m_state != PTS_READY)
  769.     {
  770. m_bSave = TRUE;
  771.     }
  772. cleanup:
  773.     return rc;
  774. }
  775. /************************************************************************
  776.  * Method:
  777.  *     IHXPreferredTransportManager::RemovePrefTransport
  778.  * Purpose:
  779.  *     Remove preferred host transport
  780.  */
  781. STDMETHODIMP
  782. HXPreferredTransportManager::RemovePrefTransport(IHXPreferredTransport*   /* IN */ pPrefTransport)
  783. {
  784.     HX_RESULT     rc = HXR_OK;
  785.     HXPreferredTransport*  pTransport = NULL;
  786.     LISTPOSITION     lPos = NULL;
  787.     if (!m_pPrefHostTransportList)
  788.     {
  789. goto cleanup;
  790.     }
  791.     lPos = m_pPrefHostTransportList->GetHeadPosition();
  792.     while (lPos && m_pPrefHostTransportList->GetCount())
  793.     {     
  794. pTransport = (HXPreferredTransport*)m_pPrefHostTransportList->GetAt(lPos);
  795. if (pTransport == pPrefTransport)
  796. {
  797.     HX_RELEASE(pTransport);
  798.     lPos = m_pPrefHostTransportList->RemoveAt(lPos);
  799. }
  800. else
  801. {
  802.     m_pPrefHostTransportList->GetNext(lPos);
  803. }
  804.     }
  805. cleanup:
  806.     return rc;
  807. }
  808. /************************************************************************
  809.  * Method:
  810.  *     IHXPreferredTransportManager::GetTransportPreference
  811.  * Purpose:
  812.  *     Get transport preference set by the user
  813.  */
  814. STDMETHODIMP
  815. HXPreferredTransportManager::GetTransportPreference(PreferredTransportProtocol /* IN  */ prefTransportProtocol,
  816.      REF(UINT32) /* OUT */ ulPreferenceMask)
  817. {
  818.     HX_RESULT rc = HXR_OK;
  819.     if (PTP_RTSP == prefTransportProtocol)
  820.     {
  821. ulPreferenceMask = m_ulRTSPTransportMask;
  822.     }
  823.     else if (PTP_PNM == prefTransportProtocol)
  824.     {
  825. ulPreferenceMask = m_ulPNMTransportMask;
  826.     }
  827.     else
  828.     {
  829. rc = HXR_FAILED;
  830.     }
  831.     return rc;
  832. }
  833. /*
  834.  * IHXNetInterfacesAdviseSink methods
  835.  */
  836. STDMETHODIMP
  837. HXPreferredTransportManager::NetInterfacesUpdated()
  838. {
  839.     HX_RESULT rc = HXR_OK;
  840.     if (m_bSave)
  841.     {
  842. SavePrefTransport();
  843.     }
  844.     ResetPrefTransport(m_pPrevPrefHostTransportList);
  845.     m_pPrevPrefHostTransportList = m_pPrefHostTransportList;
  846.     m_pPrefHostTransportList = NULL;
  847.     HX_VECTOR_DELETE(m_pszFile);
  848.     m_bInitialized = FALSE;
  849.     return rc;
  850. }
  851. HX_RESULT     
  852. HXPreferredTransportManager::CollectNetworkInfo(void)
  853. {
  854.     HX_RESULT rc = HXR_FAILED;
  855.     UINT16 i = 0;
  856.     UINT32 uNI = 0;
  857.     NIInfo* pTempNIInfo = NULL;
  858.     NIInfo* pNIInfo = NULL;
  859.     if (!m_pHXNetInterface)
  860.     {
  861. if (HXR_OK != m_pContext->QueryInterface(IID_IHXNetInterfaces, (void**)&m_pHXNetInterface))
  862. {
  863.     goto cleanup;
  864. }
  865. m_pHXNetInterface->AddAdviseSink((IHXNetInterfacesAdviseSink*)this);
  866.     }
  867.     if (m_pHXNetInterface)
  868.     {
  869. uNI = m_pHXNetInterface->GetNumOfNetInterfaces();
  870. for (i = 0; i < uNI; i++)
  871. {
  872.     if (HXR_OK == m_pHXNetInterface->GetNetInterfaces(i, pTempNIInfo))
  873.     {
  874. if (pTempNIInfo && pTempNIInfo->bActive)
  875. {     
  876.     pNIInfo = pTempNIInfo;
  877.     if (POINTTOPOINT == pNIInfo->type)
  878.     {
  879. break;
  880.     }
  881. }
  882.     }
  883. }
  884. if (pNIInfo)
  885. {
  886.     m_ulLocalHost  = DwToHost(pNIInfo->ulNetAddress);
  887.     m_ulSubnetMask = DwToHost(pNIInfo->ulNetMask);
  888.     rc = HXR_OK;
  889. }
  890.     }
  891.     HX_ASSERT(m_ulLocalHost);
  892.     HX_ASSERT(m_ulSubnetMask);
  893.     m_ulSubnet = m_ulLocalHost & m_ulSubnetMask;
  894. cleanup:
  895.     return rc;
  896. }
  897. HX_RESULT     
  898. HXPreferredTransportManager::PrepPrefTransport(void)
  899. {
  900.     HX_RESULT   hr = HXR_OK;
  901. #ifndef _VXWORKS
  902.     char        buffer[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  903.     const char* pszValue = NULL;
  904.     IHXBuffer*  pBuffer = NULL;
  905.     IHXBuffer*  pPrefBuffer = NULL;
  906.     CHXString   strUserDataPath;
  907.     if (!m_pPreferences &&  
  908.         HXR_OK != m_pContext->QueryInterface(IID_IHXPreferences, (void**)&m_pPreferences))
  909.     {
  910.         hr = HXR_FAILED;
  911.         goto cleanup;
  912.     }
  913.     if (HXR_OK == m_pPreferences->ReadPref("UserSDKDataPath", pBuffer) && pBuffer)
  914.     {
  915.         pszValue = (char*) pBuffer->GetBuffer();
  916.     }
  917.     if (!pszValue)
  918.     {
  919.         // construct base path
  920. #ifdef _UNIX
  921.         strUserDataPath = (const char*) getenv("HOME");
  922.         strUserDataPath += OS_SEPARATOR_CHAR;
  923.         strUserDataPath += ".helix";
  924.         strUserDataPath += OS_SEPARATOR_CHAR;
  925.         pszValue = (const char*) strUserDataPath;
  926. #else
  927.         pszValue = GetDLLAccessPath()->GetPath(DLLTYPE_COMMON);
  928. #endif        
  929.     }
  930.     // determine whether preferred transport setting of this network configuration
  931.     // has been saved
  932. #ifdef _MAC_MACHO
  933. sprintf(buffer, "networkconfig_%lX.txt", m_ulSubnet);
  934. #else
  935.     i64toa(m_ulSubnet, buffer, 16);
  936.     strcat(buffer, ".txt"); /* Flawfinder: ignore */
  937. #endif
  938.    
  939.     m_pszFile = new char[strlen(pszValue) + strlen(buffer) + 10];
  940.     ::strcpy(m_pszFile, pszValue); /* Flawfinder: ignore */
  941.     if (m_pszFile[::strlen(m_pszFile)-1] != OS_SEPARATOR_CHAR)
  942.     {
  943.         strcat(m_pszFile, OS_SEPARATOR_STRING); /* Flawfinder: ignore */
  944.     }
  945.     strcat(m_pszFile, buffer); /* Flawfinder: ignore */
  946. #if !defined (__TCS__)
  947.     // we maintain max # of preferred transport config files with
  948.     // the least used file deleted
  949.     m_pPreferences->ReadPref("PreferredTransportFiles", pPrefBuffer);
  950.     ::AddFileToFileListWithCap(buffer, 0, pszValue, pPrefBuffer);
  951.     m_pPreferences->WritePref("PreferredTransportFiles", pPrefBuffer);
  952. #endif /* __TCS__ */
  953.     HX_RELEASE(pPrefBuffer);
  954.     HX_RELEASE(pBuffer);
  955. #endif /* _VXWORKS */
  956.   cleanup:
  957.     return hr;
  958. }
  959. void
  960. HXPreferredTransportManager::ResetPrefTransport(CHXSimpleList* pPrefHostTransportList)
  961. {
  962.     HXPreferredTransport*   pTransport = NULL;
  963.     while (pPrefHostTransportList && pPrefHostTransportList->GetCount() > 0)
  964.     {
  965. pTransport = (HXPreferredTransport*)pPrefHostTransportList->RemoveHead();
  966. pTransport->Close();
  967. HX_RELEASE(pTransport);
  968.     }
  969. }
  970. HX_RESULT
  971. HXPreferredTransportManager::FileReadLine(FILE* fp, char* pLine, UINT32 ulLineBuf, UINT32* pBytesRead)
  972. {
  973.     HX_RESULT hr = HXR_OK;
  974.     UINT32 i = 0;
  975.     UINT32 ulBytesRead = 0;
  976.     char* pTmpBuf = NULL;
  977.     if (!fp)
  978.     {
  979. hr = HXR_FAILED;
  980. goto cleanup;
  981.     }
  982.     if (ulLineBuf < 1) 
  983.     {
  984.         *pBytesRead = 0;
  985.         goto cleanup;
  986.     }
  987.     ulBytesRead = fread(pLine, sizeof(char), ulLineBuf, fp);
  988.     pTmpBuf = pLine;
  989.     if (ulBytesRead)
  990.     {
  991. while (i < ulBytesRead) 
  992. {
  993. #ifdef _MACINTOSH
  994.     if (pTmpBuf[i] == 10 || pTmpBuf[i] == 13)
  995. #else
  996.     if (pTmpBuf[i] == 10)
  997. #endif
  998.     {   // LF
  999. if (pTmpBuf[i+1])
  1000. {
  1001.     pTmpBuf[i+1] = '';
  1002. }
  1003. // Back the file pointer up.
  1004. fseek(fp, (long)((i + 1) - ulBytesRead), SEEK_CUR);
  1005. *pBytesRead = i + 1;
  1006. break;
  1007.     }
  1008.     i++;
  1009. }
  1010.     }
  1011.     else
  1012.     {
  1013. hr = HXR_FAILED;
  1014.     }
  1015.     
  1016. cleanup:
  1017.     return hr;
  1018. }
  1019. HX_RESULT
  1020. HXPreferredTransportManager::FileWriteLine(FILE* fp, HXPreferredTransport* pPrefTransport)
  1021. {
  1022.     HX_RESULT rc = HXR_OK;
  1023.     UINT32 ulNetAddress = 0;
  1024.     char        buffer[36] = {0}; /* Flawfinder: ignore */
  1025.     char* value = NULL;
  1026.     /* line format is:
  1027.      *
  1028.      * hostname t class t protocol t transport t cloakport t lastRTSPmodifiedtime(internalclass) or
  1029.      *   lastPNMModifiedtime(externalclass)
  1030.      *
  1031.      * hostname     - string(null by default)
  1032.      * class     - transport class(PTC_Internal by default)
  1033.      * protocol     - protocol type(RTSP vs PNM)
  1034.      * transport    - preferred transport(UDPMode by default)
  1035.      * cloakport    - cloak port
  1036.      * time     - last used time
  1037.      * sameserverIP - cloak GET/POST w/ same serverIP
  1038.      * playbacks    - # of playbacks
  1039.      */
  1040.     if (pPrefTransport->m_pHost)
  1041.     {     
  1042. fwrite((const char*)*(pPrefTransport->m_pHost), sizeof(char), pPrefTransport->m_pHost->GetLength(), fp);
  1043.     }
  1044.     else
  1045.     {
  1046.         HX_ASSERT(FALSE);
  1047.     }
  1048.     fwrite("t", sizeof(char), 1, fp);
  1049.     itoa(pPrefTransport->m_prefTransportClass, buffer, 10);
  1050.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1051.     fwrite("t", sizeof(char), 1, fp);
  1052.     itoa(pPrefTransport->m_prefTransportProtocol, buffer, 10);
  1053.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1054.     fwrite("t", sizeof(char), 1, fp);
  1055.     itoa(pPrefTransport->m_prefTransportType, buffer, 10);
  1056.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1057.     fwrite("t", sizeof(char), 1, fp);
  1058.     itoa(pPrefTransport->m_uCloakPort, buffer, 10);
  1059.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1060.     fwrite("t", sizeof(char), 1, fp);
  1061.     snprintf(buffer, 36, "%lu", pPrefTransport->m_lastUsedTime); /* Flawfinder: ignore */
  1062.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1063.     fwrite("t", sizeof(char), 1, fp);
  1064.     itoa(pPrefTransport->m_bHTTPNG, buffer, 10);
  1065.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1066.     fwrite("t", sizeof(char), 1, fp);
  1067.     itoa(pPrefTransport->m_uPlaybacks, buffer, 10);
  1068.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1069.     fwrite(LINEBREAK, sizeof(char), LINEBREAK_LEN, fp);
  1070.     return rc;
  1071. }
  1072. HX_RESULT
  1073. HXPreferredTransportManager::FileWriteClass(FILE* fp, 
  1074.      PreferredTransportClass prefTransportClass, 
  1075.      TransportMode transportType,
  1076.      PreferredTransportProtocol protocol,
  1077.      UINT32 ulTransportMask,
  1078.      time_t lastModifiedTime)
  1079. {
  1080.     HX_RESULT rc = HXR_OK;
  1081.     char        buffer[36] = {0}; /* Flawfinder: ignore */
  1082.     /* line format is:
  1083.      *
  1084.      * hostname t class t protocol t transport t cloakport t lastusedtime
  1085.      *
  1086.      * hostname     - string(null by default)
  1087.      * class     - transport class(PTC_Internal by default)
  1088.      * transport    - preferred transport of this class
  1089.      * protocol     - protocol type(RTSP vs PNM)
  1090.      * transportmask- mask for the transport preference
  1091.      * time     - last RTSP/PNM preferences' modified time
  1092.      */
  1093.     fwrite("localhost", sizeof(char), 9, fp);
  1094.     fwrite("t", sizeof(char), 1, fp);
  1095.     itoa(prefTransportClass, buffer, 10);
  1096.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1097.     fwrite("t", sizeof(char), 1, fp);
  1098.     itoa(transportType, buffer, 10);
  1099.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1100.     fwrite("t", sizeof(char), 1, fp);
  1101.     itoa(protocol, buffer, 10);
  1102.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1103.     fwrite("t", sizeof(char), 1, fp);
  1104.     snprintf(buffer,36, "%lu", ulTransportMask); /* Flawfinder: ignore */
  1105.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1106.     fwrite("t", sizeof(char), 1, fp);
  1107.     snprintf(buffer,36, "%lu", lastModifiedTime); /* Flawfinder: ignore */
  1108.     fwrite(buffer, sizeof(char), strlen(buffer), fp);
  1109.     fwrite(LINEBREAK, sizeof(char), LINEBREAK_LEN, fp);
  1110.     return rc;
  1111. }
  1112. HX_RESULT
  1113. HXPreferredTransportManager::DownShiftTransport(HX_RESULT error, 
  1114.  HXPreferredTransport* pPrefTransport,
  1115.  REF(TransportMode) prefTransportType)
  1116. {
  1117.     HX_RESULT rc = HXR_OK;
  1118.     UINT32 ulTransportMask = ATTEMPT_AUTOTRANSPORT;
  1119.     HX_ASSERT(UnknownMode != prefTransportType);
  1120.     // HTTPCloak is the last on the transport switching list
  1121.     if (HTTPCloakMode == prefTransportType)
  1122.     {
  1123. prefTransportType = UnknownMode;
  1124. goto cleanup;
  1125.     }
  1126.     if (PTP_RTSP == pPrefTransport->m_prefTransportProtocol)
  1127.     {
  1128. ulTransportMask = m_ulRTSPTransportMask;
  1129.     }
  1130.     else if (PTP_PNM == pPrefTransport->m_prefTransportProtocol)
  1131.     {
  1132. ulTransportMask = m_ulPNMTransportMask;
  1133.     }
  1134.     else
  1135.     {
  1136. HX_ASSERT(FALSE);
  1137.     }
  1138.     // switch to HTTP Cloaking directly if the following list of network
  1139.     // errors have been occured
  1140.     if (error == HXR_NET_CONNECT     ||
  1141. error == HXR_DNR     ||
  1142. error == HXR_SERVER_DISCONNECTED    ||
  1143. error == HXR_DOC_MISSING     ||
  1144. error == HXR_BAD_SERVER     ||
  1145. error == HXR_PROXY_NET_CONNECT)
  1146.     {
  1147. if (ulTransportMask & ATTEMPT_HTTPCLOAK)
  1148. {
  1149.     prefTransportType = HTTPCloakMode;
  1150. }
  1151. else
  1152. {
  1153.     prefTransportType = UnknownMode;
  1154. }
  1155.     }
  1156.     else
  1157.     {
  1158. if (prefTransportType == MulticastMode ||
  1159.     prefTransportType == UDPMode)
  1160. {
  1161.     if (ulTransportMask & ATTEMPT_TCP)
  1162.     {
  1163. prefTransportType = TCPMode;
  1164. goto cleanup;
  1165.     }
  1166.          else if (ulTransportMask & ATTEMPT_HTTPCLOAK)
  1167.     {
  1168. prefTransportType = HTTPCloakMode;
  1169. goto cleanup;
  1170.     }
  1171.     else
  1172.     {
  1173. prefTransportType = UnknownMode;
  1174. goto cleanup;
  1175.     }
  1176. }
  1177. else if (prefTransportType == TCPMode)
  1178. {  
  1179.     if (ulTransportMask & ATTEMPT_HTTPCLOAK)
  1180.     {
  1181. prefTransportType = HTTPCloakMode;
  1182. goto cleanup;
  1183.     }
  1184.     else
  1185.     {
  1186. prefTransportType = UnknownMode;
  1187. goto cleanup;
  1188.     }
  1189. }
  1190.     }
  1191. cleanup:
  1192.     return rc;
  1193. }
  1194. HX_RESULT
  1195. HXPreferredTransportManager::UpShiftTransport(HXPreferredTransport* pPrefTransport,
  1196.        REF(TransportMode) prefTransportType)
  1197. {
  1198.     HX_RESULT rc = HXR_OK;
  1199.     UINT32 ulTransportMask = ATTEMPT_AUTOTRANSPORT;
  1200.     HX_ASSERT(UnknownMode != prefTransportType);
  1201.     // MulticastMode/UDPMode is the toppest on the transport switching list
  1202.     if (MulticastMode == prefTransportType ||
  1203. UDPMode == prefTransportType)
  1204.     {
  1205. goto cleanup;
  1206.     }
  1207.     if (PTP_RTSP == pPrefTransport->m_prefTransportProtocol)
  1208.     {
  1209. ulTransportMask = m_ulRTSPTransportMask;
  1210.     }
  1211.     else if (PTP_PNM == pPrefTransport->m_prefTransportProtocol)
  1212.     {
  1213. ulTransportMask = m_ulPNMTransportMask;
  1214.     }
  1215.     else
  1216.     {
  1217. HX_ASSERT(FALSE);
  1218.     }
  1219.     if (prefTransportType == HTTPCloakMode)
  1220.     {
  1221.         if (ulTransportMask & ATTEMPT_TCP)
  1222.         {
  1223.     prefTransportType = TCPMode;
  1224.     goto cleanup;
  1225. }
  1226. // this is intentional...since we always try UDP
  1227. // when we try Multicast.
  1228. else if (ulTransportMask & ATTEMPT_MULTICAST)
  1229. {
  1230.     prefTransportType = MulticastMode;
  1231. }
  1232. else if (ulTransportMask & ATTEMPT_UDP)
  1233. {
  1234.     prefTransportType = UDPMode;
  1235. }
  1236.     }
  1237.     else if (prefTransportType == TCPMode)
  1238.     {
  1239. // this is intentional...since we always try UDP
  1240. // when we try Multicast.
  1241. if (ulTransportMask & ATTEMPT_MULTICAST)
  1242. {
  1243.     prefTransportType = MulticastMode;
  1244. }
  1245. else if (ulTransportMask & ATTEMPT_UDP)
  1246. {
  1247.     prefTransportType = UDPMode;
  1248. }
  1249.     }
  1250. cleanup:
  1251.     return rc;
  1252. }
  1253. BOOL
  1254. HXPreferredTransportManager::ValidateTransport(HXPreferredTransport* pPrefTransport,
  1255. TransportMode prefTransportType)
  1256. {
  1257.     BOOL    bResult = TRUE;
  1258.     UINT32  ulTransportMask = ATTEMPT_AUTOTRANSPORT;
  1259.     if (PTP_RTSP == pPrefTransport->m_prefTransportProtocol)
  1260.     {
  1261. ulTransportMask = m_ulRTSPTransportMask;
  1262.     }
  1263.     else if (PTP_PNM == pPrefTransport->m_prefTransportProtocol)
  1264.     {
  1265. ulTransportMask = m_ulPNMTransportMask;
  1266.     }
  1267.     else
  1268.     {
  1269. HX_ASSERT(FALSE);
  1270.     }
  1271.     switch (prefTransportType)
  1272.     {
  1273.     case MulticastMode:
  1274. bResult = (ulTransportMask & ATTEMPT_MULTICAST);
  1275. break;
  1276.     case UDPMode:
  1277. bResult = (ulTransportMask & ATTEMPT_UDP);
  1278. break;
  1279.     case TCPMode:
  1280. bResult = (ulTransportMask & ATTEMPT_TCP);
  1281. break;
  1282.     case HTTPCloakMode:
  1283. bResult = (ulTransportMask & ATTEMPT_HTTPCLOAK);
  1284. break;
  1285.     default:
  1286. bResult = FALSE;
  1287. break;
  1288.     }
  1289.     return bResult;
  1290. }
  1291. CHXString*
  1292. HXPreferredTransportManager::GetMasterDomain(const char* pszHostName)
  1293. {
  1294.     int nFields = 0;
  1295.     CHXString* pOutString = NULL;
  1296.     CHXString inString;
  1297.     CHXString outString;
  1298.     CHXString domainExt;
  1299.     inString = pszHostName;
  1300.     
  1301.     nFields = inString.CountFields('.');
  1302.     // a valid master domain contains either one or two fields
  1303.     // such as "dingdong", "realguide.com" and "rbn.com"
  1304.     if (nFields <= 2)
  1305.     {
  1306. pOutString = new CHXString(inString);
  1307.     }
  1308.     else
  1309.     {
  1310. domainExt = inString.NthField('.', nFields);
  1311. // distinguish between domestic domains and international domains
  1312. if (!domainExt.CompareNoCase("com") ||
  1313.     !domainExt.CompareNoCase("net") ||
  1314.     !domainExt.CompareNoCase("org") ||
  1315.     !domainExt.CompareNoCase("edu") ||
  1316.     !domainExt.CompareNoCase("gov") ||
  1317.     !domainExt.CompareNoCase("mil"))
  1318. {
  1319.     // save the last 2 nodes for domestic domains
  1320.     outString = inString.NthField('.', nFields - 1);
  1321.     outString += ".";
  1322.     outString += inString.NthField('.', nFields);
  1323. }
  1324. else
  1325. {
  1326.     // save the last 3 nods for international domains
  1327.     outString = inString.NthField('.', nFields - 2);
  1328.     outString += ".";
  1329.     outString += inString.NthField('.', nFields - 1);
  1330.     outString += ".";
  1331.     outString += inString.NthField('.', nFields);
  1332. }
  1333. pOutString = new CHXString(outString);
  1334.     }
  1335.     return pOutString;
  1336. }
  1337. TransportMode
  1338. HXPreferredTransportManager::GetTransportPreferred(HXPreferredTransport* pPrefTransport)
  1339. {
  1340.     TransportMode   transportMode = UnknownMode;
  1341.  
  1342.     if (PTC_INTERNAL == pPrefTransport->m_prefTransportClass)
  1343.     {
  1344. if (PTP_RTSP == pPrefTransport->m_prefTransportProtocol)
  1345. {
  1346.     transportMode = GetHigherTransport(m_rtspTransportTypeStartWith,
  1347.        m_internalTransportType);
  1348. }
  1349. else if (PTP_PNM == pPrefTransport->m_prefTransportProtocol)
  1350. {
  1351.     transportMode = GetHigherTransport(m_pnmTransportTypeStartWith,
  1352.        m_internalTransportType);
  1353. }
  1354. else
  1355. {
  1356.     HX_ASSERT(FALSE);
  1357. }
  1358.     }
  1359.     else if (PTC_EXTERNAL == pPrefTransport->m_prefTransportClass)
  1360.     {
  1361. if (PTP_RTSP == pPrefTransport->m_prefTransportProtocol)
  1362. {
  1363.     transportMode = m_rtspTransportTypeStartWith; 
  1364. //     GetHigherTransport(m_rtspTransportTypeStartWith,
  1365. //        m_externalTransportType);
  1366. }
  1367. else if (PTP_PNM == pPrefTransport->m_prefTransportProtocol)
  1368. {
  1369.     transportMode = m_pnmTransportTypeStartWith;
  1370. //     GetHigherTransport(m_pnmTransportTypeStartWith,
  1371. //        m_externalTransportType);
  1372. }
  1373. else
  1374. {
  1375.     HX_ASSERT(FALSE);
  1376. }
  1377.     }
  1378.  
  1379.     return transportMode;
  1380. }
  1381. TransportMode
  1382. HXPreferredTransportManager::GetHigherTransport(TransportMode mode1, TransportMode mode2)
  1383. {
  1384.     if (mode1 < mode2)
  1385.     {
  1386. return mode2;
  1387.     }
  1388.     else
  1389.     {
  1390. return mode1;
  1391.     }    
  1392. }
  1393.     
  1394. TransportMode
  1395. HXPreferredTransportManager::GetLowerTransport(TransportMode mode1, TransportMode mode2)
  1396. {
  1397.     if (mode1 > mode2)
  1398.     {
  1399. return mode2;
  1400.     }
  1401.     else
  1402.     {
  1403. return mode1;
  1404.     }    
  1405. }
  1406. PreferredTransportClass
  1407. HXPreferredTransportManager::GetTransportClass(const char* pszHostName, UINT32 ulHostAddress)
  1408. {
  1409.     HX_RESULT rc = HXR_OK;
  1410.     PreferredTransportClass prefTransportClass = PTC_EXTERNAL;
  1411.     // Internal server is defined as:
  1412.     // a. a media server on the same network subnet as the client, or
  1413.     // b. a media server on a network subnet that meets the "Peer Subnet" criteria 
  1414.     //    (either as an explicit entry or by meeting wildcard criteria), or
  1415.     // c. a media server that meets the "Proxy Exclude" criteria 
  1416.     //    (either as an explicit entry or by meeting wildcard criteria)
  1417.     if ((m_ulSubnetMask && m_ulSubnet && ((ulHostAddress & m_ulSubnetMask) == m_ulSubnet))  ||
  1418. m_pSubnetManager->IsSubnet(pszHostName)     
  1419. #if defined(HELIX_FEATURE_PROXYMGR)
  1420. || m_pProxyManager->IsExemptionHost((char*)pszHostName)
  1421. #endif /* HELIX_FEATURE_PROXYMGR */
  1422. )
  1423.     {
  1424. prefTransportClass = PTC_INTERNAL;
  1425.     }
  1426.     return prefTransportClass;
  1427. }
  1428. void
  1429. HXPreferredTransportManager::InitTransportTypeStartWith(UINT32 ulTransportMask, 
  1430.  TransportMode& transportStartWith)
  1431. {
  1432.     transportStartWith = UnknownMode;
  1433.     if (ulTransportMask & ATTEMPT_MULTICAST)
  1434.     {
  1435. transportStartWith = MulticastMode;
  1436.     }
  1437.     else if (ulTransportMask & ATTEMPT_UDP)
  1438.     {
  1439. transportStartWith = UDPMode;
  1440.     }
  1441.     else if (ulTransportMask & ATTEMPT_TCP)
  1442.     {
  1443. transportStartWith = TCPMode;
  1444.     }
  1445.     else if (ulTransportMask & ATTEMPT_HTTPCLOAK)
  1446.     {
  1447. transportStartWith = HTTPCloakMode;
  1448.     }
  1449.     else
  1450.     {
  1451. HX_ASSERT(FALSE);
  1452.     }
  1453.     return;
  1454. }
  1455. HX_RESULT
  1456. HXPreferredTransportManager::OpenPrefTransport(void)
  1457. {
  1458.     HX_RESULT     hr = HXR_OK;
  1459.     char*     pszHostName = NULL;
  1460.     char*     pszClass = NULL;
  1461.     char*     pszProtocol = NULL;
  1462.     char*     pszTransport = NULL; 
  1463.     char*     pszTransportMask = NULL;
  1464.     char*     pszCloakPort = NULL;
  1465.     char*     pszExpires = NULL;
  1466.     char*     pszHTTPNG = NULL;
  1467.     char*     pszPlaybacks = NULL;
  1468.     char*     pszUnknownField = NULL;
  1469.     char     buffer[LINE_BUFFER_SIZE] = {0}; /* Flawfinder: ignore */
  1470.     UINT32     ulBytesRead = 0;
  1471.     UINT32     ulIAddress = 0;
  1472.     FILE*     fp = NULL;
  1473.     HXPreferredTransport* pTransport = NULL;
  1474.     PreferredTransportClass transportClass = PTC_UNKNOWN;
  1475.  
  1476.     if (!m_pszFile)
  1477.     {
  1478. hr = HXR_FAILED;
  1479. goto cleanup;
  1480.     }
  1481. #ifdef _WINDOWS
  1482.     if (!m_pLock)
  1483.     {
  1484. #ifdef THREADS_SUPPORTED        
  1485. HXEvent::MakeEvent(m_pLock, RM_PREFTRAN_FILE_LOCK, FALSE);
  1486. #else        
  1487. HXEvent::MakeStubEvent(m_pLock, RM_PREFTRAN_FILE_LOCK, FALSE);
  1488. #endif
  1489.     }
  1490.     else
  1491.     {
  1492. m_pLock->Wait();
  1493.     }
  1494. #endif /* _WINDOWS */
  1495.     if (!(fp = fopen(m_pszFile, "r+b")))
  1496.     {
  1497. hr = HXR_FAILED;
  1498. goto cleanup;
  1499.     }
  1500. #if defined (_UNIX) && !defined(_SUN) && !defined(_SCO_UW) && !defined(_HPUX) && !defined(_IRIX) && !defined(_AIX) && !defined(_OSF1)
  1501.     m_fileID = fileno(fp);    
  1502.     flock(m_fileID, LOCK_EX);
  1503. #endif /* _UNIX */
  1504.      /* line format is:
  1505.      *
  1506.      * hostname t class t protocol t transport t cloakport t time
  1507.      *
  1508.      * hostname     - string(null by default)
  1509.      * class     - transport class(PTC_Internal by default)
  1510.      * protocol     - protocol type(RTSP vs PNM)
  1511.      * transport    - preferred transport(UDPMode by default)
  1512.      * cloakport    - cloak port
  1513.      * time     - time of last used or modified
  1514.      */
  1515.     while (HXR_OK == FileReadLine(fp, &buffer[0], LINE_BUFFER_SIZE, &ulBytesRead))
  1516.     {
  1517. if (*buffer == '#' || *buffer == CR || *buffer == LF || *buffer == 0)
  1518. {
  1519.     continue;
  1520. }
  1521. pszHostName = buffer;
  1522.     
  1523. if(!(pszClass = strchr(pszHostName, 't')))
  1524. {
  1525.     continue;
  1526. }
  1527. *pszClass++ = '';
  1528. if(*pszClass == CR || *pszClass == LF || *pszClass == 0)
  1529. {
  1530.     continue;
  1531. }
  1532. if (0 == strcasecmp(pszHostName, "localhost"))
  1533. {
  1534.     transportClass = (PreferredTransportClass)atoi(pszClass);
  1535.     if(!(pszTransport = strchr(pszClass, 't')))
  1536.     {
  1537. continue;
  1538.     }
  1539.     *pszTransport++ = '';
  1540.     if(*pszTransport == CR || *pszTransport == LF || *pszTransport == 0)
  1541.     {
  1542. continue;
  1543.     }
  1544.     if(!(pszProtocol = strchr(pszTransport, 't')))
  1545.     {
  1546. continue;
  1547.     }
  1548.     *pszProtocol++ = '';
  1549.     if(*pszProtocol == CR || *pszProtocol == LF || *pszProtocol == 0)
  1550.     {
  1551. continue;
  1552.     }
  1553.     if(!(pszTransportMask = strchr(pszProtocol, 't')))
  1554.     {
  1555. continue;
  1556.     }
  1557.     *pszTransportMask++ = '';
  1558.     if(*pszTransportMask == CR || *pszTransportMask == LF || *pszTransportMask == 0)
  1559.     {
  1560. continue;
  1561.     }
  1562.     if(!(pszExpires = strchr(pszTransportMask, 't')))
  1563.     {
  1564. continue;
  1565.     }
  1566.     *pszExpires++ = '';
  1567.     if(*pszExpires == CR || *pszExpires == LF || *pszExpires == 0)
  1568.     {
  1569. continue;
  1570.     }
  1571.     if (!(pszUnknownField = strchr(pszExpires, 't')))
  1572.     {
  1573. // remove the 'n' from the end of the entry
  1574. pszExpires = ::StripLine(pszExpires);
  1575.     }
  1576.     else
  1577.     {
  1578. *pszUnknownField++ = '';
  1579.     }
  1580.     if (PTC_INTERNAL == transportClass)
  1581.     {
  1582. m_internalTransportType = (TransportMode)atoi(pszTransport);
  1583. #ifdef _MACINTOSH
  1584. m_ulRTSPTransportMask = atoi64(pszTransportMask);
  1585. m_lastRTSPPreferencesModifiedTime = (time_t)atoi64(pszExpires);
  1586. #else
  1587. m_ulRTSPTransportMask = atol(pszTransportMask);
  1588. m_lastRTSPPreferencesModifiedTime = atol(pszExpires);
  1589. #endif
  1590.     }
  1591.     else if (PTC_EXTERNAL == transportClass)
  1592.     {
  1593. m_externalTransportType = (TransportMode)atoi(pszTransport);
  1594. #ifdef _MACINTOSH
  1595. m_ulPNMTransportMask = atoi64(pszTransportMask);
  1596. m_lastPNMPreferencesModifiedTime = (time_t)atoi64(pszExpires);
  1597. #else
  1598. m_ulPNMTransportMask = atol(pszTransportMask);
  1599. m_lastPNMPreferencesModifiedTime = atol(pszExpires);
  1600. #endif
  1601.     }
  1602.     else
  1603.     {
  1604. HX_ASSERT(FALSE);
  1605.     }
  1606. }
  1607. else
  1608. {
  1609.     if(!(pszProtocol = strchr(pszClass, 't')))
  1610.     {
  1611. continue;
  1612.     }
  1613.     *pszProtocol++ = '';
  1614.     if(*pszProtocol == CR || *pszProtocol == LF || *pszProtocol == 0)
  1615.     {
  1616. continue;
  1617.     }
  1618.     if(!(pszTransport = strchr(pszProtocol, 't')))
  1619.     {
  1620. continue;
  1621.     }
  1622.     *pszTransport++ = '';
  1623.     if(*pszTransport == CR || *pszTransport == LF || *pszTransport == 0)
  1624.     {
  1625. continue;
  1626.     }
  1627.     if(!(pszCloakPort = strchr(pszTransport, 't')))
  1628.     {
  1629. continue;
  1630.     }
  1631.     *pszCloakPort++ = '';
  1632.     if(*pszCloakPort == CR || *pszCloakPort == LF || *pszCloakPort == 0)
  1633.     {
  1634. continue;
  1635.     }
  1636.     if(!(pszExpires = strchr(pszCloakPort, 't')))
  1637.     {
  1638. continue;
  1639.     }
  1640.     *pszExpires++ = '';
  1641.     if(*pszExpires == CR || *pszExpires == LF || *pszExpires == 0)
  1642.     {
  1643. continue;
  1644.     }
  1645.     if(!(pszHTTPNG = strchr(pszExpires, 't')))
  1646.     {
  1647. continue;
  1648.     }
  1649.     *pszHTTPNG++ = '';
  1650.     if(*pszHTTPNG == CR || *pszHTTPNG == LF || *pszHTTPNG == 0)
  1651.     {
  1652. continue;
  1653.     }
  1654.     if (!(pszPlaybacks = strchr(pszHTTPNG, 't')))
  1655.     {
  1656. continue;
  1657.     }
  1658.     *pszPlaybacks++ = '';
  1659.     if(*pszPlaybacks == CR || *pszPlaybacks == LF || *pszPlaybacks == 0)
  1660.     {
  1661. continue;
  1662.     }
  1663.     
  1664.     if (!(pszUnknownField = strchr(pszPlaybacks, 't')))
  1665.     {
  1666. // remove the 'n' from the end of the entry
  1667. pszPlaybacks = ::StripLine(pszPlaybacks);
  1668.     }
  1669.     else
  1670.     {
  1671. *pszUnknownField++ = '';
  1672.     }
  1673.     // construct a new preferred transport struct
  1674.     pTransport = new HXPreferredTransport(this);
  1675.     pTransport->AddRef();
  1676.     pTransport->m_pHost = new CHXString(pszHostName);
  1677.     pTransport->m_prefTransportClass = (PreferredTransportClass)atoi(pszClass);
  1678.     pTransport->m_prefTransportProtocol = (PreferredTransportProtocol)atoi(pszProtocol);
  1679.     pTransport->m_prefTransportType = (TransportMode)atoi(pszTransport);
  1680.     pTransport->m_uCloakPort = atoi(pszCloakPort);
  1681. #ifdef _MACINTOSH
  1682.     pTransport->m_lastUsedTime = (time_t)atoi64(pszExpires);
  1683. #else
  1684.     pTransport->m_lastUsedTime = atol(pszExpires);
  1685. #endif
  1686.     pTransport->m_bHTTPNG = atoi(pszHTTPNG);
  1687.     pTransport->m_uPlaybacks = atoi(pszPlaybacks);
  1688.     pTransport->m_state = PTS_READY;
  1689.     if (!m_pPrefHostTransportList)
  1690.     {
  1691. m_pPrefHostTransportList = new CHXSimpleList();
  1692.     }
  1693.     m_pPrefHostTransportList->AddTail(pTransport);
  1694. }
  1695.     }
  1696. cleanup:
  1697. #if defined (_UNIX) && !defined(_SUN) && !defined(_SCO_UW) && !defined(_HPUX) && !defined(_IRIX) && !defined(_AIX) && !defined(_OSF1)
  1698.     flock(m_fileID, LOCK_UN);
  1699. #endif /* _UNIX */
  1700.     if (fp)
  1701.     {
  1702. fclose(fp);
  1703.     }
  1704. #ifdef _WINDOWS
  1705.     if (m_pLock)
  1706.     {
  1707. m_pLock->SignalEvent();
  1708.     }
  1709. #endif /* _WINDOWS */
  1710.     return hr;
  1711. }
  1712. HX_RESULT
  1713. HXPreferredTransportManager::SavePrefTransport(void)
  1714. {
  1715.     HX_RESULT     hr = HXR_OK;
  1716.     FILE*     fp = NULL;
  1717.     UINT32     ulTransportMask = 0;
  1718.     HXPreferredTransport*  pTransport = NULL;
  1719.     CHXSimpleList::Iterator  i;
  1720.     if (!m_pszFile)
  1721.     {
  1722. goto cleanup;
  1723.     }
  1724. #ifdef _WINDOWS
  1725.     if (!m_pLock)
  1726.     {
  1727. #ifdef THREADS_SUPPORTED        
  1728. HXEvent::MakeEvent(m_pLock, RM_PREFTRAN_FILE_LOCK, FALSE);
  1729. #else
  1730. HXEvent::MakeStubEvent(m_pLock, RM_PREFTRAN_FILE_LOCK, FALSE);
  1731. #endif        
  1732.     }
  1733.     else
  1734.     {
  1735. m_pLock->Wait();
  1736.     }
  1737. #endif /* _WINDOWS */
  1738.     if (!(fp = fopen(m_pszFile, "w")))
  1739.     {
  1740. hr = HXR_FAILED;
  1741. goto cleanup;
  1742.     }
  1743. #ifdef _UNIX
  1744.     //Make the permisions on the cookies file User read/write only.
  1745.     if( chmod( m_pszFile, S_IRUSR | S_IWUSR ) != 0 )
  1746.     {
  1747.         HX_ASSERT( "Can't change permision on cookies file." == NULL );
  1748.     }
  1749.     
  1750. #endif    
  1751. #if defined (_UNIX) && !defined(_SUN) && !defined(_SCO_UW) && !defined(_HPUX) && !defined(_IRIX) && !defined(_AIX) && !defined(_OSF1)
  1752.     m_fileID = fileno(fp);    
  1753.     flock(m_fileID, LOCK_EX);
  1754. #endif /* _UNIX */
  1755.     fwrite(RM_PREFTRAN_CAPTION, sizeof(char), strlen(RM_PREFTRAN_CAPTION), fp);
  1756.     // save preferred class information first
  1757.     FileWriteClass(fp, PTC_INTERNAL, m_internalTransportType, PTP_RTSP, m_ulRTSPTransportMask, m_lastRTSPPreferencesModifiedTime);
  1758.     FileWriteClass(fp, PTC_EXTERNAL, m_externalTransportType, PTP_PNM, m_ulPNMTransportMask, m_lastPNMPreferencesModifiedTime);
  1759.     // save preferred host information
  1760.     if (m_pPrefHostTransportList)
  1761.     {
  1762. for (i = m_pPrefHostTransportList->Begin(); i != m_pPrefHostTransportList->End(); ++i)
  1763. {
  1764.     pTransport = (HXPreferredTransport*)(*i);
  1765.     if (pTransport->m_pHost && PTS_READY == pTransport->m_state)
  1766.     {
  1767. FileWriteLine(fp, pTransport);
  1768.     }
  1769. }
  1770.     }
  1771.     m_bSave = FALSE;
  1772.     
  1773. cleanup:
  1774. #if defined (_UNIX) && !defined(_SUN) && !defined(_SCO_UW) && !defined(_HPUX) && !defined(_IRIX) && !defined(_AIX) && !defined(_OSF1)
  1775.     flock(m_fileID, LOCK_UN);
  1776. #endif /* _UNIX */
  1777.     if (fp)
  1778.     {
  1779. fclose(fp);
  1780.     }
  1781. #ifdef _WINDOWS
  1782.     if (m_pLock)
  1783.     {
  1784. m_pLock->SignalEvent();
  1785.     }
  1786. #endif /* _WINDOWS */
  1787.     return(hr);
  1788. }