preftran.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:52k
源码类别:

Symbian

开发平台:

Visual C++

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