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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxcloakedtcp.cpp,v 1.7.8.2 2004/07/13 18:06:24 bobclark 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 "hlxclib/stdio.h"   
  50. #include "hxcloakedtcp.h"
  51. #include "safestring.h"
  52. #include "hxnetutil.h"
  53. #include "ihxpckts.h"
  54. #include "hxccf.h" // IHXCommonClassFactory
  55. #include "hxthread.h" // HXMutex
  56. #include "hxbuffer.h" // CHXBuffer
  57. #include "conn.h"     // TCP_BUF_SIZE
  58. #include "dbcs.h"     // HXFindString
  59. #include "hxmarsh.h"  // getshort()
  60. #include "chxuuid.h"  // CHXuuid
  61. #include "hxtick.h"   // HX_GET_TICKCOUNT
  62. #include "rtsputil.h" // BinTo64
  63. #include "hxfiles.h"  // CLSID_IHXRequest
  64. #include "hxplnsp.h"  // _CIHXObjectConfiguration_SP
  65. #include "hxcomsp.h"  // _CIHXCommonClassFactory_SP
  66. // necessary for authentication
  67. #include "hxmon.h"
  68. #include "httppars.h"
  69. #include "hxplgns.h"
  70. #include "hxcore.h"
  71. #include "httpclk.h"
  72. #ifdef _MACINTOSH
  73. #include "hx_moreprocesses.h"
  74. #endif
  75. /******************* HTTP Cloaking*****************/
  76. #define QUEUE_START_SIZE    512
  77. #define HTTPCLOAK_PUTRESPONSE_TIMEOUT 2000
  78. #define MAX_HTTP_METHOD_BUFSIZE           2048
  79. #define HXGUID_SIZE  16 // 16 byte GUID plus rn
  80. #define ENQUEUE_DATA(x,y,z) (x)->EnQueue((y),(z))
  81. #define ENQUEUE_BYTE(x,y) {UCHAR uChar = (y); 
  82. (x)->EnQueue(&uChar,sizeof(uChar));}
  83. #define ENQUEUE_WORD(x,y) {UINT16 wTemp = (y); 
  84. wTemp = WToNet(wTemp); 
  85. (x)->EnQueue(&wTemp,sizeof(UINT16));}
  86. #define ENQUEUE_DWORD(x,y) {ULONG32 dTemp = (y); 
  87. dTemp = DwToNet(dTemp); 
  88. (x)->EnQueue(&dTemp,sizeof(ULONG32));}
  89. #define DEFAULT_HTTP_HEADER_LENGTH 256
  90. #define DEFAULT_OPTION_PADDING_LENGTH 16381
  91. #ifdef _WINCE
  92. #define SCHED_GRANULARITY 10
  93. #else
  94. #define SCHED_GRANULARITY 50
  95. #endif
  96. enum
  97. {
  98.     HTTP_OK = 0,
  99.     HTTP_GENERAL_ERROR, // for any error that is not defined below
  100.     POST_NOT_RECEIVED,  // POST message was not received
  101.     INVALID_GUID  // sent only if the GUID from the Player is already in use
  102. };
  103. /* HXClientCloakedTCPSocket */
  104. HXClientCloakedTCPSocket::HXClientCloakedTCPSocket(IUnknown* pContext):
  105.      m_lRefCount(0)
  106.     ,m_pContext(pContext)
  107.     ,m_pTCPResponse(0)
  108.     ,m_pNetworkServices(0)
  109.     ,m_pGetCtrl(0)
  110.     ,m_pPutCtrl(0)
  111.     ,m_pGetCtrlResponse(0)
  112.     ,m_pPutCtrlResponse(0)
  113.     ,m_bGetReadPending(FALSE)
  114.     ,m_bPutReadPending(FALSE)
  115.     ,m_bPutWantWritePending(FALSE)
  116.     ,m_lForeignAddress(0)
  117.     ,m_nForeignPort(0)
  118.     ,m_bReadPending(FALSE)
  119.     ,m_nRequired(0)
  120.     ,m_pSendTCP(0)
  121.     ,m_pReceiveGetTCP(0)
  122.     ,m_pReceivePutTCP(0)
  123.     ,m_pPreEncodedSendHTTP(0)
  124.     ,m_pPostEncodedSendHTTP(0)
  125.     ,m_pOutBuf(0)
  126.     ,m_pOutEncodedBuf(0)
  127.     ,m_pInBuf(0)
  128.     ,m_bConnected(FALSE)
  129.     ,m_pForiegnHost(0)
  130.     ,m_pGuid(0)
  131.     ,m_bGetConnectDone(FALSE)
  132.     ,m_bPutConnectDone(FALSE)
  133.     ,m_bGetConnectSuccessful(FALSE)
  134.     ,m_bPutConnectSuccessful(FALSE)
  135.     ,m_bConnectResponsePending(TRUE)
  136.     ,m_bOptionsReceived(FALSE)
  137.     ,m_bUseExactContentLength(FALSE)
  138.     ,m_bCloseHttpAfterWrite(FALSE)
  139.     ,m_bMustCloseHTTP(FALSE)
  140.     ,m_bHttpInitialized(FALSE)
  141.     ,m_LastError(HXR_OK)
  142.     ,m_pHTTPHeaderBuffer(0)
  143.     ,m_nHTTPHeaderBufferLength(0)
  144.     ,m_bHTTPGetHeaderReadDone(FALSE)
  145.     ,m_bHTTPPutHeaderReadDone(FALSE)
  146.     ,m_pProxyHostName(0)
  147.     ,m_nProxyPortNumber(0)
  148.     ,m_bInDestructor(FALSE)
  149.     ,m_pScheduler(0)
  150.     ,m_pSchedulerCallback(0)
  151.     ,m_pNonInterruptCallback(0)
  152.     ,m_bInDoRead(FALSE)
  153.     ,m_bInDoGetWrite(FALSE)
  154.     ,m_bInDoPutWrite(FALSE)
  155.     ,m_bInTransferBuffers(FALSE)
  156.     ,m_bInitComplete(FALSE)
  157.     ,m_bDeletePadding(FALSE)
  158.     ,m_uPadLength(10+DEFAULT_OPTION_PADDING_LENGTH) // 10 for the opts and 16381 for the padding
  159.     ,m_pInterruptState(NULL)
  160.     ,m_pResponseInterruptSafe(NULL)
  161.     ,m_pMutex(NULL)
  162.     ,m_pCloakValues(NULL)
  163.     ,m_pCloakContext(NULL)
  164.     ,m_bGetResponsed(FALSE)
  165.     ,m_bPutResponsed(FALSE)
  166.     ,m_pszGetServerIP(NULL)
  167.     ,m_pszPutServerIP(NULL)
  168.     ,m_bReconnectToSameServerIP(FALSE)
  169.     ,m_bConnectToSameServerIP(FALSE)
  170.     ,m_pPreferredTransport(NULL)
  171.     ,m_pPreferredTransportManager(NULL)
  172. #ifdef _MACINTOSH
  173.     ,m_pAuthenticationCallback(NULL)
  174. #endif
  175.     ,m_bInAuthenticationKludge(FALSE)
  176. {
  177.     if(m_pContext)
  178.     {
  179. m_pContext->AddRef();
  180. m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
  181. m_pContext->QueryInterface(IID_IHXNetworkServices, (void**) &m_pNetworkServices);
  182. m_pContext->QueryInterface(IID_IHXInterruptState, (void**) &m_pInterruptState);
  183. m_pContext->QueryInterface(IID_IHXPreferredTransportManager, (void**)&m_pPreferredTransportManager);
  184.     }
  185. #if defined(THREADS_SUPPORTED) 
  186.     HXMutex::MakeMutex(m_pMutex);
  187. #elif defined(_UNIX_THREADED_NETWORK_IO)
  188.     if( ReadNetworkThreadingPref((IUnknown*)pContext) )
  189.     {
  190.         HXMutex::MakeMutex(m_pMutex);
  191.     }
  192.     else
  193.     { 
  194.         HXMutex::MakeStubMutex(m_pMutex);
  195.     }
  196. #else
  197.     HXMutex::MakeStubMutex(m_pMutex);
  198. #endif
  199. #ifdef _MACINTOSH
  200.     m_pAuthenticationCallback = new MacCloakedTCPSocketAuthenticationCallback(this);
  201.     m_pAuthenticationCallback->AddRef();
  202. #endif
  203. }
  204. HXClientCloakedTCPSocket::~HXClientCloakedTCPSocket()
  205. {
  206.     m_bInDestructor = TRUE;
  207.     
  208.     m_pMutex->Lock();
  209. #ifdef _MACINTOSH
  210.     if (m_pAuthenticationCallback && m_pAuthenticationCallback->m_ulPendingCallbackID &&
  211. m_pScheduler)
  212.     {
  213. m_pScheduler->Remove(m_pAuthenticationCallback->m_ulPendingCallbackID);
  214. m_pAuthenticationCallback->m_ulPendingCallbackID = NULL;
  215.     }
  216.     HX_RELEASE(m_pAuthenticationCallback);
  217. #endif
  218.     while (m_PendingWriteBuffers.GetCount() > 0)
  219.     {
  220. IHXBuffer* pBuffer = (IHXBuffer*) m_PendingWriteBuffers.RemoveHead();
  221. pBuffer->Release();
  222.     }
  223.     FlushQueues();
  224.     /* Send a final HTTP done message */
  225.     if (m_bHttpInitialized)
  226.     {
  227. SendHTTPDone();
  228.     }
  229.     if (m_pSchedulerCallback)
  230.     {
  231. m_pSchedulerCallback->Unschedule(m_pScheduler);
  232. HX_RELEASE(m_pSchedulerCallback);
  233.     }
  234.     if (m_pNonInterruptCallback)
  235.     {
  236. m_pNonInterruptCallback->Unschedule(m_pScheduler);
  237. HX_RELEASE(m_pNonInterruptCallback);
  238.     }
  239.     HX_RELEASE(m_pGetCtrl);
  240.     HX_RELEASE(m_pPutCtrl);
  241.     HX_RELEASE(m_pGetCtrlResponse);
  242.     HX_RELEASE(m_pPutCtrlResponse);
  243.     HX_RELEASE(m_pCloakValues);
  244.     HX_RELEASE(m_pCloakContext);
  245.     HX_RELEASE(m_pTCPResponse);
  246.     HX_RELEASE(m_pNetworkServices);
  247.     HX_DELETE(m_pSendTCP);
  248.     HX_DELETE(m_pReceiveGetTCP);
  249.     HX_DELETE(m_pReceivePutTCP);
  250.     HX_DELETE(m_pPreEncodedSendHTTP);
  251.     HX_DELETE(m_pPostEncodedSendHTTP);
  252.     HX_VECTOR_DELETE(m_pInBuf);
  253.     HX_VECTOR_DELETE(m_pOutBuf);
  254.     HX_VECTOR_DELETE(m_pOutEncodedBuf);
  255.     HX_VECTOR_DELETE(m_pForiegnHost);
  256.     HX_VECTOR_DELETE(m_pGuid);
  257.     HX_VECTOR_DELETE(m_pHTTPHeaderBuffer);
  258.     HX_VECTOR_DELETE(m_pProxyHostName);
  259.     HX_VECTOR_DELETE(m_pszGetServerIP);
  260.     HX_VECTOR_DELETE(m_pszPutServerIP);
  261.     HX_RELEASE(m_pPreferredTransport);
  262.     HX_RELEASE(m_pPreferredTransportManager);
  263.     HX_RELEASE(m_pInterruptState);
  264.     HX_RELEASE(m_pResponseInterruptSafe);
  265.     HX_RELEASE(m_pScheduler);
  266.     HX_RELEASE(m_pContext);
  267.     m_pMutex->Unlock();
  268.     HX_DELETE(m_pMutex);
  269. }
  270. STDMETHODIMP HXClientCloakedTCPSocket::QueryInterface(REFIID riid, void** ppvObj)
  271. {
  272.     QInterfaceList qiList[] =
  273.         {
  274.             { GET_IIDHANDLE(IID_IHXTCPSocket), (IHXTCPSocket*)this },
  275.             { GET_IIDHANDLE(IID_IHXCloakedTCPSocket), (IHXCloakedTCPSocket*)this },
  276.             { GET_IIDHANDLE(IID_IHXHTTPProxy), (IHXHTTPProxy*)this },
  277.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXTCPSocket*)this },
  278.         };
  279.     
  280.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  281. }
  282. STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::AddRef()
  283. {
  284.     return InterlockedIncrement(&m_lRefCount);
  285. }
  286. STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::Release()
  287. {
  288.     if (InterlockedDecrement(&m_lRefCount) > 0)
  289.     {
  290.         return m_lRefCount;
  291.     }
  292.     delete this;
  293.     return 0;
  294. }
  295. STDMETHODIMP HXClientCloakedTCPSocket::Init(IHXTCPResponse* pTCPResponse)
  296. {
  297.     HX_RESULT rc = HXR_OK;
  298.     if (!pTCPResponse)
  299.     {
  300. return HXR_UNEXPECTED;
  301.     }
  302.     if (!m_pSchedulerCallback)
  303.     {
  304. m_pSchedulerCallback = new ScheduledSocketCallback(this, TRUE);
  305. m_pSchedulerCallback->AddRef();
  306.     }
  307.     if (!m_pNonInterruptCallback)
  308.     {
  309. m_pNonInterruptCallback = new ScheduledSocketCallback(this, TRUE);
  310. m_pNonInterruptCallback->AddRef();
  311.     }
  312.     m_pTCPResponse = pTCPResponse;
  313.     m_pTCPResponse->AddRef();
  314.     m_pTCPResponse->QueryInterface(IID_IHXInterruptSafe, 
  315.    (void**) &m_pResponseInterruptSafe);
  316.     if (!m_pNetworkServices)
  317.     {
  318. return HXR_FAILED;
  319.     }
  320.     
  321.     if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pGetCtrl))
  322.     {
  323. return HXR_FAILED;
  324.     }
  325.     if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pPutCtrl))
  326.     {
  327. return HXR_FAILED;
  328.     }
  329.     m_pGetCtrlResponse = new HTTPCloakTCPResponse(this, TRUE);
  330.     m_pPutCtrlResponse = new HTTPCloakTCPResponse(this, FALSE);
  331.     if (!m_pGetCtrlResponse || !m_pPutCtrlResponse)
  332.     {
  333. return HXR_OUTOFMEMORY;
  334.     }
  335.     m_pGetCtrlResponse->AddRef();
  336.     m_pPutCtrlResponse->AddRef();
  337.     if (HXR_OK != m_pGetCtrl->Init(m_pGetCtrlResponse) || 
  338. HXR_OK != m_pPutCtrl->Init(m_pPutCtrlResponse))
  339.     {
  340. return HXR_FAILED;
  341.     }
  342.     if (HXR_OK != m_pGetCtrl->Bind(HXR_INADDR_ANY, 0) || 
  343. HXR_OK != m_pPutCtrl->Bind(HXR_INADDR_ANY, 0))
  344.     {
  345.      return HXR_FAILED;
  346.     }
  347.     // allocate TCP send and receive queue
  348.     m_pSendTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
  349.     if (!m_pSendTCP || !m_pSendTCP->IsQueueValid())
  350.     {
  351. return HXR_OUTOFMEMORY;
  352.     }
  353.     m_pSendTCP->SetMaxSize(TCP_BUF_SIZE);
  354.     m_pReceiveGetTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
  355.     if (!m_pReceiveGetTCP || !m_pReceiveGetTCP->IsQueueValid())
  356.     {
  357. return HXR_OUTOFMEMORY;
  358.     }
  359.     m_pReceiveGetTCP->SetMaxSize(TCP_BUF_SIZE);
  360.     m_pPreEncodedSendHTTP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
  361.     if (!m_pPreEncodedSendHTTP || !m_pPreEncodedSendHTTP->IsQueueValid())
  362.     {
  363. return HXR_OUTOFMEMORY;
  364.     }
  365.     /* Approx. MAX POST header size : 3000*/
  366.     m_pPreEncodedSendHTTP ->SetMaxSize((TCP_BUF_SIZE-1)/2 - 3000);
  367.     m_pPostEncodedSendHTTP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
  368.     if (!m_pPostEncodedSendHTTP || !m_pPostEncodedSendHTTP->IsQueueValid())
  369.     {
  370. return HXR_OUTOFMEMORY;
  371.     }
  372.     m_pPostEncodedSendHTTP->SetMaxSize(TCP_BUF_SIZE);
  373.     
  374.     m_pInBuf = new char[TCP_BUF_SIZE];
  375.     if (!m_pInBuf)
  376.     {
  377. return HXR_OUTOFMEMORY;
  378.     }
  379.     m_pOutBuf = new char[TCP_BUF_SIZE];
  380.     if (!m_pOutBuf)
  381.     {
  382. return HXR_OUTOFMEMORY;
  383.     }
  384.     m_pOutEncodedBuf = new char[TCP_BUF_SIZE];
  385.     if (!m_pOutEncodedBuf)
  386.     {
  387. return HXR_OUTOFMEMORY;
  388.     }
  389.     CreateGuid();
  390.     return HXR_OK;
  391. }
  392. STDMETHODIMP HXClientCloakedTCPSocket::SetResponse(IHXTCPResponse* pTCPResponse)
  393. {
  394.     m_pMutex->Lock();
  395.     HX_RELEASE(m_pTCPResponse);
  396.     m_pTCPResponse = pTCPResponse;
  397.     m_pTCPResponse->AddRef();
  398.     HX_RELEASE(m_pResponseInterruptSafe);
  399.     m_pTCPResponse->QueryInterface(IID_IHXInterruptSafe, 
  400.    (void**) &m_pResponseInterruptSafe);
  401.     m_pMutex->Unlock();
  402.     return HXR_OK;
  403. }
  404. STDMETHODIMP HXClientCloakedTCPSocket::Bind(UINT32 ulLocalAddr, UINT16 nPort)
  405. {
  406.     return HXR_NOTIMPL;
  407. }
  408. STDMETHODIMP HXClientCloakedTCPSocket::Connect(const char* pDestination,
  409. UINT16     nPort)
  410. {
  411.     m_nForeignPort = nPort;
  412.     HX_VECTOR_DELETE(m_pForiegnHost);
  413.     m_pForiegnHost = new char [strlen(pDestination) + 1];
  414.     if (!m_pForiegnHost)
  415.     {
  416. return HXR_OUTOFMEMORY;
  417.     }
  418.     ::strcpy(m_pForiegnHost, pDestination); /* Flawfinder: ignore */
  419.     // m_pCloakValues is only set by RTSP
  420.     if (m_pPreferredTransportManager && m_pCloakValues)
  421.     {
  422. HX_RELEASE(m_pPreferredTransport);
  423. m_pPreferredTransportManager->GetPrefTransport(m_pForiegnHost,
  424.        PTP_RTSP,
  425.        m_pPreferredTransport);
  426. HX_ASSERT(m_pPreferredTransport);
  427. if (m_pPreferredTransport)
  428. {
  429.     m_bConnectToSameServerIP = m_pPreferredTransport->GetHTTPNG();
  430. }
  431.     }
  432.     return  ActualConnect();
  433. }
  434. STDMETHODIMP HXClientCloakedTCPSocket::Read(UINT16 uSize)
  435. {
  436.     HX_RESULT theErr = HXR_OK;
  437.     HX_RESULT lResult = HXR_OK;
  438.     if (m_bReadPending)
  439.     {
  440. return HXR_UNEXPECTED;
  441.     }
  442.     m_bReadPending  = TRUE;
  443.     m_nRequired     = uSize;
  444.     m_pMutex->Lock();
  445.     theErr  = DoRead();
  446.     m_pMutex->Unlock();
  447.     lResult = ConvertNetworkError(theErr);
  448.     return lResult;
  449. }
  450. STDMETHODIMP HXClientCloakedTCPSocket::Write(IHXBuffer* pBuffer)
  451. {
  452.     HX_RESULT theErr = HXR_OK;
  453.     HX_RESULT lResult = HXR_OK;
  454.     pBuffer->AddRef();
  455.     m_PendingWriteBuffers.AddTail((void*) pBuffer);
  456.     
  457.     m_pMutex->Lock();
  458.     theErr = DoPutWrite();
  459.     m_pMutex->Unlock();
  460.     lResult = ConvertNetworkError(theErr);
  461.     return lResult;
  462. }
  463. STDMETHODIMP HXClientCloakedTCPSocket::WantWrite()
  464. {
  465.     m_pTCPResponse->WriteReady(HXR_OK);
  466.     return HXR_OK;
  467. }
  468. STDMETHODIMP HXClientCloakedTCPSocket::GetLocalAddress(ULONG32& lAddress)
  469. {
  470.     return HXR_NOTIMPL;
  471. }
  472. STDMETHODIMP HXClientCloakedTCPSocket::GetForeignAddress(ULONG32& lAddress)
  473. {
  474.     if(m_bConnected && m_lForeignAddress)
  475.     {
  476. lAddress = m_lForeignAddress;
  477. return HXR_OK;
  478.     }
  479.     return HXR_FAIL;
  480. }
  481. STDMETHODIMP HXClientCloakedTCPSocket::GetLocalPort(UINT16& port)
  482. {
  483.     return HXR_NOTIMPL;
  484. }
  485. STDMETHODIMP HXClientCloakedTCPSocket::GetForeignPort(UINT16& port)
  486. {
  487.     if(m_bConnected)
  488.     {
  489. port = m_nForeignPort;
  490. return HXR_OK;
  491.     }
  492.     return HXR_FAIL;
  493. }
  494. /*
  495.  * IHXHTTPProxy methods
  496.  *
  497.  *  Network addresses and ports are in native byte order
  498.  *  
  499.  */
  500. STDMETHODIMP HXClientCloakedTCPSocket::SetProxy(
  501.     const char*     /*IN*/  pProxyHostName,
  502.     UINT16     /*IN*/  nPort)
  503. {
  504.     if(pProxyHostName == 0 || *pProxyHostName == 0) 
  505.     {
  506. return HXR_FAILED;
  507.     }
  508.     
  509.     HX_VECTOR_DELETE(m_pProxyHostName);
  510.     m_pProxyHostName = new char[::strlen(pProxyHostName) + 1];
  511.     if (!m_pProxyHostName)
  512.     {
  513. return HXR_OUTOFMEMORY;
  514.     }
  515.     ::strcpy(m_pProxyHostName, pProxyHostName); /* Flawfinder: ignore */
  516.     m_nProxyPortNumber = nPort;
  517.     return HXR_OK;
  518. }
  519. /************************************************************************
  520.  * Method:
  521.  *     IHXCloakedTCPSocket::InitCloak
  522.  */
  523. STDMETHODIMP
  524. HXClientCloakedTCPSocket::InitCloak(IHXValues* /*IN*/  pValues, IUnknown* pUnknown)
  525. {
  526.     HX_RESULT rc = HXR_OK;
  527.     if (pValues)
  528.     {
  529. m_pCloakValues = pValues;
  530. m_pCloakValues->AddRef();
  531.     }
  532.     if (pUnknown)
  533.     {
  534. m_pCloakContext = pUnknown;
  535. m_pCloakContext->AddRef();
  536.     }
  537.     return rc;
  538. }
  539. HX_RESULT
  540. HXClientCloakedTCPSocket::DoRead()
  541. {
  542.     HX_RESULT theErr = HXR_OK;
  543.     char*   pStartAfterDoubleReturn = 0;
  544.     UINT16 count = 0;
  545.     if(m_bInDoRead)
  546.     {
  547. return HXR_OK;
  548.     }
  549.     m_bInDoRead = TRUE;
  550.     if (m_LastError)
  551.     {
  552. goto exit;
  553.     }
  554.     // m_pReceivePutTCP is only initialized if we receive POST response
  555.     // from the server
  556.     if (m_pReceivePutTCP)
  557.     {
  558. count = m_pReceivePutTCP->GetMaxAvailableElements();
  559.     }
  560.     else
  561.     {
  562. count = TCP_BUF_SIZE;
  563.     }
  564.     // attempt to read from PUT if:
  565.     // * we haven't initiated PUT read already AND
  566.     // * we haven't received the complete POST response header AND
  567.     // * we are not in multi-POST mode
  568.     if (count > 0     && 
  569. !m_bPutReadPending     && 
  570. !m_bHTTPPutHeaderReadDone   &&
  571. !m_bMustCloseHTTP)
  572.     {
  573. // attempt to read data from TCP link
  574. m_bPutReadPending = TRUE;
  575. theErr = m_pPutCtrl->Read(count);
  576.     }
  577.     // check how much room we have in TCP receive queue
  578.     count = m_pReceiveGetTCP->GetMaxAvailableElements();
  579.     if (count > 0 && !m_bGetReadPending)
  580.     {
  581. // attempt to read data from TCP link
  582. m_bGetReadPending = TRUE;
  583. theErr = m_pGetCtrl->Read(count);
  584. switch(theErr)
  585. {
  586.     case HXR_AT_INTERRUPT:
  587.     case HXR_WOULD_BLOCK:
  588.     case HXR_OK:
  589. // mask out these errors
  590. theErr = HXR_OK;
  591. break;
  592.     default:
  593. theErr = ConvertNetworkError(theErr);
  594. break;
  595. }
  596.     }
  597. exit:
  598.     if (theErr && !m_LastError)
  599.     {
  600. m_LastError = theErr;
  601.     }
  602.     if (m_LastError)
  603.     {
  604. if (m_bReadPending)
  605. {
  606.     if (IsSafe())
  607.     {
  608. m_bReadPending = FALSE;
  609. m_pTCPResponse->ReadDone(m_LastError, 0);
  610.     }
  611. }
  612.     }
  613.     else
  614.     {
  615. count = m_pReceiveGetTCP->GetQueuedItemCount();
  616. if (m_bReadPending && count > 0 && m_bOptionsReceived 
  617.     && m_bHTTPGetHeaderReadDone)
  618. {
  619.     /* mask any kind of errors */
  620.     theErr = HXR_OK;
  621.     if (IsSafe())
  622.     {
  623. m_bReadPending = FALSE;
  624. if (m_nRequired < count)
  625. {
  626.     count = m_nRequired;
  627. }
  628. CHXBuffer* pBuffer = new CHXBuffer;
  629. pBuffer->AddRef();
  630. m_pReceiveGetTCP->DeQueue(m_pInBuf, count);
  631. pBuffer->Set((UCHAR*) m_pInBuf, count);
  632. m_pTCPResponse->ReadDone(HXR_OK, pBuffer);
  633. pBuffer->Release();
  634.     }
  635. }
  636. if (m_pSchedulerCallback && m_bReadPending)
  637. {
  638.     m_pSchedulerCallback->ScheduleCallback(CLOAKED_TCP_READ_COMMAND, m_pScheduler, SCHED_GRANULARITY);
  639. }
  640.     }
  641.  
  642.     m_bInDoRead = FALSE;
  643.     return theErr;
  644. }
  645. HX_RESULT
  646. HXClientCloakedTCPSocket::DoGetWrite()
  647. {
  648.     HX_RESULT theErr = HXR_OK;
  649.     if (m_bInDoGetWrite)
  650.     {
  651. return HXR_OK;
  652.     }
  653.     m_bInDoGetWrite = TRUE;
  654.     // check how data we have in TCP send queue
  655.     UINT16 count    = m_pSendTCP->GetQueuedItemCount();
  656.     UINT16 actual   = count;
  657.     
  658.     if(count > 0) 
  659.     {
  660. m_pSendTCP->DeQueue(m_pOutBuf,count);
  661. CHXBuffer* pBuffer = new CHXBuffer;
  662. pBuffer->AddRef();
  663. pBuffer->Set((UCHAR*) m_pOutBuf, (ULONG32) count);
  664. theErr = m_pGetCtrl->Write(pBuffer);
  665. pBuffer->Release();
  666.     }
  667.     
  668.     if (theErr)
  669.     {
  670. switch(theErr)
  671. {
  672.     case HXR_AT_INTERRUPT:
  673.     case HXR_WOULD_BLOCK:
  674. m_pSendTCP->EnQueue(m_pOutBuf, count);
  675. // mask out these errors
  676. theErr = HXR_OK;
  677. break;
  678.     default:
  679. theErr = ConvertNetworkError(theErr);
  680. break;
  681. }
  682.     }
  683.     if (!theErr && !m_bInDestructor &&
  684. m_pSendTCP->GetQueuedItemCount() > 0 ) {
  685.     m_pSchedulerCallback->ScheduleCallback(CLOAKED_TCP_GETWRITE_COMMAND, m_pScheduler, SCHED_GRANULARITY);
  686.     }
  687.     m_bInDoGetWrite = FALSE;
  688.     return theErr;
  689. }
  690. HX_RESULT
  691. HXClientCloakedTCPSocket::DoPutWrite()
  692. {
  693.     HX_RESULT theErr = HXR_OK;
  694.     if (m_bInDoPutWrite)
  695.     {
  696. return HXR_OK;
  697.     }
  698.     m_bInDoPutWrite = TRUE;
  699.     /* Transfer pending buffers to TCP send queue */
  700.     if (m_bOptionsReceived && m_pPostEncodedSendHTTP->GetQueuedItemCount() == 0 && !m_bPutWantWritePending)
  701.     {
  702. TransferBuffers();
  703.     }
  704.     if (!m_bPutConnectDone)
  705.     {
  706. goto exit;
  707.     }
  708.     // check how data we have in TCP send queue
  709.     UINT16 count;
  710.     UINT16 actual;
  711.     
  712.     count    = m_pPostEncodedSendHTTP->GetQueuedItemCount();
  713.     actual   = count;
  714.     if(count > 0) 
  715.     {
  716. m_pPostEncodedSendHTTP->DeQueue(m_pOutEncodedBuf,count);
  717. CHXBuffer* pBuffer = new CHXBuffer;
  718. pBuffer->AddRef();
  719. pBuffer->Set((UCHAR*) m_pOutEncodedBuf, (ULONG32) count);
  720. theErr = m_pPutCtrl->Write(pBuffer);
  721. pBuffer->Release();
  722. m_bPutWantWritePending = TRUE;
  723. m_pPutCtrl->WantWrite();
  724.     }
  725.     
  726.     if (theErr)
  727.     {
  728. switch(theErr)
  729. {
  730.     case HXR_AT_INTERRUPT:
  731.     case HXR_WOULD_BLOCK:
  732. m_pPostEncodedSendHTTP->EnQueue(m_pOutEncodedBuf, count);
  733. // mask out these errors
  734. theErr = HXR_OK;
  735. break;
  736.     default:
  737. theErr = ConvertNetworkError(theErr);
  738. break;
  739. }
  740.     }
  741. exit:
  742.     if (!theErr && !m_bInDestructor &&
  743. (m_pPostEncodedSendHTTP->GetQueuedItemCount() > 0 ||
  744.  m_PendingWriteBuffers.GetCount() > 0)){
  745.     m_pSchedulerCallback->ScheduleCallback(CLOAKED_TCP_PUTWRITE_COMMAND, m_pScheduler, SCHED_GRANULARITY);
  746.     }
  747.     if (!theErr)
  748.     {
  749. theErr = DoGetWrite();
  750.     }
  751.     m_bInDoPutWrite = FALSE;
  752.     return theErr;
  753. }
  754. void 
  755. HXClientCloakedTCPSocket::GetConnectDone(BOOL bResult)
  756. {
  757.     m_bGetConnectDone = TRUE;
  758.     if (!m_bInDestructor)
  759.     {
  760. AddRef();
  761.     }
  762.     if (bResult == TRUE)
  763.     {
  764. m_bGetConnectSuccessful = TRUE;
  765. m_pGetCtrl->GetForeignAddress(m_lForeignAddress);
  766.     }
  767.     else
  768.     {
  769. m_bGetConnectSuccessful = FALSE;
  770.     }
  771.     // PUT connection has to been done at this point
  772.     if (m_bPutConnectDone && m_bConnectResponsePending)
  773.     {
  774. m_bConnectResponsePending = FALSE;
  775. // either its HTTP-NG server or we are in re-GET mode
  776. // where we send GET to the same serverIP returned from
  777. // POST response
  778. if (m_bConnectToSameServerIP || m_bReconnectToSameServerIP)
  779. {
  780.     if (m_bPutConnectSuccessful && m_bGetConnectSuccessful)
  781.     {
  782. m_bConnected = TRUE;
  783. m_pMutex->Lock();
  784. PrepareGetMessage();
  785. DoGetWrite();
  786. Read(TCP_BUF_SIZE);
  787. m_pMutex->Unlock();
  788. if (m_bConnectToSameServerIP)
  789. {
  790.     // we haven't call ConnectDone yet
  791.     m_pTCPResponse->ConnectDone(HXR_OK);
  792. }
  793. else if (m_bReconnectToSameServerIP)
  794. {
  795.     // we already called ConnectDone upon the initial
  796.     // GET/POST connect done
  797.     Read(TCP_BUF_SIZE);
  798. }
  799.     }
  800.     else
  801.     {
  802. m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
  803.     }
  804. }
  805. // don't know the server type yet, keep the old behavior
  806. // where we send both GET and POST
  807. else
  808. {
  809.     if (m_bPutConnectSuccessful && m_bGetConnectSuccessful)
  810.     {
  811. m_bConnected = TRUE;
  812. m_pMutex->Lock();
  813. PreparePostMessage(NULL, 0);
  814. DoPutWrite();
  815. PrepareGetMessage();
  816. DoGetWrite();
  817. m_pMutex->Unlock();
  818. m_pTCPResponse->ConnectDone(HXR_OK);
  819.     }
  820.     else
  821.     {
  822. m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
  823.     }
  824. }
  825.     }
  826.     if (!m_bInDestructor)
  827.     {
  828.         Release();
  829.     }
  830. }
  831. void 
  832. HXClientCloakedTCPSocket::PutConnectDone(BOOL bResult)
  833. {
  834.     HX_RESULT theErr = HXR_OK;
  835.     m_bPutConnectDone = TRUE;
  836.     if (!m_bInDestructor)
  837.     {
  838. AddRef();
  839.     }
  840.     if (bResult == TRUE)
  841.     {
  842. m_bPutConnectSuccessful = TRUE;
  843.     }
  844.     else
  845.     {
  846. m_bPutConnectSuccessful = FALSE;
  847.     }
  848.     // it's HTTP-NG server, we send POST first
  849.     if (m_bConnectToSameServerIP)
  850.     {
  851. if (m_bPutConnectSuccessful)
  852. {
  853.     m_pMutex->Lock();
  854.     PreparePostMessage(NULL, 0);
  855.     DoPutWrite();
  856.     if (!m_bPutReadPending)
  857.     {
  858. m_bPutReadPending = TRUE;
  859. m_pPutCtrl->Read(TCP_BUF_SIZE);
  860.     }
  861.     m_pMutex->Unlock();
  862. }
  863. else
  864. {
  865.     m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
  866. }
  867.     }
  868.     // don't know the server type yet, so we send both POST
  869.     // and GET
  870.     else if (m_bGetConnectDone && m_bConnectResponsePending)
  871.     {
  872. m_bConnectResponsePending = FALSE;
  873. if (m_bPutConnectSuccessful && m_bGetConnectSuccessful)
  874. {
  875.     m_bConnected = TRUE;
  876.     m_pMutex->Lock();
  877.     PreparePostMessage(NULL, 0);
  878.     DoPutWrite();
  879.     PrepareGetMessage();
  880.     theErr = DoGetWrite();
  881.     m_pMutex->Unlock();
  882.     m_pTCPResponse->ConnectDone(HXR_OK);
  883. }
  884. else
  885. {
  886.     m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
  887. }
  888.     }
  889.     if (!m_bInDestructor)
  890.     {
  891. Release();
  892.     }
  893.     if (m_bConnected && m_pPostEncodedSendHTTP->GetQueuedItemCount() > 0)
  894.     {
  895. m_pMutex->Lock();
  896. DoPutWrite();
  897. m_pMutex->Unlock();
  898.     }
  899. }
  900. HX_RESULT
  901. HXClientCloakedTCPSocket::DoGetReadDone(HX_RESULT   status, IHXBuffer* pInBuffer)
  902. {
  903.     HX_RESULT theErr = HXR_OK;
  904.     char* pStartAfterDoubleReturn = 0;
  905.     UINT16 count = 0;
  906.     if (AuthenticationRequired(status, pInBuffer))
  907.     {
  908. return HXR_OK;
  909.     }
  910.     m_pMutex->Lock();
  911.     m_bGetReadPending = FALSE;
  912.     if (status != HXR_OK && m_LastError == HXR_OK)
  913.     {
  914. m_LastError = status;
  915.     }
  916.     if (m_LastError)
  917.     {
  918. goto exit;
  919.     }
  920.     if (pInBuffer)
  921.     {
  922. m_pReceiveGetTCP->EnQueue(pInBuffer->GetBuffer(), (UINT16) pInBuffer->GetSize());
  923.     }
  924.     count = m_pReceiveGetTCP->GetQueuedItemCount();
  925.     /*
  926.      * if the 16k padding was not received in one big packet
  927.      * delete the remaining padding
  928.      */
  929.     if (m_bDeletePadding && m_uPadLength > 0)
  930.     {
  931. UINT16 len = (m_uPadLength <= count ? m_uPadLength : count); 
  932. BYTE* tmpBuf = new BYTE[len];
  933. m_pReceiveGetTCP->DeQueue(tmpBuf, len);
  934. m_uPadLength -= len;
  935. if (m_uPadLength == 0)
  936. {
  937.     m_bDeletePadding = FALSE;
  938. }
  939. HX_VECTOR_DELETE(tmpBuf);
  940. count = m_pReceiveGetTCP->GetQueuedItemCount();
  941.     }
  942.     if (!theErr && !m_bHTTPGetHeaderReadDone && count >= 2 )
  943.     {
  944. char* pEndLineLocation = 0;
  945. if (!m_pHTTPHeaderBuffer || m_nHTTPHeaderBufferLength < count+1)
  946. {
  947.     HX_VECTOR_DELETE(m_pHTTPHeaderBuffer);
  948.     m_nHTTPHeaderBufferLength = count+1 > DEFAULT_HTTP_HEADER_LENGTH ?
  949. count+1 : DEFAULT_HTTP_HEADER_LENGTH;
  950.     m_pHTTPHeaderBuffer = new char[m_nHTTPHeaderBufferLength];
  951.     if (!m_pHTTPHeaderBuffer)
  952.     {
  953. theErr = HXR_OUTOFMEMORY;
  954. goto exit;
  955.     }
  956. }
  957. m_pReceiveGetTCP->DeQueue(m_pHTTPHeaderBuffer, count);
  958. m_pHTTPHeaderBuffer[count] = '';
  959. if ((pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "nn")) ||
  960.     (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rr")) )
  961. {
  962.     pStartAfterDoubleReturn = pEndLineLocation+2;
  963.     m_bHTTPGetHeaderReadDone = TRUE;
  964. }
  965. else if (count >= 4 &&
  966.     (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rnrn")))
  967. {
  968.     pStartAfterDoubleReturn = pEndLineLocation+4;
  969.     m_bHTTPGetHeaderReadDone = TRUE;
  970. }
  971. else
  972. {
  973.     /* Put back everything in receive queue*/
  974.     m_pReceiveGetTCP->EnQueue(m_pHTTPHeaderBuffer, count);
  975.     goto exit;
  976. }
  977. // determine whether we need to issue re-GET to the same serverIP
  978. // from the POST response
  979. if (!m_bGetResponsed && !m_bConnectToSameServerIP)
  980. {
  981.     m_bGetResponsed = TRUE;
  982.     GetServerIPFromResponse(TRUE, m_pHTTPHeaderBuffer);
  983.     if (m_pszGetServerIP && m_pszPutServerIP)
  984.     {
  985. m_bReconnectToSameServerIP = strcasecmp(m_pszGetServerIP, m_pszPutServerIP);
  986.     }
  987.     if (m_bReconnectToSameServerIP)
  988.     {
  989. theErr = ReconnectToSameServerIP();
  990. goto quit;
  991.     }
  992. }
  993. /* If we have read the complete header, see if the content is OK..*/
  994. char* pFound = (char*) HXFindString(m_pHTTPHeaderBuffer, "HTTP/1.0 200 OK");
  995. if (!pFound)
  996. {
  997.     pFound = (char*) HXFindString(m_pHTTPHeaderBuffer, "200 OK");
  998. }
  999. // XXX HP we are phasing out PNM protocol
  1000. // m_pCloakValues is only set in RTSP so we use this to exclude
  1001. // support for redirect in PNM Cloaking
  1002. if (!pFound)
  1003. {
  1004.     if (m_pCloakValues)
  1005.     {
  1006. pFound = (char*) HXFindString(m_pHTTPHeaderBuffer, "HTTP/1.0 302");
  1007. if (pFound)
  1008. {
  1009.     strncpy(pFound, "RTSP", 4); /* Flawfinder: ignore */
  1010.     IHXBuffer* pBuffer = new CHXBuffer;
  1011.     pBuffer->AddRef();
  1012.     pBuffer->Set((UCHAR*) m_pHTTPHeaderBuffer, count);
  1013.     
  1014.     m_pTCPResponse->ReadDone(HXR_OK, pBuffer);
  1015.     pBuffer->Release();
  1016.     goto exit;
  1017. }
  1018.     }
  1019.     theErr = HXR_DOC_MISSING;
  1020. }
  1021. if (!theErr)
  1022. {
  1023.     m_pReceiveGetTCP->EnQueue(pStartAfterDoubleReturn, 
  1024.     (m_pHTTPHeaderBuffer + count) - pStartAfterDoubleReturn);
  1025.     
  1026.     count = m_pReceiveGetTCP->GetQueuedItemCount();
  1027. }
  1028.     }
  1029.     /* hmmm... time to read options */ 
  1030.     if (!theErr && count > 0 && !m_bOptionsReceived && m_bHTTPGetHeaderReadDone)
  1031.     {
  1032. /* There needs to be atleast 4 bytes to have the response
  1033.  * reponse_opcode(HTTP_RV_RESPONSE), response len, 
  1034.  * actual response(minimum one byte)
  1035.  */
  1036. if (count < 3)
  1037. {
  1038.     goto exit;
  1039. }
  1040. m_pReceiveGetTCP->DeQueue(m_pInBuf, count);
  1041. if (m_pInBuf[0] == HTTP_RESPONSE)
  1042. {
  1043.     m_bOptionsReceived = TRUE;
  1044.     
  1045.     UINT16 nOptionLen = m_pInBuf[1];
  1046.     /* Place any data after the response back in Receive queue.
  1047.      * This data needs to be sent to the user*/
  1048.     if (count > 2+nOptionLen)
  1049.     {
  1050. m_pReceiveGetTCP->EnQueue(m_pInBuf+2+nOptionLen, (count - (2+nOptionLen)));
  1051.     }
  1052.     theErr = HandleHTTPResponse((UCHAR) m_pInBuf[2]);
  1053.     if (!theErr)
  1054.     {
  1055. count = m_pReceiveGetTCP->GetQueuedItemCount();
  1056.     }
  1057. }
  1058. else if (m_pInBuf[0] == HTTP_RV_RESPONSE)
  1059. {
  1060.     if (count < 9)
  1061.     {
  1062. m_pReceiveGetTCP->EnQueue(m_pInBuf, count);
  1063. goto exit;
  1064.     }
  1065.     /*
  1066.      * this involves receiving a message from the server of the format:
  1067.      * HTTP/1.0 200 OK
  1068.      * ...
  1069.      * Content-length:2147483000
  1070.      * r...O?...16k padding of ZEROs...e
  1071.      *
  1072.      * r -- HTTP_RV_RESPONSE (same as the 5.0 player)
  1073.      * O -- HTTP_OPTION_RESPONSE
  1074.      * e -- HTTP_OPT_RESPONSE_END
  1075.      */
  1076.     BYTE* ptr = (BYTE *)m_pInBuf;
  1077.     m_bOptionsReceived = TRUE;
  1078.     
  1079.     ptr += 2;
  1080.     UINT16 nOptionLen = *ptr;
  1081.     ptr++;
  1082.     
  1083.     theErr = HandleHTTPResponse((UCHAR)*ptr);
  1084.     ptr++;
  1085.     if (!theErr)
  1086.     {
  1087. ptr++;  // get past the HTTP_OPTION_RESPONSE char 'O'
  1088. m_uPadLength = (UINT16)getshort(ptr); 
  1089. ptr += 2;
  1090. // skip over the short padding option
  1091. m_uPadLength += 1; // for the 'e' at the end of the 16k padding
  1092. m_pReceiveGetTCP->EnQueue(ptr, 
  1093.     (m_uPadLength <= (count - (ptr - (BYTE *)m_pInBuf)) 
  1094.     ? m_uPadLength : (count - (ptr - (BYTE *)m_pInBuf))));
  1095. count = m_pReceiveGetTCP->GetQueuedItemCount();
  1096. // get rid of the padding sent with the first response
  1097. UINT16 len = (m_uPadLength <= count ? m_uPadLength : count); 
  1098. BYTE* tmpBuf = new BYTE[len];
  1099. m_pReceiveGetTCP->DeQueue(tmpBuf, len);
  1100. m_uPadLength -= len;
  1101. if (m_uPadLength > 0)
  1102. {
  1103.     m_bDeletePadding = TRUE;
  1104. }
  1105. // if we got more than the 16k initial buffer, put it back
  1106. if (len && len < count)
  1107.     m_pReceiveGetTCP->EnQueue(&m_pInBuf[len], count-len);
  1108. HX_VECTOR_DELETE(tmpBuf);
  1109.      count = m_pReceiveGetTCP->GetQueuedItemCount();
  1110.     }
  1111. }
  1112. else
  1113. {
  1114.     theErr = HXR_BAD_SERVER;
  1115.     goto exit;
  1116. }
  1117.     }
  1118.     if (!theErr && m_bReadPending && count > 0 && m_bOptionsReceived 
  1119. && m_bHTTPGetHeaderReadDone)
  1120.     {
  1121. /* mask any kind of errors */
  1122. theErr = HXR_OK;
  1123. if (IsSafe())
  1124. {
  1125.     m_bReadPending = FALSE;
  1126.     if (m_nRequired < count)
  1127.     {
  1128. count = m_nRequired;
  1129.     }
  1130.     CHXBuffer* pBuffer = new CHXBuffer;
  1131.     pBuffer->AddRef();
  1132.     m_pReceiveGetTCP->DeQueue(m_pInBuf, count);
  1133.     pBuffer->Set((UCHAR*) m_pInBuf, count);
  1134.     
  1135.     m_pTCPResponse->ReadDone(HXR_OK, pBuffer);
  1136.     pBuffer->Release();
  1137. }
  1138.     }
  1139. exit:
  1140.     if (theErr && !m_LastError)
  1141.     {
  1142. m_LastError = theErr;
  1143.     }
  1144.     if (m_LastError)
  1145.     {
  1146. if (m_bReadPending)
  1147. {
  1148.     if (IsSafe())
  1149.     {
  1150. m_bReadPending = FALSE;
  1151. m_pTCPResponse->ReadDone(m_LastError, 0);
  1152.     }
  1153. }
  1154.     }
  1155.     if (!m_LastError)
  1156.     {
  1157. DoPutWrite();
  1158. DoRead();
  1159.     }
  1160. quit:
  1161.     m_pMutex->Unlock();
  1162.     return HXR_OK;
  1163. }
  1164. HX_RESULT
  1165. HXClientCloakedTCPSocket::DoPutReadDone(HX_RESULT   status, IHXBuffer* pInBuffer)
  1166. {
  1167.     HX_RESULT rc = HXR_OK;
  1168.     UINT16 count = 0;
  1169.     m_bPutReadPending = FALSE;
  1170.     if (HXR_OK != status)
  1171.     {
  1172. rc = status;
  1173. goto cleanup;
  1174.     }
  1175.     // stop processing either we already processed one PUT response or
  1176.     // we are in multi-post mode
  1177.     if (!m_bPutResponsed && !m_bMustCloseHTTP)
  1178.     {
  1179. if (!m_pReceivePutTCP)
  1180. {
  1181.     m_pReceivePutTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
  1182.     if (!m_pReceivePutTCP || !m_pReceivePutTCP->IsQueueValid())
  1183.     {
  1184. rc = HXR_OUTOFMEMORY;
  1185. goto cleanup;
  1186.     }
  1187.     m_pReceivePutTCP->SetMaxSize(TCP_BUF_SIZE);
  1188. }
  1189. if (pInBuffer)
  1190. {
  1191.     m_pReceivePutTCP->EnQueue(pInBuffer->GetBuffer(), (UINT16) pInBuffer->GetSize());
  1192. }
  1193. count = m_pReceivePutTCP->GetQueuedItemCount();
  1194. if (count >= 2)
  1195. {
  1196.     char* pEndLineLocation = 0;
  1197.     if (!m_pHTTPHeaderBuffer || m_nHTTPHeaderBufferLength < count+1)
  1198.     {
  1199. HX_VECTOR_DELETE(m_pHTTPHeaderBuffer);
  1200. m_nHTTPHeaderBufferLength = count+1 > DEFAULT_HTTP_HEADER_LENGTH ?
  1201.     count+1 : DEFAULT_HTTP_HEADER_LENGTH;
  1202. m_pHTTPHeaderBuffer = new char[m_nHTTPHeaderBufferLength];
  1203. if (!m_pHTTPHeaderBuffer)
  1204. {
  1205.     rc = HXR_OUTOFMEMORY;
  1206.     goto cleanup;
  1207. }
  1208.     }
  1209.     m_pReceivePutTCP->DeQueue(m_pHTTPHeaderBuffer, count);
  1210.     m_pHTTPHeaderBuffer[count] = '';
  1211.     if ((pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "nn")) ||
  1212.      (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rr")) )
  1213.     {
  1214. m_bHTTPPutHeaderReadDone = TRUE;
  1215.     }
  1216.     else if (count >= 4 &&
  1217.     (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rnrn")))
  1218.     {
  1219. m_bHTTPPutHeaderReadDone = TRUE;
  1220.     }
  1221.     else
  1222.     {
  1223. /* Put back everything in receive queue*/
  1224. m_pReceivePutTCP->EnQueue(m_pHTTPHeaderBuffer, count);
  1225. goto cleanup;
  1226.     }
  1227.     m_bPutResponsed = TRUE;
  1228.     GetServerIPFromResponse(FALSE, m_pHTTPHeaderBuffer);
  1229.     if (m_bConnectToSameServerIP)
  1230.     {
  1231. rc = ActualConnect();
  1232.     }
  1233.     else
  1234.     {
  1235. if (m_pszPutServerIP && m_pPreferredTransport)
  1236. {
  1237.     m_pPreferredTransport->SetHTTPNG(TRUE);
  1238. }
  1239. // determine whether we need to issue re-GET to the same serverIP
  1240. // from the POST response
  1241. if (m_pszGetServerIP && m_pszPutServerIP)
  1242. {
  1243.     m_bReconnectToSameServerIP = strcasecmp(m_pszGetServerIP, m_pszPutServerIP);
  1244. }
  1245. if (m_bReconnectToSameServerIP)
  1246. {
  1247.     rc = ReconnectToSameServerIP();
  1248. }
  1249.     }
  1250. }
  1251.     }
  1252. cleanup:
  1253.     return rc;
  1254. }
  1255. void
  1256. HXClientCloakedTCPSocket::TransferBuffers()
  1257. {
  1258.     IHXBuffer* pBuffer = 0;
  1259.     HX_RESULT theErr = HXR_OK;
  1260.     if (m_bInTransferBuffers)
  1261.     {
  1262. return;
  1263.     }
  1264.     m_bInTransferBuffers = TRUE;
  1265.     /*This is where we need to add POST header for multiple POST case*/
  1266.     while (m_PendingWriteBuffers.GetCount() > 0)
  1267.     {
  1268. pBuffer = (IHXBuffer*) m_PendingWriteBuffers.GetHead();
  1269. if ((UINT16) pBuffer->GetSize() < m_pPreEncodedSendHTTP->GetMaxAvailableElements())
  1270. {
  1271.     m_pPreEncodedSendHTTP->EnQueue(pBuffer->GetBuffer(), 
  1272. (UINT16) pBuffer->GetSize());
  1273.     pBuffer->Release();
  1274.     m_PendingWriteBuffers.RemoveHead();
  1275. }
  1276. else
  1277. {
  1278.     break;
  1279. }
  1280.     }
  1281.     UINT16 nCount = m_pPreEncodedSendHTTP->GetQueuedItemCount();
  1282.     if (nCount > 0)
  1283.     {
  1284. if (m_bCloseHttpAfterWrite)
  1285. {
  1286.     ENQUEUE_BYTE(m_pPreEncodedSendHTTP, HTTP_POSTDONE);
  1287.     nCount++;
  1288. }
  1289. if (m_bMustCloseHTTP && m_pPutCtrl)
  1290. {
  1291.     m_pPutCtrl->Release();
  1292.     m_pPutCtrl = 0;
  1293.     m_bPutConnectDone = FALSE;
  1294.     m_pNetworkServices->CreateTCPSocket(&m_pPutCtrl);
  1295.     if (!m_pPutCtrl)
  1296.     {
  1297. m_LastError = HXR_OUTOFMEMORY;
  1298. m_bInTransferBuffers = FALSE;
  1299. return;
  1300.     }
  1301.     m_pPutCtrl->Init(m_pPutCtrlResponse);
  1302.     const char* pActualHost = m_pForiegnHost;
  1303.     UINT16  nActualPort = m_nForeignPort;
  1304.     if (m_pProxyHostName)
  1305.     {
  1306. pActualHost = m_pProxyHostName;
  1307. nActualPort = m_nProxyPortNumber;
  1308.     }
  1309.     m_pPutCtrl->Connect(pActualHost,nActualPort);
  1310. }
  1311. m_pPreEncodedSendHTTP->DeQueue(m_pOutBuf, nCount);
  1312. UINT16 nEncodedCount = TCP_BUF_SIZE;
  1313. EncodeBase64((UCHAR*) m_pOutBuf, nCount, (UCHAR*) m_pOutEncodedBuf, nEncodedCount);
  1314.         HX_ASSERT(nEncodedCount <= TCP_BUF_SIZE);
  1315. if (m_bCloseHttpAfterWrite)
  1316. {
  1317.     theErr = PreparePostMessage((UCHAR*) m_pOutEncodedBuf, nEncodedCount);
  1318. }
  1319. else
  1320. {
  1321.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,m_pOutEncodedBuf, nEncodedCount);
  1322. }
  1323.     }
  1324.     m_bInTransferBuffers = FALSE;
  1325. }
  1326. /***************************General routines*******/
  1327. HX_RESULT
  1328. HXClientCloakedTCPSocket::PreparePostMessage(const UCHAR *inData, UINT16 inLength) 
  1329. {
  1330.     HX_RESULT theErr = HXR_OK;
  1331.     int count = 0;
  1332.     UINT16 postLength = inLength;
  1333.     
  1334.     // create a temp buffer to help build the HTTP POST message
  1335.     char* s = new char[MAX_HTTP_METHOD_BUFSIZE];
  1336.     if(s == NULL)
  1337.     {
  1338. return HXR_OUTOFMEMORY;
  1339.     }
  1340.     // build the HTTP POST message
  1341.     if(m_pProxyHostName)
  1342.     {
  1343. if (m_nForeignPort)
  1344. {
  1345.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"POST http://%s:%d/SmpDsBhgRl",m_pForiegnHost, m_nForeignPort);
  1346. }
  1347. else
  1348. {
  1349.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"POST http://%s/SmpDsBhgRl",m_pForiegnHost);
  1350. }
  1351.     }
  1352.     else
  1353.     {
  1354. //count = sprintf(s,"POST /SmpDsBhgRl"); /* Flawfinder: ignore */
  1355. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"POST /SmpDsBhgRl"); /* Flawfinder: ignore */
  1356.     }
  1357.     
  1358.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1359.     // enqueue the remainder of the POST line
  1360.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE," HTTP/1.0rn"); /* Flawfinder: ignore */
  1361.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1362.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"User-Agent: RealPlayer G2rn"); /* Flawfinder: ignore */
  1363.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1364.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Pragma: no-cachern"); /* Flawfinder: ignore */
  1365.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1366.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Expires: Mon, 18 May 1974 00:00:00 GMTrn"); /* Flawfinder: ignore */
  1367.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1368.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Accept: application/x-rtsp-tunnelled, */*rn"); /* Flawfinder: ignore */
  1369.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1370.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Content-type: application/x-pncmdrn"); /* Flawfinder: ignore */
  1371.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1372.     CHXString strAuth;
  1373.     ObtainAuthenticationInformation(strAuth);
  1374.     
  1375.     if (!strAuth.IsEmpty())
  1376.     {
  1377. strAuth += "rn";    
  1378. ENQUEUE_DATA(m_pPostEncodedSendHTTP, (void*)(const char*)strAuth, 
  1379.      (UINT16)strAuth.GetLength());
  1380.     }
  1381.     UINT16 guidSize = ::strlen(m_pGuid);
  1382.     if(m_bUseExactContentLength)
  1383.     {
  1384. // add in the size of the GUID (which was not base64 encoded)
  1385. postLength += guidSize + 2; // 2 is for the rn at the end of the GUID!
  1386. // we must report the exact size of the post data in the Content-length parameter
  1387. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Content-length: %hurn",postLength); /* Flawfinder: ignore */
  1388.     }
  1389.     else
  1390.     {
  1391. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Content-length: 32767rn"); /* Flawfinder: ignore */
  1392.     }
  1393.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1394.     // enqueue the CR LF to indicate end of the POST header
  1395.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"rn"); /* Flawfinder: ignore */
  1396.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1397.     // enqueue the GUID (Must be sent with every POST and not base64 encoded)
  1398.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,&m_pGuid[0],guidSize);
  1399.     
  1400.     // enqueue the CR LF to indicate end of the GUID
  1401.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"rn"); /* Flawfinder: ignore */
  1402.     ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
  1403.     if(inLength > 0)
  1404.     {
  1405. // enqueue the actual POST data
  1406. ENQUEUE_DATA(m_pPostEncodedSendHTTP,(char *)inData,inLength);
  1407.     }
  1408.     
  1409.     // clean up allocated buffers
  1410.     if(s)
  1411.     {
  1412. delete [] s;
  1413.     }
  1414.     return theErr;
  1415. }
  1416. HX_RESULT
  1417. HXClientCloakedTCPSocket::PrepareGetMessage(void) 
  1418. {
  1419.     HX_RESULT theErr = HXR_OK;
  1420.     IHXBuffer* pBuffer = NULL;
  1421.     // create a temp buffer for the HTTP GET message
  1422.     char* s = new char[MAX_HTTP_METHOD_BUFSIZE];
  1423.     
  1424.     if(s == NULL)
  1425.     {
  1426. theErr = HXR_OUTOFMEMORY;
  1427.     }
  1428.     
  1429.     /* Flush any prior data in the send queue */
  1430.     m_pSendTCP->FlushQueue();
  1431.     /* Create a fresh GUID */
  1432.     CreateGuid();
  1433.     // format the HTTP GET message
  1434.     if(!theErr)
  1435.     {
  1436. int count = 0;
  1437. // build the HTTP POST message
  1438. if(m_pProxyHostName)
  1439. {   
  1440.     if (m_nForeignPort)
  1441.     {
  1442. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"GET http://%s:%d/SmpDsBhgRl",m_pForiegnHost, m_nForeignPort);
  1443.     }
  1444.     else
  1445.     {
  1446. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"GET http://%s/SmpDsBhgRl",m_pForiegnHost);
  1447.     }
  1448. }
  1449. else
  1450. {
  1451.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"GET /SmpDsBhgRl"); /* Flawfinder: ignore */
  1452. }
  1453. ENQUEUE_DATA(m_pSendTCP,s,count);
  1454. #if 0 // XXX HP enable this to test re-GET after initial GET/POST response 
  1455. // returned with different serverIP
  1456. if (!m_bReconnectToSameServerIP)
  1457. {
  1458.     char* pGuid = new char[strlen(m_pGuid)+1];
  1459.     memcpy(pGuid, m_pGuid, strlen(m_pGuid)); /* Flawfinder: ignore */
  1460.     pGuid[0] = 'z';
  1461.     // enqueue the GUID directly after the SmpDsBhgRl tag
  1462.     ENQUEUE_DATA(m_pSendTCP,&pGuid[0],::strlen(pGuid));
  1463.     HX_VECTOR_DELETE(pGuid);
  1464. }
  1465. else
  1466. #endif
  1467. {
  1468.     // enqueue the GUID directly after the SmpDsBhgRl tag
  1469.     ENQUEUE_DATA(m_pSendTCP,&m_pGuid[0],::strlen(m_pGuid));
  1470. }
  1471. if (m_pProxyHostName)
  1472. {
  1473.     /* 
  1474.      * enqueue dummy option to tell the server to send a padding
  1475.      * of 16k of ZEROs with the first response
  1476.      */
  1477.     count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"?1="1""); /* Flawfinder: ignore */
  1478.     ENQUEUE_DATA(m_pSendTCP,s,count);
  1479. }
  1480. // enqueue the HTTP 1.0 and CR LF
  1481. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE," HTTP/1.0rn"); /* Flawfinder: ignore */
  1482. ENQUEUE_DATA(m_pSendTCP,s,count);
  1483. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"User-Agent: RealPlayer G2rn"); /* Flawfinder: ignore */
  1484. ENQUEUE_DATA(m_pSendTCP,s,count);
  1485. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Expires: Mon, 18 May 1974 00:00:00 GMTrn"); /* Flawfinder: ignore */
  1486. ENQUEUE_DATA(m_pSendTCP,s,count);
  1487. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Pragma: no-cachern"); /* Flawfinder: ignore */
  1488. ENQUEUE_DATA(m_pSendTCP,s,count);
  1489. count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Accept: application/x-rtsp-tunnelled, */*rn"); /* Flawfinder: ignore */
  1490. ENQUEUE_DATA(m_pSendTCP,s,count);
  1491. CHXString strAuth;
  1492. ObtainAuthenticationInformation(strAuth);
  1493. if (!strAuth.IsEmpty())
  1494. {
  1495.     strAuth += "rn";    
  1496.     ENQUEUE_DATA(m_pSendTCP, (void*)(const char*)strAuth, 
  1497.  (UINT16)strAuth.GetLength());
  1498. }
  1499. // send client information so that GoldPass Admin
  1500. // can generate redirect URL via HTTPCloaking
  1501. if (m_pCloakValues)
  1502. {
  1503.     if (HXR_OK == m_pCloakValues->GetPropertyCString("ClientID", pBuffer))
  1504.     {
  1505. UINT32 ulNewSize = pBuffer->GetSize()+25;
  1506. s = (char*)realloc(s, ulNewSize);
  1507.                 if(s)
  1508.                 {
  1509.                     count = SafeSprintf(s,ulNewSize,"ClientID: %srn", pBuffer->GetBuffer()); /* Flawfinder: ignore */
  1510.                     ENQUEUE_DATA(m_pSendTCP,s,count);
  1511.                 }
  1512.                 else
  1513.                 {
  1514.                     theErr = HXR_OUTOFMEMORY;
  1515.                 }
  1516.                 
  1517.     }
  1518.     HX_RELEASE(pBuffer);
  1519.     if (HXR_OK == m_pCloakValues->GetPropertyCString("Cookie", pBuffer))
  1520.     {
  1521. UINT32 ulNewSize = pBuffer->GetSize()+25;
  1522. s = (char*)realloc(s, ulNewSize);
  1523.                 if(s)
  1524.                 {
  1525.                     count = SafeSprintf(s,ulNewSize,"Cookie: %srn", pBuffer->GetBuffer()); /* Flawfinder: ignore */
  1526.                     ENQUEUE_DATA(m_pSendTCP,s,count);
  1527.                 }
  1528.                 else
  1529.                 {
  1530.                     theErr = HXR_OUTOFMEMORY;
  1531.                 }
  1532.             }
  1533.     HX_RELEASE(pBuffer);
  1534.     if (HXR_OK == m_pCloakValues->GetPropertyCString("url", pBuffer))
  1535.     {
  1536. UINT32 ulNewSize = pBuffer->GetSize()+25;
  1537.                 s = (char*)realloc(s, ulNewSize);
  1538.                 if(s)
  1539.                 {
  1540.                     count = SafeSprintf(s,ulNewSize,"X-Actual-URL: %srn", pBuffer->GetBuffer()); /* Flawfinder: ignore */
  1541.                     ENQUEUE_DATA(m_pSendTCP,s,count);
  1542.                 }
  1543.                 else
  1544.                 {
  1545.                     theErr = HXR_OUTOFMEMORY;
  1546.                 }
  1547.     }
  1548.     HX_RELEASE(pBuffer);
  1549. }
  1550. // enqueue the CR LF to indicate the end of the HTTP GET header
  1551.         s = (char*)realloc(s, 25);
  1552.         if(s)
  1553.         {
  1554.             count = SafeSprintf(s,25,"rn"); /* Flawfinder: ignore */
  1555.             ENQUEUE_DATA(m_pSendTCP,s,count);
  1556.         }
  1557.         else
  1558.         {
  1559.             theErr = HXR_OUTOFMEMORY;
  1560.         }
  1561.     }
  1562.     
  1563.     // clean up
  1564.     HX_DELETE(s);
  1565.     
  1566.     return theErr;
  1567. }
  1568. void
  1569. HXClientCloakedTCPSocket::CreateGuid(void)
  1570. {
  1571.     CHXuuid theGuid;
  1572.     uuid_tt uuid;
  1573.     
  1574.     if (m_pGuid)
  1575.     {
  1576. return;
  1577.     }
  1578.     if(m_pGuid)
  1579.     {
  1580. delete [] m_pGuid;
  1581. m_pGuid = NULL;
  1582.     }
  1583.     
  1584.     // generate a new GUID
  1585.     HX_RESULT theErr = theGuid.GetUuid(&uuid);
  1586. //    HX_RESULT theErr = HXR_OK;
  1587.     if(!theErr)
  1588.     {
  1589. CHXString theString;
  1590. CHXuuid::HXUuidToString((const uuid_tt*)&uuid,&theString);
  1591. int length = theString.GetLength();
  1592. m_pGuid = new char[length + 1];
  1593. if(!m_pGuid)
  1594. {
  1595. theErr = HXR_OUTOFMEMORY;
  1596. }
  1597. if(!theErr)
  1598. {
  1599. ::strcpy(m_pGuid,(const char *)theString); /* Flawfinder: ignore */
  1600. m_pGuid[length] = '';
  1601. }
  1602. if(theErr && m_pGuid)
  1603. {
  1604. delete [] m_pGuid;
  1605. m_pGuid = NULL;
  1606. }
  1607.     }
  1608.     
  1609.     if(theErr)  // use our own GUID generator
  1610.     {
  1611. theErr = HXR_OK;
  1612. ULONG32 temp = HX_GET_TICKCOUNT();
  1613. if(m_pGuid)
  1614. {
  1615.     delete [] m_pGuid;
  1616.     m_pGuid = NULL;
  1617. }
  1618.     
  1619. m_pGuid = new char[HXGUID_SIZE + 1];
  1620. UINT16 length = SafeSprintf(m_pGuid,HXGUID_SIZE + 1,"%ld",temp);
  1621. while(length < HXGUID_SIZE)
  1622. {
  1623. m_pGuid[length++] = '1';
  1624. }
  1625. m_pGuid[HXGUID_SIZE] = '';
  1626.     }
  1627. }
  1628. HX_RESULT 
  1629. HXClientCloakedTCPSocket::EncodeBase64(const UCHAR* inData, UINT16 inLength, UCHAR* outData, UINT16& outLength)
  1630. {
  1631.     HX_RESULT theErr = HXR_OK;
  1632.     
  1633.     HX_ASSERT(inData != NULL);
  1634.     HX_ASSERT(outData != NULL);
  1635.     HX_ASSERT(inLength != 0);
  1636.     
  1637.     // first base64 encode the buffer
  1638.     outLength = (UINT16) BinTo64((const UCHAR*) inData, (ULONG32) inLength,(char *)outData);
  1639.     HX_ASSERT(outLength >= inLength);
  1640.     return HXR_OK;
  1641. }
  1642. HX_RESULT
  1643. HXClientCloakedTCPSocket::HandleHTTPResponse(UCHAR response)
  1644. {
  1645.     HX_RESULT theErr = HXR_OK;
  1646.     
  1647.     switch(response)
  1648.     {
  1649. case HTTP_OK:
  1650. {
  1651.     m_bUseExactContentLength = FALSE;
  1652.     m_bCloseHttpAfterWrite = FALSE;
  1653.     m_bHttpInitialized = TRUE;
  1654.     /*force a write of the cached data to be sent to the server*/
  1655. //     theErr = control_write();
  1656. }
  1657. break;
  1658. case POST_NOT_RECEIVED: // POST message was not received
  1659. {
  1660.     if (m_pszGetServerIP)
  1661.     {
  1662. HX_VECTOR_DELETE(m_pForiegnHost);
  1663. // use serverIP from GET response for multi-POST
  1664. m_pForiegnHost = new char [strlen(m_pszGetServerIP) + 1];
  1665. if (m_pForiegnHost)
  1666. {
  1667.     ::strcpy(m_pForiegnHost, m_pszGetServerIP); /* Flawfinder: ignore */
  1668. }
  1669. else
  1670. {
  1671.     theErr = HXR_OUTOFMEMORY;
  1672. }
  1673.     }
  1674.  
  1675.     m_bUseExactContentLength = TRUE;
  1676.     m_bCloseHttpAfterWrite = TRUE;
  1677.     m_bHttpInitialized = TRUE;
  1678.     m_bMustCloseHTTP = TRUE;
  1679.     /*force a write of the cached data to be sent to the server*/
  1680. //     theErr = control_write();
  1681. }
  1682. break;
  1683. case INVALID_GUID: 
  1684. {
  1685.     /* sent only if the GUID from the Player is already in use
  1686.      * Need to regenerate GUID and send everything again
  1687.      */
  1688.     /// TBD - Rahul     
  1689.     if (m_pGuid)
  1690.     {
  1691. delete [] m_pGuid;
  1692. m_pGuid = 0;
  1693.     }
  1694.     PrepareGetMessage();
  1695.     theErr = DoGetWrite();
  1696. }
  1697. break;
  1698. default:
  1699. {
  1700.     // shut this clip down and report an appropriate error
  1701.     theErr = HXR_HTTP_CONTENT_NOT_FOUND;
  1702. }
  1703. break;
  1704.     }
  1705.     
  1706.     return theErr;
  1707. }
  1708. /* If we are at interrupt time and the response object is not interrupt safe,
  1709.  * schedule a callback to return back the data
  1710.  */
  1711. BOOL
  1712. HXClientCloakedTCPSocket::IsSafe()
  1713. {
  1714.     if (m_pInterruptState && m_pInterruptState->AtInterruptTime() && 
  1715. (!m_pResponseInterruptSafe || 
  1716.  !m_pResponseInterruptSafe->IsInterruptSafe()))
  1717.     {
  1718. if (m_pNonInterruptCallback){
  1719.     m_pNonInterruptCallback->ScheduleCallback(CLOAKED_TCP_READ_COMMAND, m_pScheduler, 0);
  1720. }
  1721. return FALSE;
  1722.     }
  1723.     return TRUE;
  1724. }
  1725. void
  1726. HXClientCloakedTCPSocket::FlushQueues(void)
  1727. {
  1728.     if (m_pSendTCP)
  1729.     {
  1730. m_pSendTCP->FlushQueue();
  1731.     }
  1732.     if (m_pReceiveGetTCP)
  1733.     {
  1734. m_pReceiveGetTCP->FlushQueue();
  1735.     }
  1736.     if (m_pReceivePutTCP)
  1737.     {
  1738. m_pReceivePutTCP->FlushQueue();
  1739.     }
  1740.     if (m_pPreEncodedSendHTTP)
  1741.     {
  1742. m_pPreEncodedSendHTTP->FlushQueue();
  1743.     }
  1744.     if (m_pPostEncodedSendHTTP)
  1745.     {
  1746. m_pPostEncodedSendHTTP->FlushQueue();
  1747.     }
  1748. }
  1749. void
  1750. HXClientCloakedTCPSocket::SendHTTPDone(void)
  1751. {
  1752.     CHXBuffer* pBuffer = new CHXBuffer;
  1753.     pBuffer->AddRef();
  1754.     BYTE http_done = HTTP_DONE;
  1755.     pBuffer->Set((UCHAR*) &http_done, 1);
  1756.     m_PendingWriteBuffers.AddTail((void*) pBuffer);
  1757.     TransferBuffers();
  1758.     DoPutWrite();
  1759. }
  1760. HX_RESULT
  1761. HXClientCloakedTCPSocket::ActualConnect(void)
  1762. {
  1763.     HX_RESULT rc = HXR_OK;
  1764.     const char* pActualHost = m_pForiegnHost;
  1765.     UINT16  nActualPort = m_nForeignPort;
  1766.     if (m_pProxyHostName)
  1767.     {
  1768. pActualHost = m_pProxyHostName;
  1769. nActualPort = m_nProxyPortNumber;
  1770.     }
  1771.     if (m_bConnectToSameServerIP)
  1772.     {
  1773. if (m_bPutConnectSuccessful)
  1774. {
  1775.     rc = m_pGetCtrl->Connect(pActualHost,nActualPort);
  1776. }
  1777. else
  1778. {
  1779.     rc = m_pPutCtrl->Connect(pActualHost,nActualPort);
  1780. }
  1781. rc = ConvertNetworkError(rc);
  1782.     }
  1783.     else
  1784.     {
  1785. rc = m_pGetCtrl->Connect(pActualHost,nActualPort);
  1786. rc = ConvertNetworkError(rc);
  1787. if (rc == HXR_OK && !m_bReconnectToSameServerIP)
  1788. {
  1789.     rc = m_pPutCtrl->Connect(pActualHost,nActualPort);
  1790.     rc = ConvertNetworkError(rc);
  1791. }
  1792.     }
  1793.     return rc;
  1794. }
  1795. HX_RESULT
  1796. HXClientCloakedTCPSocket::GetServerIPFromResponse(BOOL bGetResponse, const char* pszInBuffer)
  1797. {
  1798.     HX_RESULT rc = HXR_OK;
  1799.     UINT8 nLength = 0;
  1800.     char* pszServerIPStart = NULL;    
  1801.     char* pszServerIPEnd = NULL;
  1802.     char* pszServerIP = NULL;
  1803.     if (!pszInBuffer)
  1804.     {
  1805. rc = HXR_FAILED;
  1806. goto cleanup;
  1807.     }
  1808.     pszServerIPStart = (char*)HXFindString(pszInBuffer, "x-server-ip-address:");
  1809.     if (pszServerIPStart)
  1810.     {
  1811. pszServerIPStart += strlen("x-server-ip-address:");
  1812. // removing leading spaces
  1813. while (*pszServerIPStart == ' ')
  1814. {
  1815.     pszServerIPStart++;
  1816. }
  1817. pszServerIPEnd = (char*)HXFindString(pszServerIPStart, "rn");
  1818. if (pszServerIPEnd)
  1819. {
  1820.     nLength = pszServerIPEnd - pszServerIPStart;
  1821.     pszServerIP = new char[nLength + 1];
  1822.     memset(pszServerIP, 0, nLength + 1);
  1823.     strncpy(pszServerIP, pszServerIPStart, nLength); /* Flawfinder: ignore */
  1824.     if (bGetResponse)
  1825.     {
  1826. HX_VECTOR_DELETE(m_pszGetServerIP);
  1827. m_pszGetServerIP = pszServerIP;
  1828.     }
  1829.     else
  1830.     {
  1831. HX_VECTOR_DELETE(m_pszPutServerIP);
  1832. m_pszPutServerIP = pszServerIP;
  1833.     }
  1834. }
  1835.     }
  1836. cleanup:
  1837.     return rc;
  1838. }
  1839. HX_RESULT
  1840. HXClientCloakedTCPSocket::CleanUpAndReInitializeStuff(void)
  1841. {
  1842.     HX_RESULT rc = HXR_OK;
  1843.     IHXBuffer* pBuffer = NULL;
  1844.     m_pMutex->Lock();
  1845.     const char* pActualHost = m_pForiegnHost;
  1846.     UINT16  nActualPort = m_nForeignPort;
  1847.     if (m_pProxyHostName)
  1848.     {
  1849. pActualHost = m_pProxyHostName;
  1850. nActualPort = m_nProxyPortNumber;
  1851.     }
  1852.     if (m_pReceiveGetTCP)
  1853.     {
  1854. m_pReceiveGetTCP->FlushQueue();
  1855.     }
  1856.     /* Send a final HTTP done message */
  1857.     if (m_bHttpInitialized)
  1858.     {
  1859. SendHTTPDone();
  1860.     }
  1861.     if (m_pSchedulerCallback)
  1862.     {
  1863. m_pSchedulerCallback->Unschedule(m_pScheduler);
  1864.     }
  1865.     if (m_pNonInterruptCallback)
  1866.     {
  1867. m_pNonInterruptCallback->Unschedule(m_pScheduler);
  1868.     }
  1869.     HX_RELEASE(m_pGetCtrl);
  1870.     HX_RELEASE(m_pPutCtrl);
  1871.     
  1872.     m_bHTTPGetHeaderReadDone = FALSE;
  1873.     m_bOptionsReceived = FALSE;
  1874.     m_bReadPending = FALSE;
  1875.     m_bGetReadPending = FALSE;
  1876.     m_bGetConnectDone = FALSE;
  1877.     m_bGetConnectSuccessful = FALSE;
  1878.     m_bConnectResponsePending = TRUE;
  1879.     m_bConnected = FALSE;
  1880.     m_bPutConnectDone = FALSE;
  1881.     m_bPutReadPending = FALSE;
  1882.     m_bInAuthenticationKludge = TRUE;
  1883.     
  1884.     // OK, clean up is done so now we re-initialize.
  1885.     
  1886.     
  1887.     // use serverIP from PUT response for GET reconnect
  1888.     
  1889.     if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pGetCtrl))
  1890.     {
  1891. rc = HXR_FAILED;
  1892. goto cleanup;
  1893.     }
  1894.     if (HXR_OK != m_pGetCtrl->Init(m_pGetCtrlResponse))
  1895.     {
  1896. rc = HXR_FAILED;
  1897. goto cleanup;
  1898.     }
  1899.     if (HXR_OK != m_pGetCtrl->Bind(HXR_INADDR_ANY, 0))
  1900.     {
  1901. rc = HXR_FAILED;
  1902. goto cleanup;
  1903.     }
  1904.     
  1905.     rc = m_pGetCtrl->Connect(pActualHost, nActualPort);    
  1906.     if (HXR_OK != rc)
  1907.     {
  1908. goto cleanup;
  1909.     }
  1910.     if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pPutCtrl))
  1911.     {
  1912. rc = HXR_FAILED;
  1913. goto cleanup;
  1914.     }
  1915.     if (HXR_OK != m_pPutCtrl->Init(m_pPutCtrlResponse))
  1916.     {
  1917. rc = HXR_FAILED;
  1918. goto cleanup;
  1919.     }
  1920.     if (HXR_OK != m_pPutCtrl->Bind(HXR_INADDR_ANY, 0))
  1921.     {
  1922. rc = HXR_FAILED;
  1923. goto cleanup;
  1924.     }
  1925.     rc = m_pPutCtrl->Connect(pActualHost, nActualPort);
  1926.     if (HXR_OK != rc) goto cleanup;
  1927. cleanup:
  1928.     m_pMutex->Unlock();
  1929.     return rc;
  1930. }
  1931. HX_RESULT
  1932. HXClientCloakedTCPSocket::ReconnectToSameServerIP(void)
  1933. {
  1934.     HX_RESULT rc = HXR_OK;
  1935.     IHXBuffer* pBuffer = NULL;
  1936.     m_pMutex->Lock();
  1937.     if (m_pReceiveGetTCP)
  1938.     {
  1939. m_pReceiveGetTCP->FlushQueue();
  1940.     }
  1941.     /* Send a final HTTP done message */
  1942.     if (m_bHttpInitialized)
  1943.     {
  1944. SendHTTPDone();
  1945.     }
  1946.     if (m_pSchedulerCallback)
  1947.     {
  1948. m_pSchedulerCallback->Unschedule(m_pScheduler);
  1949.     }
  1950.     if (m_pNonInterruptCallback)
  1951.     {
  1952. m_pNonInterruptCallback->Unschedule(m_pScheduler);
  1953.     }
  1954.     HX_RELEASE(m_pGetCtrl);
  1955.     HX_RELEASE(m_pGetCtrlResponse);
  1956.     
  1957.     m_bHTTPGetHeaderReadDone = FALSE;
  1958.     m_bOptionsReceived = FALSE;
  1959.     m_bReadPending = FALSE;
  1960.     m_bGetReadPending = FALSE;
  1961.     m_bGetConnectDone = FALSE;
  1962.     m_bGetConnectSuccessful = FALSE;
  1963.     m_bConnectResponsePending = TRUE;
  1964.     m_bConnected = FALSE;
  1965.     HX_VECTOR_DELETE(m_pForiegnHost);
  1966.     // use serverIP from PUT response for GET reconnect
  1967.     m_pForiegnHost = new char [strlen(m_pszPutServerIP) + 1];
  1968.     if (!m_pForiegnHost)
  1969.     {
  1970. rc = HXR_OUTOFMEMORY;
  1971. goto cleanup;
  1972.     }
  1973.     ::strcpy(m_pForiegnHost, m_pszPutServerIP); /* Flawfinder: ignore */
  1974.     
  1975.     if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pGetCtrl))
  1976.     {
  1977. rc = HXR_FAILED;
  1978. goto cleanup;
  1979.     }
  1980.     m_pGetCtrlResponse = new HTTPCloakTCPResponse(this, TRUE);
  1981.     if (!m_pGetCtrlResponse)
  1982.     {
  1983. rc = HXR_FAILED;
  1984. goto cleanup;
  1985.     }
  1986.     m_pGetCtrlResponse->AddRef();
  1987.     if (HXR_OK != m_pGetCtrl->Init(m_pGetCtrlResponse))
  1988.     {
  1989. rc = HXR_FAILED;
  1990. goto cleanup;
  1991.     }
  1992.     if (HXR_OK != m_pGetCtrl->Bind(HXR_INADDR_ANY, 0))
  1993.     {
  1994. rc = HXR_FAILED;
  1995. goto cleanup;
  1996.     }
  1997.     rc = ActualConnect();
  1998. cleanup:
  1999.     m_pMutex->Unlock();
  2000.     return rc;
  2001. }
  2002. BOOL
  2003. HXClientCloakedTCPSocket::AuthenticationRequired(HX_RESULT   status, IHXBuffer* pInBuffer)
  2004. {
  2005.     if (!pInBuffer)
  2006.     {
  2007. return FALSE;
  2008.     }
  2009.     // start of authenticated proxy logic.
  2010.     HTTPParser Parser;
  2011.     char* pBufferContents = (char*)(const char*)pInBuffer->GetBuffer();
  2012.     ULONG32 nMsgLen = pInBuffer->GetSize();
  2013.     HTTPResponseMessage* pMessage = (HTTPResponseMessage*)Parser.parse( pBufferContents, nMsgLen );
  2014.     // ignore non-HTTP responses which will be processed by the response object:
  2015.     // RTSPClientProtocol
  2016.     if (HTTPMessage::T_UNKNOWN == pMessage->tag())
  2017.     {
  2018. HX_DELETE(pMessage);
  2019. return FALSE;
  2020.     }
  2021.     ULONG32 ulHTTPStatus = 0;
  2022.     if (strlen(pMessage->errorCode()) > 0)
  2023.     {
  2024. ulHTTPStatus = atoi(pMessage->errorCode());
  2025.     }
  2026.     if (ulHTTPStatus == 401 || ulHTTPStatus == 407)
  2027.     {
  2028. #ifdef _MACINTOSH
  2029. if (!IsMacInCooperativeThread())
  2030. {
  2031.     // xxxbobclark Since there's UI involved with authentication,
  2032.     // we'll ensure that we're not at interrupt time.
  2033.     if (m_pAuthenticationCallback && !m_pAuthenticationCallback->m_ulPendingCallbackID)
  2034.     {
  2035. m_pAuthenticationCallback->m_ulPendingCallbackID  =
  2036. m_pScheduler->RelativeEnter(m_pAuthenticationCallback, 0);
  2037. m_pAuthenticationCallback->m_Status = status;
  2038. pInBuffer->AddRef();
  2039. m_pAuthenticationCallback->m_pInBuffer = pInBuffer;
  2040.     }
  2041.     HX_DELETE(pMessage);
  2042.     return TRUE;  
  2043. }
  2044. #endif
  2045. IHXRequest* pRequest = NULL;
  2046. IHXCommonClassFactory* pCCF;
  2047. HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF);
  2048. if (SUCCEEDED(retVal))
  2049. {
  2050.     retVal = pCCF->CreateInstance(CLSID_IHXRequest, (void**)&pRequest);
  2051.     if(retVal == HXR_OK)
  2052.     {
  2053. PrepareGetMessage(); // set up m_pSendTCP
  2054. UINT16 count    = m_pSendTCP->GetQueuedItemCount();
  2055. m_pSendTCP->DeQueue(m_pOutBuf,count);
  2056. retVal = pRequest->SetURL(m_pOutBuf);
  2057. IHXKeyValueList* pResponseHeaders = NULL;
  2058. pCCF->CreateInstance(CLSID_IHXKeyValueList, (void**)&pResponseHeaders);
  2059. MIMEHeaderValue* pHeaderValue = NULL;
  2060. MIMEHeader* pHeader = pMessage->getFirstHeader();
  2061. while (pHeader)
  2062. {
  2063.     pHeaderValue = pHeader->getFirstHeaderValue();
  2064.     CHXString strHeader;
  2065.     while (pHeaderValue)
  2066.     {
  2067. CHXString strTemp;
  2068. pHeaderValue->asString(strTemp);
  2069. strHeader += strTemp;
  2070. pHeaderValue = pHeader->getNextHeaderValue();
  2071. if (pHeaderValue)
  2072. {
  2073.     strHeader += ", ";
  2074. }
  2075.     }
  2076.     IHXBuffer* pBuffer = NULL;
  2077.     CHXBuffer::FromCharArray((const char*)strHeader, &pBuffer);
  2078.     pResponseHeaders->AddKeyValue(pHeader->name(), pBuffer);
  2079.     HX_RELEASE(pBuffer);
  2080.     pHeader = pMessage->getNextHeader();
  2081. }
  2082. IHXValues* pResponseValues = NULL;             
  2083. if (HXR_OK == pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseValues))
  2084. {
  2085.     pRequest->SetResponseHeaders(pResponseValues);
  2086. }
  2087. HandleAuthentication(pRequest, pMessage, m_pForiegnHost, m_pProxyHostName);
  2088. HX_RELEASE(pResponseValues);
  2089. HX_RELEASE(pResponseHeaders);
  2090.     }
  2091.     HX_RELEASE(pCCF);
  2092. }
  2093. HX_DELETE(pMessage);
  2094. return TRUE;
  2095.     }
  2096.     HX_DELETE(pMessage);
  2097.     return FALSE;
  2098. }
  2099. #define CLOAKED_WWW_AUTHENTICATION_RECENT_KEY "authentication.http.realm.recent"
  2100. #define CLOAKED_PROXY_AUTHENTICATION_RECENT_KEY "proxy-authentication.http.realm.recent"
  2101. void
  2102. HXClientCloakedTCPSocket::ObtainAuthenticationInformation(CHXString& strAuth)
  2103. {
  2104.     IHXBuffer* pBuffer = NULL;
  2105.     CHXString key("no-authentication-information");
  2106.     CHXString recentAuthRealmInfo;
  2107.     CHXString recentProxyAuthRealmInfo;
  2108.     IHXBuffer* pHeaderBuffer = NULL;
  2109.     
  2110.     HX_RESULT theErr = HXR_OK;
  2111.     IHXRegistry* pRegistry = NULL;
  2112.     
  2113.     m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  2114.     HX_ASSERT(pRegistry);
  2115.     
  2116.     if (!pRegistry) return;
  2117.     
  2118.     theErr = pRegistry->GetStrByName(CLOAKED_WWW_AUTHENTICATION_RECENT_KEY, pHeaderBuffer);
  2119.     if (SUCCEEDED(theErr))
  2120.     {
  2121. HX_ASSERT(pHeaderBuffer);
  2122. recentAuthRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
  2123. HX_RELEASE(pHeaderBuffer);
  2124.     }
  2125.     theErr = pRegistry->GetStrByName(CLOAKED_PROXY_AUTHENTICATION_RECENT_KEY, pHeaderBuffer);
  2126.     if (SUCCEEDED(theErr))
  2127.     {
  2128. HX_ASSERT(pHeaderBuffer);
  2129. recentProxyAuthRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
  2130. HX_RELEASE(pHeaderBuffer);
  2131.     }
  2132.     key = "proxy-authentication.http:";
  2133.     key += m_pProxyHostName;
  2134.     key += ":";
  2135.     key += recentProxyAuthRealmInfo;
  2136.     if (HXR_OK == pRegistry->GetStrByName((const char*)key, pBuffer) )
  2137.     {
  2138. if (pBuffer)
  2139. {
  2140.     CHXString authString((const char*)pBuffer->GetBuffer(), pBuffer->GetSize());
  2141.     strAuth = "Proxy-Authorization: ";
  2142.     strAuth += (const char*)authString;
  2143. }
  2144.     }
  2145.     HX_RELEASE(pBuffer);
  2146.     HX_RELEASE(pRegistry);
  2147. }
  2148. HX_RESULT
  2149. HXClientCloakedTCPSocket::HandleAuthentication(IHXRequest* pRequest, HTTPResponseMessage* pMessage,
  2150. const char* pHost, const char* pProxyHost)
  2151. {
  2152.     HX_RESULT   ResultStatus = HXR_OK;
  2153.     UINT32      ulAltURL = 0;
  2154.     CHXString   sConnection;
  2155.     IHXValues* pNewHeaders = NULL;
  2156.     // xxxbobclark The reason we need to extract the IHXPlayer is that
  2157.     // later on the authenticator smart pointer needs a context which knows
  2158.     // about authentication conversations. this->m_pContext does not know
  2159.     // about the authentication conversation. That's why we have to iterate
  2160.     // through the players looking for someone. Sheesh.
  2161.     if (!pRequest)
  2162.     {
  2163.         return HXR_UNEXPECTED;
  2164.     }
  2165.     HX_RESULT retVal = HXR_OK;
  2166.     IHXRegistry* pRegistry = NULL;
  2167.     retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  2168.     if (SUCCEEDED(retVal))
  2169.     {
  2170. IHXCommonClassFactory* pCCF;
  2171. retVal = m_pCloakContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF);
  2172. if (SUCCEEDED(retVal))
  2173. {
  2174.     IHXValues* pResponseHeaders = NULL;
  2175.     
  2176.     HX_ASSERT(pRequest);
  2177.     if (HXR_OK == pRequest->GetResponseHeaders(pResponseHeaders))
  2178.     {
  2179. IHXBuffer* pServerHeaderBuffer = NULL;
  2180. HX_ASSERT(pHost);
  2181. if (pHost)
  2182. {
  2183.     retVal = pCCF->CreateInstance(CLSID_IHXBuffer,
  2184.      (void**)&pServerHeaderBuffer);
  2185.     if (SUCCEEDED(retVal))
  2186.     {
  2187. UINT32 ulHTTPStatus = atoi(pMessage->errorCode());
  2188. if (ulHTTPStatus == 407 && pProxyHost)
  2189. {
  2190.     pServerHeaderBuffer->Set((UCHAR*)pProxyHost, strlen(pProxyHost)+1);
  2191. }
  2192. else
  2193. {
  2194.     pServerHeaderBuffer->Set((UCHAR*)pHost, strlen(pHost)+1);
  2195. }
  2196. pResponseHeaders->SetPropertyCString("_server", pServerHeaderBuffer);
  2197. HX_RELEASE(pServerHeaderBuffer);
  2198.     }
  2199. }
  2200.     // Add the protocol to the response headers because TLC needs it
  2201.     IHXBuffer* pProtocol = NULL;
  2202.     if (SUCCEEDED(pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pProtocol)))
  2203.     {
  2204. pProtocol->Set((UCHAR*)"http", strlen("http") + 1);
  2205. pResponseHeaders->SetPropertyCString("_protocol", pProtocol);
  2206. HX_RELEASE(pProtocol);
  2207.     }
  2208.     }
  2209.     if (!spClientAuthConversationAuthenticator.IsValid())
  2210.     {
  2211. DECLARE_SMART_POINTER_UNKNOWN spUnknownAuthenticator;
  2212. DECLARE_SMART_POINTER
  2213. (
  2214. IHXObjectConfiguration
  2215. ) spObjectConfigurationAuthenticator;
  2216. DECLARE_SMART_POINTER
  2217. (
  2218. IHXCommonClassFactory
  2219. ) spCommonClassFactoryHXCore;
  2220. spCommonClassFactoryHXCore = m_pCloakContext;
  2221. // Starting conversation
  2222. ResultStatus = spCommonClassFactoryHXCore->CreateInstance
  2223. (
  2224. CLSID_CHXClientAuthenticator,
  2225. (void**)&spUnknownAuthenticator
  2226. );
  2227. if ( SUCCEEDED(ResultStatus) && spUnknownAuthenticator.IsValid() )
  2228. {
  2229.     spObjectConfigurationAuthenticator = 
  2230. (
  2231. spUnknownAuthenticator
  2232. );
  2233.     spObjectConfigurationAuthenticator->SetContext(m_pCloakContext);
  2234.     spClientAuthConversationAuthenticator = 
  2235. (
  2236. spUnknownAuthenticator
  2237. );
  2238. }
  2239.     }
  2240.     if ( spClientAuthConversationAuthenticator.IsValid()
  2241. && !spClientAuthConversationAuthenticator->IsDone() )
  2242.     {
  2243. HX_ASSERT(pRequest);
  2244. if (pRequest)
  2245. {
  2246.     ResultStatus = 
  2247. (
  2248. spClientAuthConversationAuthenticator->MakeResponse
  2249. (
  2250. this,
  2251. pRequest
  2252. )
  2253. );
  2254. // Flow continues in ResponseReady()
  2255. }
  2256. else
  2257. {
  2258.     // Auth Failed!
  2259.     spClientAuthConversationAuthenticator->Authenticated(FALSE);
  2260.     ResponseReady(HXR_NOT_AUTHORIZED, pRequest);
  2261. }
  2262.     }
  2263.     HX_RELEASE(pCCF);
  2264. }
  2265. HX_RELEASE(pRegistry);
  2266.     }
  2267.     
  2268.     return ResultStatus;
  2269. }
  2270. // IHXClientAuthResponse
  2271. STDMETHODIMP 
  2272. HXClientCloakedTCPSocket::ResponseReady( HX_RESULT ResultStatus, IHXRequest* pRequestResponse)
  2273. {
  2274.     // now if it's an OK result, then I can use pRequestResponse in a new get.
  2275.     if (FAILED(ResultStatus))
  2276.     {
  2277. return ResultStatus;
  2278.     }
  2279.     IHXValues* pHeaders = NULL;
  2280.     HX_ASSERT(pRequestResponse);
  2281.     if (HXR_OK == pRequestResponse->GetRequestHeaders(pHeaders))
  2282.     {
  2283. const char* pName;
  2284. IHXBuffer* pBuf;
  2285. HX_RESULT res = pHeaders->GetFirstPropertyCString(pName, pBuf);
  2286. while (res == HXR_OK)
  2287. {
  2288.     if (!strcasecmp(pName, "Proxy-Authorization"))
  2289.     {
  2290. HX_RESULT retVal = HXR_OK;
  2291. IHXRegistry* pRegistry = NULL;
  2292. retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  2293. IHXCommonClassFactory* pCCF = NULL;
  2294. if (m_pContext)
  2295. {
  2296.     m_pContext->AddRef();
  2297.     // get the CCF
  2298.     m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF);
  2299. }
  2300. if (SUCCEEDED(retVal))
  2301. {
  2302.     IHXBuffer* pBuffer = NULL;
  2303.     retVal = pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
  2304.     UINT32 regid = 0;
  2305.     
  2306.     HX_ASSERT(SUCCEEDED(retVal));
  2307.     if (SUCCEEDED(retVal))
  2308.     {
  2309. IHXBuffer* pHeaderBuffer = NULL;
  2310. CHXString key;
  2311. CHXString recentRealmInfo = "";
  2312. if (!strcasecmp(pName, "Proxy-Authorization"))
  2313. {
  2314.     key = "proxy-authentication.http:";
  2315.     retVal = pRegistry->GetStrByName(CLOAKED_PROXY_AUTHENTICATION_RECENT_KEY,
  2316. pHeaderBuffer);
  2317.     if (SUCCEEDED(retVal))
  2318.     {
  2319. HX_ASSERT(pHeaderBuffer);
  2320. recentRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
  2321. HX_RELEASE(pHeaderBuffer);
  2322.     }
  2323. key += m_pProxyHostName;
  2324. }
  2325. key += ":";
  2326. key += recentRealmInfo;
  2327. HX_ASSERT(!key.IsEmpty());
  2328. pBuffer->Set(pBuf->GetBuffer(), pBuf->GetSize());
  2329. regid = pRegistry->GetId((const char*)key);
  2330. if (!regid)
  2331. {
  2332.     pRegistry->AddStr((const char*)key, pBuffer);
  2333. }
  2334. else
  2335. {
  2336.     pRegistry->SetStrByName((const char*)key, pBuffer);
  2337. }
  2338. HX_RELEASE(pBuffer);
  2339. HX_RELEASE(pHeaderBuffer);
  2340.     }
  2341. }
  2342. HX_RELEASE(pCCF);
  2343.     }
  2344.     HX_RELEASE(pBuf);
  2345.     res = pHeaders->GetNextPropertyCString(pName, pBuf);
  2346. }
  2347.     }
  2348.     CleanUpAndReInitializeStuff();
  2349.     return HXR_OK;
  2350. }
  2351. STDMETHODIMP
  2352. HXClientCloakedTCPSocket::HandleCallback(INT32 theCommand, HX_RESULT theError)
  2353. {
  2354.     if (!m_bInDestructor)
  2355.     {
  2356. m_pMutex->Lock();
  2357. DoGetWrite();
  2358. DoPutWrite();
  2359. DoRead();
  2360. m_pMutex->Unlock();
  2361.     }
  2362.     return HXR_OK;
  2363. }
  2364. HXClientCloakedTCPSocket::HTTPCloakTCPResponse::HTTPCloakTCPResponse(HXClientCloakedTCPSocket* pOwner, BOOL bIsRead) :
  2365.      m_pOwner(pOwner)
  2366.     ,m_lRefCount(0) 
  2367.     ,m_bIsRead(bIsRead)
  2368. {
  2369. }
  2370. HXClientCloakedTCPSocket::HTTPCloakTCPResponse::~HTTPCloakTCPResponse()
  2371. {
  2372. }
  2373. /*
  2374.  *  IUnknown methods
  2375.  */
  2376. /////////////////////////////////////////////////////////////////////////
  2377. //  Method:
  2378. // IUnknown::QueryInterface
  2379. //  Purpose:
  2380. // Implement this to export the interfaces supported by your 
  2381. // object.
  2382. //
  2383. STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::QueryInterface(REFIID riid, void** ppvObj)
  2384. {
  2385.     QInterfaceList qiList[] =
  2386.         {
  2387.             { GET_IIDHANDLE(IID_IHXTCPResponse), (IHXTCPResponse*)this },
  2388.             { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*)this },
  2389.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXTCPResponse*)this },
  2390.         };
  2391.     
  2392.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2393. }
  2394. /////////////////////////////////////////////////////////////////////////
  2395. //  Method:
  2396. // IUnknown::AddRef
  2397. //  Purpose:
  2398. // Everyone usually implements this the same... feel free to use
  2399. // this implementation.
  2400. //
  2401. STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::HTTPCloakTCPResponse::AddRef()
  2402. {
  2403.     return InterlockedIncrement(&m_lRefCount);
  2404. }
  2405. /////////////////////////////////////////////////////////////////////////
  2406. //  Method:
  2407. // IUnknown::Release
  2408. //  Purpose:
  2409. // Everyone usually implements this the same... feel free to use
  2410. // this implementation.
  2411. //
  2412. STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::HTTPCloakTCPResponse::Release()
  2413. {
  2414.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2415.     {
  2416.         return m_lRefCount;
  2417.     }
  2418.     delete this;
  2419.     return 0;
  2420. }
  2421. /*
  2422.  * IHXTCPResponse methods
  2423.  */
  2424. STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::ConnectDone(HX_RESULT status)
  2425. {
  2426.     // xxxbobclark this authentication kludge is to ensure that layers "above" me
  2427.     // never have to care whether they're using an authenticated proxy or not.
  2428.     // So since this cloaked socket has already called its owner with ConnectDone
  2429.     // messages, it won't resend those... rather, it will reconstruct the same state
  2430.     // that the above layer expects.
  2431.     // So we set it up so the next ReadDone will work through the proxy and pass
  2432.     // through to the above layer and everything should be cool.
  2433.     if (m_pOwner->m_bInAuthenticationKludge)
  2434.     {
  2435. m_pOwner->m_bInAuthenticationKludge = FALSE;
  2436. if (m_bIsRead)
  2437. {
  2438.     m_pOwner->PreparePostMessage(NULL, 0);
  2439.     m_pOwner->DoPutWrite();
  2440.     m_pOwner->PrepareGetMessage();
  2441.     m_pOwner->DoGetWrite();
  2442. }
  2443. m_pOwner->Read(4096);
  2444. m_pOwner->m_bConnected = TRUE;
  2445. return HXR_OK;
  2446.     }
  2447.     if (m_bIsRead)
  2448.     {
  2449. m_pOwner->GetConnectDone(status == HXR_OK ? TRUE : FALSE);/*m_pGetCtrl*/
  2450.     }
  2451.     else
  2452.     {
  2453. m_pOwner->PutConnectDone(status == HXR_OK ? TRUE : FALSE);/*m_pPutCtrl*/
  2454.     }
  2455.     return HXR_OK;
  2456. }
  2457. STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::ReadDone( HX_RESULT   status,
  2458. IHXBuffer* pBuffer)
  2459. {
  2460.     if (m_bIsRead)
  2461.     {
  2462. m_pOwner->DoGetReadDone(status, pBuffer); /*m_pGetCtrl*/
  2463.     }
  2464.     else 
  2465.     {
  2466. m_pOwner->DoPutReadDone(status, pBuffer); /*m_pPutCtrl*/
  2467.     }
  2468.     return HXR_OK;
  2469. }
  2470. STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::WriteReady(HX_RESULT status)
  2471. {
  2472.     if (m_bIsRead)
  2473.     {
  2474. m_pOwner->m_pMutex->Lock();
  2475. m_pOwner->DoGetWrite(); /*m_pGetCtrl*/
  2476. m_pOwner->m_pMutex->Unlock();
  2477.     }
  2478.     else
  2479.     {
  2480. m_pOwner->m_bPutWantWritePending = FALSE;
  2481. m_pOwner->m_pMutex->Lock();
  2482. m_pOwner->DoPutWrite(); /*m_pPutCtrl*/
  2483. m_pOwner->m_pMutex->Unlock();
  2484.     }
  2485.     return HXR_OK;
  2486. }
  2487. STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::Closed(HX_RESULT status)
  2488. {
  2489.     return HXR_OK;
  2490. }
  2491. #ifdef _MACINTOSH
  2492. HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::MacCloakedTCPSocketAuthenticationCallback (
  2493. HXClientCloakedTCPSocket* pSocket)
  2494.     : m_lRefCount(0)
  2495.     , m_ulPendingCallbackID(NULL)
  2496.     , m_pSocket(pSocket)
  2497.     , m_Status(HXR_OK)
  2498.     , m_pInBuffer(NULL)
  2499. {
  2500. }
  2501. HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::~MacCloakedTCPSocketAuthenticationCallback()
  2502. {
  2503. }
  2504. STDMETHODIMP
  2505. HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::QueryInterface(
  2506. REFIID riid, void** ppvObj)
  2507. {
  2508.     QInterfaceList qiList[] =
  2509.         {
  2510.             { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this },
  2511.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXCallback*)this },
  2512.         };
  2513.     
  2514.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2515. }
  2516. STDMETHODIMP_(ULONG32)
  2517. HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::AddRef()
  2518. {
  2519.     return InterlockedIncrement( &m_lRefCount );
  2520. }
  2521. STDMETHODIMP_(ULONG32)
  2522. HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::Release()
  2523. {
  2524.     if ( InterlockedDecrement( &m_lRefCount ) > 0 )
  2525.     {
  2526. return m_lRefCount;
  2527.     }
  2528.     
  2529.     delete this;
  2530.     return 0;
  2531. }
  2532. STDMETHODIMP
  2533. HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::Func()
  2534. {
  2535.     m_ulPendingCallbackID = NULL;
  2536.     
  2537.     if (m_pInBuffer)
  2538.     {
  2539. m_pSocket->DoGetReadDone(m_Status, m_pInBuffer);
  2540. HX_RELEASE(m_pInBuffer);
  2541.     }
  2542.     
  2543.     return HXR_OK;
  2544. }
  2545. #endif