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

Symbian

开发平台:

C/C++

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