hxcloakedtcp.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:72k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hlxclib/stdio.h"
- #include "hxcloakedtcp.h"
- #include "safestring.h"
- #include "hxnetutil.h"
- #include "ihxpckts.h"
- #include "hxccf.h" // IHXCommonClassFactory
- #include "hxthread.h" // HXMutex
- #include "hxbuffer.h" // CHXBuffer
- #include "conn.h" // TCP_BUF_SIZE
- #include "dbcs.h" // HXFindString
- #include "hxmarsh.h" // getshort()
- #include "chxuuid.h" // CHXuuid
- #include "hxtick.h" // HX_GET_TICKCOUNT
- #include "rtsputil.h" // BinTo64
- #include "hxfiles.h" // CLSID_IHXRequest
- #include "hxplnsp.h" // _CIHXObjectConfiguration_SP
- #include "hxcomsp.h" // _CIHXCommonClassFactory_SP
- // necessary for authentication
- #include "hxmon.h"
- #include "httppars.h"
- #include "hxplgns.h"
- #include "hxcore.h"
- #include "httpclk.h"
- #ifdef _MACINTOSH
- #include "hx_moreprocesses.h"
- #endif
- /******************* HTTP Cloaking*****************/
- #define QUEUE_START_SIZE 512
- #define HTTPCLOAK_PUTRESPONSE_TIMEOUT 2000
- #define MAX_HTTP_METHOD_BUFSIZE 2048
- #define HXGUID_SIZE 16 // 16 byte GUID plus rn
- #define ENQUEUE_DATA(x,y,z) (x)->EnQueue((y),(z))
- #define ENQUEUE_BYTE(x,y) {UCHAR uChar = (y);
- (x)->EnQueue(&uChar,sizeof(uChar));}
- #define ENQUEUE_WORD(x,y) {UINT16 wTemp = (y);
- wTemp = WToNet(wTemp);
- (x)->EnQueue(&wTemp,sizeof(UINT16));}
- #define ENQUEUE_DWORD(x,y) {ULONG32 dTemp = (y);
- dTemp = DwToNet(dTemp);
- (x)->EnQueue(&dTemp,sizeof(ULONG32));}
- #define DEFAULT_HTTP_HEADER_LENGTH 256
- #define DEFAULT_OPTION_PADDING_LENGTH 16381
- #ifdef _WINCE
- #define SCHED_GRANULARITY 10
- #else
- #define SCHED_GRANULARITY 50
- #endif
- enum
- {
- HTTP_OK = 0,
- HTTP_GENERAL_ERROR, // for any error that is not defined below
- POST_NOT_RECEIVED, // POST message was not received
- INVALID_GUID // sent only if the GUID from the Player is already in use
- };
- /* HXClientCloakedTCPSocket */
- HXClientCloakedTCPSocket::HXClientCloakedTCPSocket(IUnknown* pContext):
- m_lRefCount(0)
- ,m_pContext(pContext)
- ,m_pTCPResponse(0)
- ,m_pNetworkServices(0)
- ,m_pGetCtrl(0)
- ,m_pPutCtrl(0)
- ,m_pGetCtrlResponse(0)
- ,m_pPutCtrlResponse(0)
- ,m_bGetReadPending(FALSE)
- ,m_bPutReadPending(FALSE)
- ,m_bPutWantWritePending(FALSE)
- ,m_lForeignAddress(0)
- ,m_nForeignPort(0)
- ,m_bReadPending(FALSE)
- ,m_nRequired(0)
- ,m_pSendTCP(0)
- ,m_pReceiveGetTCP(0)
- ,m_pReceivePutTCP(0)
- ,m_pPreEncodedSendHTTP(0)
- ,m_pPostEncodedSendHTTP(0)
- ,m_pOutBuf(0)
- ,m_pOutEncodedBuf(0)
- ,m_pInBuf(0)
- ,m_bConnected(FALSE)
- ,m_pForiegnHost(0)
- ,m_pGuid(0)
- ,m_bGetConnectDone(FALSE)
- ,m_bPutConnectDone(FALSE)
- ,m_bGetConnectSuccessful(FALSE)
- ,m_bPutConnectSuccessful(FALSE)
- ,m_bConnectResponsePending(TRUE)
- ,m_bOptionsReceived(FALSE)
- ,m_bUseExactContentLength(FALSE)
- ,m_bCloseHttpAfterWrite(FALSE)
- ,m_bMustCloseHTTP(FALSE)
- ,m_bHttpInitialized(FALSE)
- ,m_LastError(HXR_OK)
- ,m_pHTTPHeaderBuffer(0)
- ,m_nHTTPHeaderBufferLength(0)
- ,m_bHTTPGetHeaderReadDone(FALSE)
- ,m_bHTTPPutHeaderReadDone(FALSE)
- ,m_pProxyHostName(0)
- ,m_nProxyPortNumber(0)
- ,m_bInDestructor(FALSE)
- ,m_pScheduler(0)
- ,m_pSchedulerCallback(0)
- ,m_pNonInterruptCallback(0)
- ,m_bInDoRead(FALSE)
- ,m_bInDoGetWrite(FALSE)
- ,m_bInDoPutWrite(FALSE)
- ,m_bInTransferBuffers(FALSE)
- ,m_bInitComplete(FALSE)
- ,m_bDeletePadding(FALSE)
- ,m_uPadLength(10+DEFAULT_OPTION_PADDING_LENGTH) // 10 for the opts and 16381 for the padding
- ,m_pInterruptState(NULL)
- ,m_pResponseInterruptSafe(NULL)
- ,m_pMutex(NULL)
- ,m_pCloakValues(NULL)
- ,m_pCloakContext(NULL)
- ,m_bGetResponsed(FALSE)
- ,m_bPutResponsed(FALSE)
- ,m_pszGetServerIP(NULL)
- ,m_pszPutServerIP(NULL)
- ,m_bReconnectToSameServerIP(FALSE)
- ,m_bConnectToSameServerIP(FALSE)
- ,m_pPreferredTransport(NULL)
- ,m_pPreferredTransportManager(NULL)
- #ifdef _MACINTOSH
- ,m_pAuthenticationCallback(NULL)
- #endif
- ,m_bInAuthenticationKludge(FALSE)
- {
- if(m_pContext)
- {
- m_pContext->AddRef();
- m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
- m_pContext->QueryInterface(IID_IHXNetworkServices, (void**) &m_pNetworkServices);
- m_pContext->QueryInterface(IID_IHXInterruptState, (void**) &m_pInterruptState);
- m_pContext->QueryInterface(IID_IHXPreferredTransportManager, (void**)&m_pPreferredTransportManager);
- }
- #if defined(THREADS_SUPPORTED)
- HXMutex::MakeMutex(m_pMutex);
- #elif defined(_UNIX_THREADED_NETWORK_IO)
- if( ReadNetworkThreadingPref((IUnknown*)pContext) )
- {
- HXMutex::MakeMutex(m_pMutex);
- }
- else
- {
- HXMutex::MakeStubMutex(m_pMutex);
- }
- #else
- HXMutex::MakeStubMutex(m_pMutex);
- #endif
- #ifdef _MACINTOSH
- m_pAuthenticationCallback = new MacCloakedTCPSocketAuthenticationCallback(this);
- m_pAuthenticationCallback->AddRef();
- #endif
- }
- HXClientCloakedTCPSocket::~HXClientCloakedTCPSocket()
- {
- m_bInDestructor = TRUE;
-
- m_pMutex->Lock();
- #ifdef _MACINTOSH
- if (m_pAuthenticationCallback && m_pAuthenticationCallback->m_ulPendingCallbackID &&
- m_pScheduler)
- {
- m_pScheduler->Remove(m_pAuthenticationCallback->m_ulPendingCallbackID);
- m_pAuthenticationCallback->m_ulPendingCallbackID = NULL;
- }
- HX_RELEASE(m_pAuthenticationCallback);
- #endif
- while (m_PendingWriteBuffers.GetCount() > 0)
- {
- IHXBuffer* pBuffer = (IHXBuffer*) m_PendingWriteBuffers.RemoveHead();
- pBuffer->Release();
- }
- FlushQueues();
- /* Send a final HTTP done message */
- if (m_bHttpInitialized)
- {
- SendHTTPDone();
- }
- if (m_pSchedulerCallback)
- {
- m_pSchedulerCallback->Unschedule(m_pScheduler);
- HX_RELEASE(m_pSchedulerCallback);
- }
- if (m_pNonInterruptCallback)
- {
- m_pNonInterruptCallback->Unschedule(m_pScheduler);
- HX_RELEASE(m_pNonInterruptCallback);
- }
- HX_RELEASE(m_pGetCtrl);
- HX_RELEASE(m_pPutCtrl);
- HX_RELEASE(m_pGetCtrlResponse);
- HX_RELEASE(m_pPutCtrlResponse);
- HX_RELEASE(m_pCloakValues);
- HX_RELEASE(m_pCloakContext);
- HX_RELEASE(m_pTCPResponse);
- HX_RELEASE(m_pNetworkServices);
- HX_DELETE(m_pSendTCP);
- HX_DELETE(m_pReceiveGetTCP);
- HX_DELETE(m_pReceivePutTCP);
- HX_DELETE(m_pPreEncodedSendHTTP);
- HX_DELETE(m_pPostEncodedSendHTTP);
- HX_VECTOR_DELETE(m_pInBuf);
- HX_VECTOR_DELETE(m_pOutBuf);
- HX_VECTOR_DELETE(m_pOutEncodedBuf);
- HX_VECTOR_DELETE(m_pForiegnHost);
- HX_VECTOR_DELETE(m_pGuid);
- HX_VECTOR_DELETE(m_pHTTPHeaderBuffer);
- HX_VECTOR_DELETE(m_pProxyHostName);
- HX_VECTOR_DELETE(m_pszGetServerIP);
- HX_VECTOR_DELETE(m_pszPutServerIP);
- HX_RELEASE(m_pPreferredTransport);
- HX_RELEASE(m_pPreferredTransportManager);
- HX_RELEASE(m_pInterruptState);
- HX_RELEASE(m_pResponseInterruptSafe);
- HX_RELEASE(m_pScheduler);
- HX_RELEASE(m_pContext);
- m_pMutex->Unlock();
- HX_DELETE(m_pMutex);
- }
- STDMETHODIMP HXClientCloakedTCPSocket::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IHXTCPSocket), (IHXTCPSocket*)this },
- { GET_IIDHANDLE(IID_IHXCloakedTCPSocket), (IHXCloakedTCPSocket*)this },
- { GET_IIDHANDLE(IID_IHXHTTPProxy), (IHXHTTPProxy*)this },
- { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXTCPSocket*)this },
- };
-
- return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::Init(IHXTCPResponse* pTCPResponse)
- {
- HX_RESULT rc = HXR_OK;
- if (!pTCPResponse)
- {
- return HXR_UNEXPECTED;
- }
- if (!m_pSchedulerCallback)
- {
- m_pSchedulerCallback = new ScheduledSocketCallback(this, TRUE);
- m_pSchedulerCallback->AddRef();
- }
- if (!m_pNonInterruptCallback)
- {
- m_pNonInterruptCallback = new ScheduledSocketCallback(this, TRUE);
- m_pNonInterruptCallback->AddRef();
- }
- m_pTCPResponse = pTCPResponse;
- m_pTCPResponse->AddRef();
- m_pTCPResponse->QueryInterface(IID_IHXInterruptSafe,
- (void**) &m_pResponseInterruptSafe);
- if (!m_pNetworkServices)
- {
- return HXR_FAILED;
- }
-
- if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pGetCtrl))
- {
- return HXR_FAILED;
- }
- if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pPutCtrl))
- {
- return HXR_FAILED;
- }
- m_pGetCtrlResponse = new HTTPCloakTCPResponse(this, TRUE);
- m_pPutCtrlResponse = new HTTPCloakTCPResponse(this, FALSE);
- if (!m_pGetCtrlResponse || !m_pPutCtrlResponse)
- {
- return HXR_OUTOFMEMORY;
- }
- m_pGetCtrlResponse->AddRef();
- m_pPutCtrlResponse->AddRef();
- if (HXR_OK != m_pGetCtrl->Init(m_pGetCtrlResponse) ||
- HXR_OK != m_pPutCtrl->Init(m_pPutCtrlResponse))
- {
- return HXR_FAILED;
- }
- if (HXR_OK != m_pGetCtrl->Bind(HXR_INADDR_ANY, 0) ||
- HXR_OK != m_pPutCtrl->Bind(HXR_INADDR_ANY, 0))
- {
- return HXR_FAILED;
- }
- // allocate TCP send and receive queue
- m_pSendTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
- if (!m_pSendTCP || !m_pSendTCP->IsQueueValid())
- {
- return HXR_OUTOFMEMORY;
- }
- m_pSendTCP->SetMaxSize(TCP_BUF_SIZE);
- m_pReceiveGetTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
- if (!m_pReceiveGetTCP || !m_pReceiveGetTCP->IsQueueValid())
- {
- return HXR_OUTOFMEMORY;
- }
- m_pReceiveGetTCP->SetMaxSize(TCP_BUF_SIZE);
- m_pPreEncodedSendHTTP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
- if (!m_pPreEncodedSendHTTP || !m_pPreEncodedSendHTTP->IsQueueValid())
- {
- return HXR_OUTOFMEMORY;
- }
- /* Approx. MAX POST header size : 3000*/
- m_pPreEncodedSendHTTP ->SetMaxSize((TCP_BUF_SIZE-1)/2 - 3000);
- m_pPostEncodedSendHTTP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
- if (!m_pPostEncodedSendHTTP || !m_pPostEncodedSendHTTP->IsQueueValid())
- {
- return HXR_OUTOFMEMORY;
- }
- m_pPostEncodedSendHTTP->SetMaxSize(TCP_BUF_SIZE);
-
- m_pInBuf = new char[TCP_BUF_SIZE];
- if (!m_pInBuf)
- {
- return HXR_OUTOFMEMORY;
- }
- m_pOutBuf = new char[TCP_BUF_SIZE];
- if (!m_pOutBuf)
- {
- return HXR_OUTOFMEMORY;
- }
- m_pOutEncodedBuf = new char[TCP_BUF_SIZE];
- if (!m_pOutEncodedBuf)
- {
- return HXR_OUTOFMEMORY;
- }
- CreateGuid();
- return HXR_OK;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::SetResponse(IHXTCPResponse* pTCPResponse)
- {
- m_pMutex->Lock();
- HX_RELEASE(m_pTCPResponse);
- m_pTCPResponse = pTCPResponse;
- m_pTCPResponse->AddRef();
- HX_RELEASE(m_pResponseInterruptSafe);
- m_pTCPResponse->QueryInterface(IID_IHXInterruptSafe,
- (void**) &m_pResponseInterruptSafe);
- m_pMutex->Unlock();
- return HXR_OK;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::Bind(UINT32 ulLocalAddr, UINT16 nPort)
- {
- return HXR_NOTIMPL;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::Connect(const char* pDestination,
- UINT16 nPort)
- {
- m_nForeignPort = nPort;
- HX_VECTOR_DELETE(m_pForiegnHost);
- m_pForiegnHost = new char [strlen(pDestination) + 1];
- if (!m_pForiegnHost)
- {
- return HXR_OUTOFMEMORY;
- }
- ::strcpy(m_pForiegnHost, pDestination); /* Flawfinder: ignore */
- // m_pCloakValues is only set by RTSP
- if (m_pPreferredTransportManager && m_pCloakValues)
- {
- HX_RELEASE(m_pPreferredTransport);
- m_pPreferredTransportManager->GetPrefTransport(m_pForiegnHost,
- PTP_RTSP,
- m_pPreferredTransport);
- HX_ASSERT(m_pPreferredTransport);
- if (m_pPreferredTransport)
- {
- m_bConnectToSameServerIP = m_pPreferredTransport->GetHTTPNG();
- }
- }
- return ActualConnect();
- }
- STDMETHODIMP HXClientCloakedTCPSocket::Read(UINT16 uSize)
- {
- HX_RESULT theErr = HXR_OK;
- HX_RESULT lResult = HXR_OK;
- if (m_bReadPending)
- {
- return HXR_UNEXPECTED;
- }
- m_bReadPending = TRUE;
- m_nRequired = uSize;
- m_pMutex->Lock();
- theErr = DoRead();
- m_pMutex->Unlock();
- lResult = ConvertNetworkError(theErr);
- return lResult;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::Write(IHXBuffer* pBuffer)
- {
- HX_RESULT theErr = HXR_OK;
- HX_RESULT lResult = HXR_OK;
- pBuffer->AddRef();
- m_PendingWriteBuffers.AddTail((void*) pBuffer);
-
- m_pMutex->Lock();
- theErr = DoPutWrite();
- m_pMutex->Unlock();
- lResult = ConvertNetworkError(theErr);
- return lResult;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::WantWrite()
- {
- m_pTCPResponse->WriteReady(HXR_OK);
- return HXR_OK;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::GetLocalAddress(ULONG32& lAddress)
- {
- return HXR_NOTIMPL;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::GetForeignAddress(ULONG32& lAddress)
- {
- if(m_bConnected && m_lForeignAddress)
- {
- lAddress = m_lForeignAddress;
- return HXR_OK;
- }
- return HXR_FAIL;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::GetLocalPort(UINT16& port)
- {
- return HXR_NOTIMPL;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::GetForeignPort(UINT16& port)
- {
- if(m_bConnected)
- {
- port = m_nForeignPort;
- return HXR_OK;
- }
- return HXR_FAIL;
- }
- /*
- * IHXHTTPProxy methods
- *
- * Network addresses and ports are in native byte order
- *
- */
- STDMETHODIMP HXClientCloakedTCPSocket::SetProxy(
- const char* /*IN*/ pProxyHostName,
- UINT16 /*IN*/ nPort)
- {
- if(pProxyHostName == 0 || *pProxyHostName == 0)
- {
- return HXR_FAILED;
- }
-
- HX_VECTOR_DELETE(m_pProxyHostName);
- m_pProxyHostName = new char[::strlen(pProxyHostName) + 1];
- if (!m_pProxyHostName)
- {
- return HXR_OUTOFMEMORY;
- }
- ::strcpy(m_pProxyHostName, pProxyHostName); /* Flawfinder: ignore */
- m_nProxyPortNumber = nPort;
- return HXR_OK;
- }
- /************************************************************************
- * Method:
- * IHXCloakedTCPSocket::InitCloak
- */
- STDMETHODIMP
- HXClientCloakedTCPSocket::InitCloak(IHXValues* /*IN*/ pValues, IUnknown* pUnknown)
- {
- HX_RESULT rc = HXR_OK;
- if (pValues)
- {
- m_pCloakValues = pValues;
- m_pCloakValues->AddRef();
- }
- if (pUnknown)
- {
- m_pCloakContext = pUnknown;
- m_pCloakContext->AddRef();
- }
- return rc;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::DoRead()
- {
- HX_RESULT theErr = HXR_OK;
- char* pStartAfterDoubleReturn = 0;
- UINT16 count = 0;
- if(m_bInDoRead)
- {
- return HXR_OK;
- }
- m_bInDoRead = TRUE;
- if (m_LastError)
- {
- goto exit;
- }
- // m_pReceivePutTCP is only initialized if we receive POST response
- // from the server
- if (m_pReceivePutTCP)
- {
- count = m_pReceivePutTCP->GetMaxAvailableElements();
- }
- else
- {
- count = TCP_BUF_SIZE;
- }
- // attempt to read from PUT if:
- // * we haven't initiated PUT read already AND
- // * we haven't received the complete POST response header AND
- // * we are not in multi-POST mode
- if (count > 0 &&
- !m_bPutReadPending &&
- !m_bHTTPPutHeaderReadDone &&
- !m_bMustCloseHTTP)
- {
- // attempt to read data from TCP link
- m_bPutReadPending = TRUE;
- theErr = m_pPutCtrl->Read(count);
- }
- // check how much room we have in TCP receive queue
- count = m_pReceiveGetTCP->GetMaxAvailableElements();
- if (count > 0 && !m_bGetReadPending)
- {
- // attempt to read data from TCP link
- m_bGetReadPending = TRUE;
- theErr = m_pGetCtrl->Read(count);
- switch(theErr)
- {
- case HXR_AT_INTERRUPT:
- case HXR_WOULD_BLOCK:
- case HXR_OK:
- // mask out these errors
- theErr = HXR_OK;
- break;
- default:
- theErr = ConvertNetworkError(theErr);
- break;
- }
- }
- exit:
- if (theErr && !m_LastError)
- {
- m_LastError = theErr;
- }
- if (m_LastError)
- {
- if (m_bReadPending)
- {
- if (IsSafe())
- {
- m_bReadPending = FALSE;
- m_pTCPResponse->ReadDone(m_LastError, 0);
- }
- }
- }
- else
- {
- count = m_pReceiveGetTCP->GetQueuedItemCount();
- if (m_bReadPending && count > 0 && m_bOptionsReceived
- && m_bHTTPGetHeaderReadDone)
- {
- /* mask any kind of errors */
- theErr = HXR_OK;
- if (IsSafe())
- {
- m_bReadPending = FALSE;
- if (m_nRequired < count)
- {
- count = m_nRequired;
- }
- CHXBuffer* pBuffer = new CHXBuffer;
- pBuffer->AddRef();
- m_pReceiveGetTCP->DeQueue(m_pInBuf, count);
- pBuffer->Set((UCHAR*) m_pInBuf, count);
-
- m_pTCPResponse->ReadDone(HXR_OK, pBuffer);
- pBuffer->Release();
- }
- }
- if (m_pSchedulerCallback && m_bReadPending)
- {
- m_pSchedulerCallback->ScheduleCallback(CLOAKED_TCP_READ_COMMAND, m_pScheduler, SCHED_GRANULARITY);
- }
- }
-
- m_bInDoRead = FALSE;
- return theErr;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::DoGetWrite()
- {
- HX_RESULT theErr = HXR_OK;
- if (m_bInDoGetWrite)
- {
- return HXR_OK;
- }
- m_bInDoGetWrite = TRUE;
- // check how data we have in TCP send queue
- UINT16 count = m_pSendTCP->GetQueuedItemCount();
- UINT16 actual = count;
-
- if(count > 0)
- {
- m_pSendTCP->DeQueue(m_pOutBuf,count);
- CHXBuffer* pBuffer = new CHXBuffer;
- pBuffer->AddRef();
- pBuffer->Set((UCHAR*) m_pOutBuf, (ULONG32) count);
- theErr = m_pGetCtrl->Write(pBuffer);
- pBuffer->Release();
- }
-
- if (theErr)
- {
- switch(theErr)
- {
- case HXR_AT_INTERRUPT:
- case HXR_WOULD_BLOCK:
- m_pSendTCP->EnQueue(m_pOutBuf, count);
- // mask out these errors
- theErr = HXR_OK;
- break;
- default:
- theErr = ConvertNetworkError(theErr);
- break;
- }
- }
- if (!theErr && !m_bInDestructor &&
- m_pSendTCP->GetQueuedItemCount() > 0 ) {
- m_pSchedulerCallback->ScheduleCallback(CLOAKED_TCP_GETWRITE_COMMAND, m_pScheduler, SCHED_GRANULARITY);
- }
- m_bInDoGetWrite = FALSE;
- return theErr;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::DoPutWrite()
- {
- HX_RESULT theErr = HXR_OK;
- if (m_bInDoPutWrite)
- {
- return HXR_OK;
- }
- m_bInDoPutWrite = TRUE;
- /* Transfer pending buffers to TCP send queue */
- if (m_bOptionsReceived && m_pPostEncodedSendHTTP->GetQueuedItemCount() == 0 && !m_bPutWantWritePending)
- {
- TransferBuffers();
- }
- if (!m_bPutConnectDone)
- {
- goto exit;
- }
- // check how data we have in TCP send queue
- UINT16 count;
- UINT16 actual;
-
- count = m_pPostEncodedSendHTTP->GetQueuedItemCount();
- actual = count;
- if(count > 0)
- {
- m_pPostEncodedSendHTTP->DeQueue(m_pOutEncodedBuf,count);
- CHXBuffer* pBuffer = new CHXBuffer;
- pBuffer->AddRef();
- pBuffer->Set((UCHAR*) m_pOutEncodedBuf, (ULONG32) count);
- theErr = m_pPutCtrl->Write(pBuffer);
- pBuffer->Release();
- m_bPutWantWritePending = TRUE;
- m_pPutCtrl->WantWrite();
- }
-
- if (theErr)
- {
- switch(theErr)
- {
- case HXR_AT_INTERRUPT:
- case HXR_WOULD_BLOCK:
- m_pPostEncodedSendHTTP->EnQueue(m_pOutEncodedBuf, count);
- // mask out these errors
- theErr = HXR_OK;
- break;
- default:
- theErr = ConvertNetworkError(theErr);
- break;
- }
- }
- exit:
- if (!theErr && !m_bInDestructor &&
- (m_pPostEncodedSendHTTP->GetQueuedItemCount() > 0 ||
- m_PendingWriteBuffers.GetCount() > 0)){
- m_pSchedulerCallback->ScheduleCallback(CLOAKED_TCP_PUTWRITE_COMMAND, m_pScheduler, SCHED_GRANULARITY);
- }
- if (!theErr)
- {
- theErr = DoGetWrite();
- }
- m_bInDoPutWrite = FALSE;
- return theErr;
- }
- void
- HXClientCloakedTCPSocket::GetConnectDone(BOOL bResult)
- {
- m_bGetConnectDone = TRUE;
- if (!m_bInDestructor)
- {
- AddRef();
- }
- if (bResult == TRUE)
- {
- m_bGetConnectSuccessful = TRUE;
- m_pGetCtrl->GetForeignAddress(m_lForeignAddress);
- }
- else
- {
- m_bGetConnectSuccessful = FALSE;
- }
- // PUT connection has to been done at this point
- if (m_bPutConnectDone && m_bConnectResponsePending)
- {
- m_bConnectResponsePending = FALSE;
- // either its HTTP-NG server or we are in re-GET mode
- // where we send GET to the same serverIP returned from
- // POST response
- if (m_bConnectToSameServerIP || m_bReconnectToSameServerIP)
- {
- if (m_bPutConnectSuccessful && m_bGetConnectSuccessful)
- {
- m_bConnected = TRUE;
- m_pMutex->Lock();
- PrepareGetMessage();
- DoGetWrite();
- Read(TCP_BUF_SIZE);
- m_pMutex->Unlock();
- if (m_bConnectToSameServerIP)
- {
- // we haven't call ConnectDone yet
- m_pTCPResponse->ConnectDone(HXR_OK);
- }
- else if (m_bReconnectToSameServerIP)
- {
- // we already called ConnectDone upon the initial
- // GET/POST connect done
- Read(TCP_BUF_SIZE);
- }
- }
- else
- {
- m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
- }
- }
- // don't know the server type yet, keep the old behavior
- // where we send both GET and POST
- else
- {
- if (m_bPutConnectSuccessful && m_bGetConnectSuccessful)
- {
- m_bConnected = TRUE;
- m_pMutex->Lock();
- PreparePostMessage(NULL, 0);
- DoPutWrite();
- PrepareGetMessage();
- DoGetWrite();
- m_pMutex->Unlock();
- m_pTCPResponse->ConnectDone(HXR_OK);
- }
- else
- {
- m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
- }
- }
- }
-
- if (!m_bInDestructor)
- {
- Release();
- }
- }
- void
- HXClientCloakedTCPSocket::PutConnectDone(BOOL bResult)
- {
- HX_RESULT theErr = HXR_OK;
- m_bPutConnectDone = TRUE;
- if (!m_bInDestructor)
- {
- AddRef();
- }
- if (bResult == TRUE)
- {
- m_bPutConnectSuccessful = TRUE;
- }
- else
- {
- m_bPutConnectSuccessful = FALSE;
- }
- // it's HTTP-NG server, we send POST first
- if (m_bConnectToSameServerIP)
- {
- if (m_bPutConnectSuccessful)
- {
- m_pMutex->Lock();
- PreparePostMessage(NULL, 0);
- DoPutWrite();
- if (!m_bPutReadPending)
- {
- m_bPutReadPending = TRUE;
- m_pPutCtrl->Read(TCP_BUF_SIZE);
- }
- m_pMutex->Unlock();
- }
- else
- {
- m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
- }
- }
- // don't know the server type yet, so we send both POST
- // and GET
- else if (m_bGetConnectDone && m_bConnectResponsePending)
- {
- m_bConnectResponsePending = FALSE;
- if (m_bPutConnectSuccessful && m_bGetConnectSuccessful)
- {
- m_bConnected = TRUE;
- m_pMutex->Lock();
- PreparePostMessage(NULL, 0);
- DoPutWrite();
- PrepareGetMessage();
- theErr = DoGetWrite();
- m_pMutex->Unlock();
- m_pTCPResponse->ConnectDone(HXR_OK);
- }
- else
- {
- m_pTCPResponse->ConnectDone(HXR_NET_CONNECT);
- }
- }
- if (!m_bInDestructor)
- {
- Release();
- }
- if (m_bConnected && m_pPostEncodedSendHTTP->GetQueuedItemCount() > 0)
- {
- m_pMutex->Lock();
- DoPutWrite();
- m_pMutex->Unlock();
- }
- }
- HX_RESULT
- HXClientCloakedTCPSocket::DoGetReadDone(HX_RESULT status, IHXBuffer* pInBuffer)
- {
- HX_RESULT theErr = HXR_OK;
- char* pStartAfterDoubleReturn = 0;
- UINT16 count = 0;
- if (AuthenticationRequired(status, pInBuffer))
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- m_bGetReadPending = FALSE;
- if (status != HXR_OK && m_LastError == HXR_OK)
- {
- m_LastError = status;
- }
- if (m_LastError)
- {
- goto exit;
- }
- if (pInBuffer)
- {
- m_pReceiveGetTCP->EnQueue(pInBuffer->GetBuffer(), (UINT16) pInBuffer->GetSize());
- }
- count = m_pReceiveGetTCP->GetQueuedItemCount();
- /*
- * if the 16k padding was not received in one big packet
- * delete the remaining padding
- */
- if (m_bDeletePadding && m_uPadLength > 0)
- {
- UINT16 len = (m_uPadLength <= count ? m_uPadLength : count);
- BYTE* tmpBuf = new BYTE[len];
-
- m_pReceiveGetTCP->DeQueue(tmpBuf, len);
- m_uPadLength -= len;
- if (m_uPadLength == 0)
- {
- m_bDeletePadding = FALSE;
- }
- HX_VECTOR_DELETE(tmpBuf);
- count = m_pReceiveGetTCP->GetQueuedItemCount();
- }
- if (!theErr && !m_bHTTPGetHeaderReadDone && count >= 2 )
- {
- char* pEndLineLocation = 0;
- if (!m_pHTTPHeaderBuffer || m_nHTTPHeaderBufferLength < count+1)
- {
- HX_VECTOR_DELETE(m_pHTTPHeaderBuffer);
- m_nHTTPHeaderBufferLength = count+1 > DEFAULT_HTTP_HEADER_LENGTH ?
- count+1 : DEFAULT_HTTP_HEADER_LENGTH;
- m_pHTTPHeaderBuffer = new char[m_nHTTPHeaderBufferLength];
- if (!m_pHTTPHeaderBuffer)
- {
- theErr = HXR_OUTOFMEMORY;
- goto exit;
- }
- }
- m_pReceiveGetTCP->DeQueue(m_pHTTPHeaderBuffer, count);
- m_pHTTPHeaderBuffer[count] = ' ';
- if ((pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "nn")) ||
- (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rr")) )
- {
- pStartAfterDoubleReturn = pEndLineLocation+2;
- m_bHTTPGetHeaderReadDone = TRUE;
- }
- else if (count >= 4 &&
- (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rnrn")))
- {
- pStartAfterDoubleReturn = pEndLineLocation+4;
- m_bHTTPGetHeaderReadDone = TRUE;
- }
- else
- {
- /* Put back everything in receive queue*/
- m_pReceiveGetTCP->EnQueue(m_pHTTPHeaderBuffer, count);
- goto exit;
- }
- // determine whether we need to issue re-GET to the same serverIP
- // from the POST response
- if (!m_bGetResponsed && !m_bConnectToSameServerIP)
- {
- m_bGetResponsed = TRUE;
- GetServerIPFromResponse(TRUE, m_pHTTPHeaderBuffer);
- if (m_pszGetServerIP && m_pszPutServerIP)
- {
- m_bReconnectToSameServerIP = strcasecmp(m_pszGetServerIP, m_pszPutServerIP);
- }
- if (m_bReconnectToSameServerIP)
- {
- theErr = ReconnectToSameServerIP();
- goto quit;
- }
- }
- /* If we have read the complete header, see if the content is OK..*/
- char* pFound = (char*) HXFindString(m_pHTTPHeaderBuffer, "HTTP/1.0 200 OK");
- if (!pFound)
- {
- pFound = (char*) HXFindString(m_pHTTPHeaderBuffer, "200 OK");
- }
-
- // XXX HP we are phasing out PNM protocol
- // m_pCloakValues is only set in RTSP so we use this to exclude
- // support for redirect in PNM Cloaking
- if (!pFound)
- {
- if (m_pCloakValues)
- {
- pFound = (char*) HXFindString(m_pHTTPHeaderBuffer, "HTTP/1.0 302");
- if (pFound)
- {
- strncpy(pFound, "RTSP", 4); /* Flawfinder: ignore */
- IHXBuffer* pBuffer = new CHXBuffer;
- pBuffer->AddRef();
- pBuffer->Set((UCHAR*) m_pHTTPHeaderBuffer, count);
-
- m_pTCPResponse->ReadDone(HXR_OK, pBuffer);
- pBuffer->Release();
- goto exit;
- }
- }
- theErr = HXR_DOC_MISSING;
- }
- if (!theErr)
- {
- m_pReceiveGetTCP->EnQueue(pStartAfterDoubleReturn,
- (m_pHTTPHeaderBuffer + count) - pStartAfterDoubleReturn);
-
- count = m_pReceiveGetTCP->GetQueuedItemCount();
- }
- }
- /* hmmm... time to read options */
- if (!theErr && count > 0 && !m_bOptionsReceived && m_bHTTPGetHeaderReadDone)
- {
- /* There needs to be atleast 4 bytes to have the response
- * reponse_opcode(HTTP_RV_RESPONSE), response len,
- * actual response(minimum one byte)
- */
- if (count < 3)
- {
- goto exit;
- }
- m_pReceiveGetTCP->DeQueue(m_pInBuf, count);
- if (m_pInBuf[0] == HTTP_RESPONSE)
- {
- m_bOptionsReceived = TRUE;
-
- UINT16 nOptionLen = m_pInBuf[1];
- /* Place any data after the response back in Receive queue.
- * This data needs to be sent to the user*/
- if (count > 2+nOptionLen)
- {
- m_pReceiveGetTCP->EnQueue(m_pInBuf+2+nOptionLen, (count - (2+nOptionLen)));
- }
- theErr = HandleHTTPResponse((UCHAR) m_pInBuf[2]);
- if (!theErr)
- {
- count = m_pReceiveGetTCP->GetQueuedItemCount();
- }
- }
- else if (m_pInBuf[0] == HTTP_RV_RESPONSE)
- {
- if (count < 9)
- {
- m_pReceiveGetTCP->EnQueue(m_pInBuf, count);
- goto exit;
- }
- /*
- * this involves receiving a message from the server of the format:
- * HTTP/1.0 200 OK
- * ...
- * Content-length:2147483000
- * r...O?...16k padding of ZEROs...e
- *
- * r -- HTTP_RV_RESPONSE (same as the 5.0 player)
- * O -- HTTP_OPTION_RESPONSE
- * e -- HTTP_OPT_RESPONSE_END
- */
- BYTE* ptr = (BYTE *)m_pInBuf;
- m_bOptionsReceived = TRUE;
-
- ptr += 2;
- UINT16 nOptionLen = *ptr;
- ptr++;
-
- theErr = HandleHTTPResponse((UCHAR)*ptr);
- ptr++;
- if (!theErr)
- {
- ptr++; // get past the HTTP_OPTION_RESPONSE char 'O'
- m_uPadLength = (UINT16)getshort(ptr);
- ptr += 2;
- // skip over the short padding option
- m_uPadLength += 1; // for the 'e' at the end of the 16k padding
- m_pReceiveGetTCP->EnQueue(ptr,
- (m_uPadLength <= (count - (ptr - (BYTE *)m_pInBuf))
- ? m_uPadLength : (count - (ptr - (BYTE *)m_pInBuf))));
- count = m_pReceiveGetTCP->GetQueuedItemCount();
- // get rid of the padding sent with the first response
- UINT16 len = (m_uPadLength <= count ? m_uPadLength : count);
- BYTE* tmpBuf = new BYTE[len];
-
- m_pReceiveGetTCP->DeQueue(tmpBuf, len);
- m_uPadLength -= len;
- if (m_uPadLength > 0)
- {
- m_bDeletePadding = TRUE;
- }
- // if we got more than the 16k initial buffer, put it back
- if (len && len < count)
- m_pReceiveGetTCP->EnQueue(&m_pInBuf[len], count-len);
- HX_VECTOR_DELETE(tmpBuf);
- count = m_pReceiveGetTCP->GetQueuedItemCount();
- }
- }
- else
- {
- theErr = HXR_BAD_SERVER;
- goto exit;
- }
- }
- if (!theErr && m_bReadPending && count > 0 && m_bOptionsReceived
- && m_bHTTPGetHeaderReadDone)
- {
- /* mask any kind of errors */
- theErr = HXR_OK;
- if (IsSafe())
- {
- m_bReadPending = FALSE;
- if (m_nRequired < count)
- {
- count = m_nRequired;
- }
- CHXBuffer* pBuffer = new CHXBuffer;
- pBuffer->AddRef();
- m_pReceiveGetTCP->DeQueue(m_pInBuf, count);
- pBuffer->Set((UCHAR*) m_pInBuf, count);
-
- m_pTCPResponse->ReadDone(HXR_OK, pBuffer);
- pBuffer->Release();
- }
- }
- exit:
- if (theErr && !m_LastError)
- {
- m_LastError = theErr;
- }
- if (m_LastError)
- {
- if (m_bReadPending)
- {
- if (IsSafe())
- {
- m_bReadPending = FALSE;
- m_pTCPResponse->ReadDone(m_LastError, 0);
- }
- }
- }
- if (!m_LastError)
- {
- DoPutWrite();
- DoRead();
- }
- quit:
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::DoPutReadDone(HX_RESULT status, IHXBuffer* pInBuffer)
- {
- HX_RESULT rc = HXR_OK;
- UINT16 count = 0;
- m_bPutReadPending = FALSE;
- if (HXR_OK != status)
- {
- rc = status;
- goto cleanup;
- }
- // stop processing either we already processed one PUT response or
- // we are in multi-post mode
- if (!m_bPutResponsed && !m_bMustCloseHTTP)
- {
- if (!m_pReceivePutTCP)
- {
- m_pReceivePutTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
- if (!m_pReceivePutTCP || !m_pReceivePutTCP->IsQueueValid())
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- m_pReceivePutTCP->SetMaxSize(TCP_BUF_SIZE);
- }
- if (pInBuffer)
- {
- m_pReceivePutTCP->EnQueue(pInBuffer->GetBuffer(), (UINT16) pInBuffer->GetSize());
- }
- count = m_pReceivePutTCP->GetQueuedItemCount();
- if (count >= 2)
- {
- char* pEndLineLocation = 0;
- if (!m_pHTTPHeaderBuffer || m_nHTTPHeaderBufferLength < count+1)
- {
- HX_VECTOR_DELETE(m_pHTTPHeaderBuffer);
- m_nHTTPHeaderBufferLength = count+1 > DEFAULT_HTTP_HEADER_LENGTH ?
- count+1 : DEFAULT_HTTP_HEADER_LENGTH;
- m_pHTTPHeaderBuffer = new char[m_nHTTPHeaderBufferLength];
- if (!m_pHTTPHeaderBuffer)
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- }
- m_pReceivePutTCP->DeQueue(m_pHTTPHeaderBuffer, count);
- m_pHTTPHeaderBuffer[count] = ' ';
- if ((pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "nn")) ||
- (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rr")) )
- {
- m_bHTTPPutHeaderReadDone = TRUE;
- }
- else if (count >= 4 &&
- (pEndLineLocation = (char*) HXFindString(m_pHTTPHeaderBuffer, "rnrn")))
- {
- m_bHTTPPutHeaderReadDone = TRUE;
- }
- else
- {
- /* Put back everything in receive queue*/
- m_pReceivePutTCP->EnQueue(m_pHTTPHeaderBuffer, count);
- goto cleanup;
- }
- m_bPutResponsed = TRUE;
- GetServerIPFromResponse(FALSE, m_pHTTPHeaderBuffer);
- if (m_bConnectToSameServerIP)
- {
- rc = ActualConnect();
- }
- else
- {
- if (m_pszPutServerIP && m_pPreferredTransport)
- {
- m_pPreferredTransport->SetHTTPNG(TRUE);
- }
- // determine whether we need to issue re-GET to the same serverIP
- // from the POST response
- if (m_pszGetServerIP && m_pszPutServerIP)
- {
- m_bReconnectToSameServerIP = strcasecmp(m_pszGetServerIP, m_pszPutServerIP);
- }
- if (m_bReconnectToSameServerIP)
- {
- rc = ReconnectToSameServerIP();
- }
- }
- }
- }
- cleanup:
- return rc;
- }
- void
- HXClientCloakedTCPSocket::TransferBuffers()
- {
- IHXBuffer* pBuffer = 0;
- HX_RESULT theErr = HXR_OK;
- if (m_bInTransferBuffers)
- {
- return;
- }
- m_bInTransferBuffers = TRUE;
- /*This is where we need to add POST header for multiple POST case*/
- while (m_PendingWriteBuffers.GetCount() > 0)
- {
- pBuffer = (IHXBuffer*) m_PendingWriteBuffers.GetHead();
- if ((UINT16) pBuffer->GetSize() < m_pPreEncodedSendHTTP->GetMaxAvailableElements())
- {
- m_pPreEncodedSendHTTP->EnQueue(pBuffer->GetBuffer(),
- (UINT16) pBuffer->GetSize());
- pBuffer->Release();
- m_PendingWriteBuffers.RemoveHead();
- }
- else
- {
- break;
- }
- }
- UINT16 nCount = m_pPreEncodedSendHTTP->GetQueuedItemCount();
- if (nCount > 0)
- {
- if (m_bCloseHttpAfterWrite)
- {
- ENQUEUE_BYTE(m_pPreEncodedSendHTTP, HTTP_POSTDONE);
- nCount++;
- }
- if (m_bMustCloseHTTP && m_pPutCtrl)
- {
- m_pPutCtrl->Release();
- m_pPutCtrl = 0;
- m_bPutConnectDone = FALSE;
- m_pNetworkServices->CreateTCPSocket(&m_pPutCtrl);
- if (!m_pPutCtrl)
- {
- m_LastError = HXR_OUTOFMEMORY;
- m_bInTransferBuffers = FALSE;
- return;
- }
- m_pPutCtrl->Init(m_pPutCtrlResponse);
- const char* pActualHost = m_pForiegnHost;
- UINT16 nActualPort = m_nForeignPort;
- if (m_pProxyHostName)
- {
- pActualHost = m_pProxyHostName;
- nActualPort = m_nProxyPortNumber;
- }
- m_pPutCtrl->Connect(pActualHost,nActualPort);
- }
- m_pPreEncodedSendHTTP->DeQueue(m_pOutBuf, nCount);
- UINT16 nEncodedCount = TCP_BUF_SIZE;
- EncodeBase64((UCHAR*) m_pOutBuf, nCount, (UCHAR*) m_pOutEncodedBuf, nEncodedCount);
- HX_ASSERT(nEncodedCount <= TCP_BUF_SIZE);
- if (m_bCloseHttpAfterWrite)
- {
- theErr = PreparePostMessage((UCHAR*) m_pOutEncodedBuf, nEncodedCount);
- }
- else
- {
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,m_pOutEncodedBuf, nEncodedCount);
- }
- }
- m_bInTransferBuffers = FALSE;
- }
- /***************************General routines*******/
- HX_RESULT
- HXClientCloakedTCPSocket::PreparePostMessage(const UCHAR *inData, UINT16 inLength)
- {
- HX_RESULT theErr = HXR_OK;
- int count = 0;
- UINT16 postLength = inLength;
-
- // create a temp buffer to help build the HTTP POST message
- char* s = new char[MAX_HTTP_METHOD_BUFSIZE];
- if(s == NULL)
- {
- return HXR_OUTOFMEMORY;
- }
- // build the HTTP POST message
- if(m_pProxyHostName)
- {
- if (m_nForeignPort)
- {
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"POST http://%s:%d/SmpDsBhgRl",m_pForiegnHost, m_nForeignPort);
- }
- else
- {
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"POST http://%s/SmpDsBhgRl",m_pForiegnHost);
- }
- }
- else
- {
- //count = sprintf(s,"POST /SmpDsBhgRl"); /* Flawfinder: ignore */
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"POST /SmpDsBhgRl"); /* Flawfinder: ignore */
- }
-
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- // enqueue the remainder of the POST line
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE," HTTP/1.0rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"User-Agent: RealPlayer G2rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Pragma: no-cachern"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Expires: Mon, 18 May 1974 00:00:00 GMTrn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Accept: application/x-rtsp-tunnelled, */*rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Content-type: application/x-pncmdrn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- CHXString strAuth;
- ObtainAuthenticationInformation(strAuth);
-
- if (!strAuth.IsEmpty())
- {
- strAuth += "rn";
- ENQUEUE_DATA(m_pPostEncodedSendHTTP, (void*)(const char*)strAuth,
- (UINT16)strAuth.GetLength());
- }
- UINT16 guidSize = ::strlen(m_pGuid);
-
- if(m_bUseExactContentLength)
- {
- // add in the size of the GUID (which was not base64 encoded)
- postLength += guidSize + 2; // 2 is for the rn at the end of the GUID!
-
- // we must report the exact size of the post data in the Content-length parameter
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Content-length: %hurn",postLength); /* Flawfinder: ignore */
- }
- else
- {
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Content-length: 32767rn"); /* Flawfinder: ignore */
- }
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- // enqueue the CR LF to indicate end of the POST header
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- // enqueue the GUID (Must be sent with every POST and not base64 encoded)
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,&m_pGuid[0],guidSize);
-
- // enqueue the CR LF to indicate end of the GUID
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,s,count);
- if(inLength > 0)
- {
- // enqueue the actual POST data
- ENQUEUE_DATA(m_pPostEncodedSendHTTP,(char *)inData,inLength);
- }
-
- // clean up allocated buffers
- if(s)
- {
- delete [] s;
- }
- return theErr;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::PrepareGetMessage(void)
- {
- HX_RESULT theErr = HXR_OK;
- IHXBuffer* pBuffer = NULL;
- // create a temp buffer for the HTTP GET message
- char* s = new char[MAX_HTTP_METHOD_BUFSIZE];
-
- if(s == NULL)
- {
- theErr = HXR_OUTOFMEMORY;
- }
-
- /* Flush any prior data in the send queue */
- m_pSendTCP->FlushQueue();
- /* Create a fresh GUID */
- CreateGuid();
- // format the HTTP GET message
- if(!theErr)
- {
- int count = 0;
- // build the HTTP POST message
- if(m_pProxyHostName)
- {
- if (m_nForeignPort)
- {
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"GET http://%s:%d/SmpDsBhgRl",m_pForiegnHost, m_nForeignPort);
- }
- else
- {
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"GET http://%s/SmpDsBhgRl",m_pForiegnHost);
- }
- }
- else
- {
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"GET /SmpDsBhgRl"); /* Flawfinder: ignore */
- }
- ENQUEUE_DATA(m_pSendTCP,s,count);
-
- #if 0 // XXX HP enable this to test re-GET after initial GET/POST response
- // returned with different serverIP
- if (!m_bReconnectToSameServerIP)
- {
- char* pGuid = new char[strlen(m_pGuid)+1];
- memcpy(pGuid, m_pGuid, strlen(m_pGuid)); /* Flawfinder: ignore */
- pGuid[0] = 'z';
- // enqueue the GUID directly after the SmpDsBhgRl tag
- ENQUEUE_DATA(m_pSendTCP,&pGuid[0],::strlen(pGuid));
- HX_VECTOR_DELETE(pGuid);
- }
- else
- #endif
- {
- // enqueue the GUID directly after the SmpDsBhgRl tag
- ENQUEUE_DATA(m_pSendTCP,&m_pGuid[0],::strlen(m_pGuid));
- }
- if (m_pProxyHostName)
- {
- /*
- * enqueue dummy option to tell the server to send a padding
- * of 16k of ZEROs with the first response
- */
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"?1="1""); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- }
- // enqueue the HTTP 1.0 and CR LF
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE," HTTP/1.0rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"User-Agent: RealPlayer G2rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Expires: Mon, 18 May 1974 00:00:00 GMTrn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Pragma: no-cachern"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- count = SafeSprintf(s,MAX_HTTP_METHOD_BUFSIZE,"Accept: application/x-rtsp-tunnelled, */*rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- CHXString strAuth;
- ObtainAuthenticationInformation(strAuth);
- if (!strAuth.IsEmpty())
- {
- strAuth += "rn";
- ENQUEUE_DATA(m_pSendTCP, (void*)(const char*)strAuth,
- (UINT16)strAuth.GetLength());
- }
- // send client information so that GoldPass Admin
- // can generate redirect URL via HTTPCloaking
- if (m_pCloakValues)
- {
- if (HXR_OK == m_pCloakValues->GetPropertyCString("ClientID", pBuffer))
- {
- UINT32 ulNewSize = pBuffer->GetSize()+25;
- s = (char*)realloc(s, ulNewSize);
- if(s)
- {
- count = SafeSprintf(s,ulNewSize,"ClientID: %srn", pBuffer->GetBuffer()); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- }
- else
- {
- theErr = HXR_OUTOFMEMORY;
- }
-
- }
- HX_RELEASE(pBuffer);
- if (HXR_OK == m_pCloakValues->GetPropertyCString("Cookie", pBuffer))
- {
- UINT32 ulNewSize = pBuffer->GetSize()+25;
- s = (char*)realloc(s, ulNewSize);
- if(s)
- {
- count = SafeSprintf(s,ulNewSize,"Cookie: %srn", pBuffer->GetBuffer()); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- }
- else
- {
- theErr = HXR_OUTOFMEMORY;
- }
- }
- HX_RELEASE(pBuffer);
- if (HXR_OK == m_pCloakValues->GetPropertyCString("url", pBuffer))
- {
- UINT32 ulNewSize = pBuffer->GetSize()+25;
- s = (char*)realloc(s, ulNewSize);
- if(s)
- {
- count = SafeSprintf(s,ulNewSize,"X-Actual-URL: %srn", pBuffer->GetBuffer()); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- }
- else
- {
- theErr = HXR_OUTOFMEMORY;
- }
- }
- HX_RELEASE(pBuffer);
- }
- // enqueue the CR LF to indicate the end of the HTTP GET header
- s = (char*)realloc(s, 25);
- if(s)
- {
- count = SafeSprintf(s,25,"rn"); /* Flawfinder: ignore */
- ENQUEUE_DATA(m_pSendTCP,s,count);
- }
- else
- {
- theErr = HXR_OUTOFMEMORY;
- }
- }
-
- // clean up
- HX_DELETE(s);
-
- return theErr;
- }
- void
- HXClientCloakedTCPSocket::CreateGuid(void)
- {
- CHXuuid theGuid;
- uuid_tt uuid;
-
- if (m_pGuid)
- {
- return;
- }
- if(m_pGuid)
- {
- delete [] m_pGuid;
- m_pGuid = NULL;
- }
-
- // generate a new GUID
- HX_RESULT theErr = theGuid.GetUuid(&uuid);
- // HX_RESULT theErr = HXR_OK;
- if(!theErr)
- {
- CHXString theString;
-
- CHXuuid::HXUuidToString((const uuid_tt*)&uuid,&theString);
-
- int length = theString.GetLength();
-
- m_pGuid = new char[length + 1];
-
- if(!m_pGuid)
- {
- theErr = HXR_OUTOFMEMORY;
- }
-
- if(!theErr)
- {
- ::strcpy(m_pGuid,(const char *)theString); /* Flawfinder: ignore */
- m_pGuid[length] = ' ';
- }
-
- if(theErr && m_pGuid)
- {
- delete [] m_pGuid;
- m_pGuid = NULL;
- }
- }
-
- if(theErr) // use our own GUID generator
- {
- theErr = HXR_OK;
- ULONG32 temp = HX_GET_TICKCOUNT();
- if(m_pGuid)
- {
- delete [] m_pGuid;
- m_pGuid = NULL;
- }
-
- m_pGuid = new char[HXGUID_SIZE + 1];
- UINT16 length = SafeSprintf(m_pGuid,HXGUID_SIZE + 1,"%ld",temp);
-
- while(length < HXGUID_SIZE)
- {
- m_pGuid[length++] = '1';
- }
-
- m_pGuid[HXGUID_SIZE] = ' ';
- }
- }
- HX_RESULT
- HXClientCloakedTCPSocket::EncodeBase64(const UCHAR* inData, UINT16 inLength, UCHAR* outData, UINT16& outLength)
- {
- HX_RESULT theErr = HXR_OK;
-
- HX_ASSERT(inData != NULL);
- HX_ASSERT(outData != NULL);
- HX_ASSERT(inLength != 0);
-
- // first base64 encode the buffer
- outLength = (UINT16) BinTo64((const UCHAR*) inData, (ULONG32) inLength,(char *)outData);
- HX_ASSERT(outLength >= inLength);
- return HXR_OK;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::HandleHTTPResponse(UCHAR response)
- {
- HX_RESULT theErr = HXR_OK;
-
- switch(response)
- {
- case HTTP_OK:
- {
- m_bUseExactContentLength = FALSE;
- m_bCloseHttpAfterWrite = FALSE;
- m_bHttpInitialized = TRUE;
- /*force a write of the cached data to be sent to the server*/
- // theErr = control_write();
- }
- break;
-
- case POST_NOT_RECEIVED: // POST message was not received
- {
- if (m_pszGetServerIP)
- {
- HX_VECTOR_DELETE(m_pForiegnHost);
- // use serverIP from GET response for multi-POST
- m_pForiegnHost = new char [strlen(m_pszGetServerIP) + 1];
- if (m_pForiegnHost)
- {
- ::strcpy(m_pForiegnHost, m_pszGetServerIP); /* Flawfinder: ignore */
- }
- else
- {
- theErr = HXR_OUTOFMEMORY;
- }
- }
-
- m_bUseExactContentLength = TRUE;
- m_bCloseHttpAfterWrite = TRUE;
- m_bHttpInitialized = TRUE;
- m_bMustCloseHTTP = TRUE;
- /*force a write of the cached data to be sent to the server*/
- // theErr = control_write();
- }
- break;
-
- case INVALID_GUID:
- {
- /* sent only if the GUID from the Player is already in use
- * Need to regenerate GUID and send everything again
- */
- /// TBD - Rahul
- if (m_pGuid)
- {
- delete [] m_pGuid;
- m_pGuid = 0;
- }
- PrepareGetMessage();
- theErr = DoGetWrite();
- }
- break;
- default:
- {
- // shut this clip down and report an appropriate error
- theErr = HXR_HTTP_CONTENT_NOT_FOUND;
- }
- break;
- }
-
- return theErr;
- }
- /* If we are at interrupt time and the response object is not interrupt safe,
- * schedule a callback to return back the data
- */
- BOOL
- HXClientCloakedTCPSocket::IsSafe()
- {
- if (m_pInterruptState && m_pInterruptState->AtInterruptTime() &&
- (!m_pResponseInterruptSafe ||
- !m_pResponseInterruptSafe->IsInterruptSafe()))
- {
- if (m_pNonInterruptCallback){
- m_pNonInterruptCallback->ScheduleCallback(CLOAKED_TCP_READ_COMMAND, m_pScheduler, 0);
- }
- return FALSE;
- }
- return TRUE;
- }
- void
- HXClientCloakedTCPSocket::FlushQueues(void)
- {
- if (m_pSendTCP)
- {
- m_pSendTCP->FlushQueue();
- }
- if (m_pReceiveGetTCP)
- {
- m_pReceiveGetTCP->FlushQueue();
- }
- if (m_pReceivePutTCP)
- {
- m_pReceivePutTCP->FlushQueue();
- }
- if (m_pPreEncodedSendHTTP)
- {
- m_pPreEncodedSendHTTP->FlushQueue();
- }
- if (m_pPostEncodedSendHTTP)
- {
- m_pPostEncodedSendHTTP->FlushQueue();
- }
- }
- void
- HXClientCloakedTCPSocket::SendHTTPDone(void)
- {
- CHXBuffer* pBuffer = new CHXBuffer;
- pBuffer->AddRef();
- BYTE http_done = HTTP_DONE;
- pBuffer->Set((UCHAR*) &http_done, 1);
- m_PendingWriteBuffers.AddTail((void*) pBuffer);
- TransferBuffers();
- DoPutWrite();
- }
- HX_RESULT
- HXClientCloakedTCPSocket::ActualConnect(void)
- {
- HX_RESULT rc = HXR_OK;
- const char* pActualHost = m_pForiegnHost;
- UINT16 nActualPort = m_nForeignPort;
- if (m_pProxyHostName)
- {
- pActualHost = m_pProxyHostName;
- nActualPort = m_nProxyPortNumber;
- }
- if (m_bConnectToSameServerIP)
- {
- if (m_bPutConnectSuccessful)
- {
- rc = m_pGetCtrl->Connect(pActualHost,nActualPort);
- }
- else
- {
- rc = m_pPutCtrl->Connect(pActualHost,nActualPort);
- }
- rc = ConvertNetworkError(rc);
- }
- else
- {
- rc = m_pGetCtrl->Connect(pActualHost,nActualPort);
- rc = ConvertNetworkError(rc);
- if (rc == HXR_OK && !m_bReconnectToSameServerIP)
- {
- rc = m_pPutCtrl->Connect(pActualHost,nActualPort);
- rc = ConvertNetworkError(rc);
- }
- }
- return rc;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::GetServerIPFromResponse(BOOL bGetResponse, const char* pszInBuffer)
- {
- HX_RESULT rc = HXR_OK;
- UINT8 nLength = 0;
- char* pszServerIPStart = NULL;
- char* pszServerIPEnd = NULL;
- char* pszServerIP = NULL;
- if (!pszInBuffer)
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- pszServerIPStart = (char*)HXFindString(pszInBuffer, "x-server-ip-address:");
- if (pszServerIPStart)
- {
- pszServerIPStart += strlen("x-server-ip-address:");
- // removing leading spaces
- while (*pszServerIPStart == ' ')
- {
- pszServerIPStart++;
- }
- pszServerIPEnd = (char*)HXFindString(pszServerIPStart, "rn");
- if (pszServerIPEnd)
- {
- nLength = pszServerIPEnd - pszServerIPStart;
- pszServerIP = new char[nLength + 1];
- memset(pszServerIP, 0, nLength + 1);
- strncpy(pszServerIP, pszServerIPStart, nLength); /* Flawfinder: ignore */
- if (bGetResponse)
- {
- HX_VECTOR_DELETE(m_pszGetServerIP);
- m_pszGetServerIP = pszServerIP;
- }
- else
- {
- HX_VECTOR_DELETE(m_pszPutServerIP);
- m_pszPutServerIP = pszServerIP;
- }
- }
- }
- cleanup:
- return rc;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::CleanUpAndReInitializeStuff(void)
- {
- HX_RESULT rc = HXR_OK;
- IHXBuffer* pBuffer = NULL;
- m_pMutex->Lock();
- const char* pActualHost = m_pForiegnHost;
- UINT16 nActualPort = m_nForeignPort;
- if (m_pProxyHostName)
- {
- pActualHost = m_pProxyHostName;
- nActualPort = m_nProxyPortNumber;
- }
- if (m_pReceiveGetTCP)
- {
- m_pReceiveGetTCP->FlushQueue();
- }
- /* Send a final HTTP done message */
- if (m_bHttpInitialized)
- {
- SendHTTPDone();
- }
- if (m_pSchedulerCallback)
- {
- m_pSchedulerCallback->Unschedule(m_pScheduler);
- }
- if (m_pNonInterruptCallback)
- {
- m_pNonInterruptCallback->Unschedule(m_pScheduler);
- }
- HX_RELEASE(m_pGetCtrl);
- HX_RELEASE(m_pPutCtrl);
-
- m_bHTTPGetHeaderReadDone = FALSE;
- m_bOptionsReceived = FALSE;
- m_bReadPending = FALSE;
- m_bGetReadPending = FALSE;
- m_bGetConnectDone = FALSE;
- m_bGetConnectSuccessful = FALSE;
- m_bConnectResponsePending = TRUE;
- m_bConnected = FALSE;
- m_bPutConnectDone = FALSE;
- m_bPutReadPending = FALSE;
- m_bInAuthenticationKludge = TRUE;
-
- // OK, clean up is done so now we re-initialize.
-
-
- // use serverIP from PUT response for GET reconnect
-
- if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pGetCtrl))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- if (HXR_OK != m_pGetCtrl->Init(m_pGetCtrlResponse))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- if (HXR_OK != m_pGetCtrl->Bind(HXR_INADDR_ANY, 0))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
-
- rc = m_pGetCtrl->Connect(pActualHost, nActualPort);
- if (HXR_OK != rc)
- {
- goto cleanup;
- }
- if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pPutCtrl))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- if (HXR_OK != m_pPutCtrl->Init(m_pPutCtrlResponse))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- if (HXR_OK != m_pPutCtrl->Bind(HXR_INADDR_ANY, 0))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- rc = m_pPutCtrl->Connect(pActualHost, nActualPort);
- if (HXR_OK != rc) goto cleanup;
- cleanup:
- m_pMutex->Unlock();
- return rc;
- }
- HX_RESULT
- HXClientCloakedTCPSocket::ReconnectToSameServerIP(void)
- {
- HX_RESULT rc = HXR_OK;
- IHXBuffer* pBuffer = NULL;
- m_pMutex->Lock();
- if (m_pReceiveGetTCP)
- {
- m_pReceiveGetTCP->FlushQueue();
- }
- /* Send a final HTTP done message */
- if (m_bHttpInitialized)
- {
- SendHTTPDone();
- }
- if (m_pSchedulerCallback)
- {
- m_pSchedulerCallback->Unschedule(m_pScheduler);
- }
- if (m_pNonInterruptCallback)
- {
- m_pNonInterruptCallback->Unschedule(m_pScheduler);
- }
- HX_RELEASE(m_pGetCtrl);
- HX_RELEASE(m_pGetCtrlResponse);
-
- m_bHTTPGetHeaderReadDone = FALSE;
- m_bOptionsReceived = FALSE;
- m_bReadPending = FALSE;
- m_bGetReadPending = FALSE;
- m_bGetConnectDone = FALSE;
- m_bGetConnectSuccessful = FALSE;
- m_bConnectResponsePending = TRUE;
- m_bConnected = FALSE;
- HX_VECTOR_DELETE(m_pForiegnHost);
- // use serverIP from PUT response for GET reconnect
- m_pForiegnHost = new char [strlen(m_pszPutServerIP) + 1];
- if (!m_pForiegnHost)
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- ::strcpy(m_pForiegnHost, m_pszPutServerIP); /* Flawfinder: ignore */
-
- if (HXR_OK != m_pNetworkServices->CreateTCPSocket(&m_pGetCtrl))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- m_pGetCtrlResponse = new HTTPCloakTCPResponse(this, TRUE);
- if (!m_pGetCtrlResponse)
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- m_pGetCtrlResponse->AddRef();
- if (HXR_OK != m_pGetCtrl->Init(m_pGetCtrlResponse))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- if (HXR_OK != m_pGetCtrl->Bind(HXR_INADDR_ANY, 0))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- rc = ActualConnect();
- cleanup:
- m_pMutex->Unlock();
- return rc;
- }
- BOOL
- HXClientCloakedTCPSocket::AuthenticationRequired(HX_RESULT status, IHXBuffer* pInBuffer)
- {
- if (!pInBuffer)
- {
- return FALSE;
- }
- // start of authenticated proxy logic.
- HTTPParser Parser;
- char* pBufferContents = (char*)(const char*)pInBuffer->GetBuffer();
- ULONG32 nMsgLen = pInBuffer->GetSize();
- HTTPResponseMessage* pMessage = (HTTPResponseMessage*)Parser.parse( pBufferContents, nMsgLen );
- // ignore non-HTTP responses which will be processed by the response object:
- // RTSPClientProtocol
- if (HTTPMessage::T_UNKNOWN == pMessage->tag())
- {
- return FALSE;
- }
- ULONG32 ulHTTPStatus = 0;
- if (strlen(pMessage->errorCode()) > 0)
- {
- ulHTTPStatus = atoi(pMessage->errorCode());
- }
- if (ulHTTPStatus == 401 || ulHTTPStatus == 407)
- {
- #ifdef _MACINTOSH
- if (!IsMacInCooperativeThread())
- {
- // xxxbobclark Since there's UI involved with authentication,
- // we'll ensure that we're not at interrupt time.
- if (m_pAuthenticationCallback && !m_pAuthenticationCallback->m_ulPendingCallbackID)
- {
- m_pAuthenticationCallback->m_ulPendingCallbackID =
- m_pScheduler->RelativeEnter(m_pAuthenticationCallback, 0);
- m_pAuthenticationCallback->m_Status = status;
- pInBuffer->AddRef();
- m_pAuthenticationCallback->m_pInBuffer = pInBuffer;
- }
- HX_DELETE(pMessage);
- return TRUE;
- }
- #endif
- IHXRequest* pRequest = NULL;
- IHXCommonClassFactory* pCCF;
- HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF);
-
- if (SUCCEEDED(retVal))
- {
- retVal = pCCF->CreateInstance(CLSID_IHXRequest, (void**)&pRequest);
- if(retVal == HXR_OK)
- {
- PrepareGetMessage(); // set up m_pSendTCP
- UINT16 count = m_pSendTCP->GetQueuedItemCount();
- m_pSendTCP->DeQueue(m_pOutBuf,count);
- retVal = pRequest->SetURL(m_pOutBuf);
- IHXKeyValueList* pResponseHeaders = NULL;
- pCCF->CreateInstance(CLSID_IHXKeyValueList, (void**)&pResponseHeaders);
- MIMEHeaderValue* pHeaderValue = NULL;
- MIMEHeader* pHeader = pMessage->getFirstHeader();
- while (pHeader)
- {
- pHeaderValue = pHeader->getFirstHeaderValue();
- CHXString strHeader;
- while (pHeaderValue)
- {
- CHXString strTemp;
- pHeaderValue->asString(strTemp);
- strHeader += strTemp;
- pHeaderValue = pHeader->getNextHeaderValue();
- if (pHeaderValue)
- {
- strHeader += ", ";
- }
- }
- IHXBuffer* pBuffer = NULL;
- CHXBuffer::FromCharArray((const char*)strHeader, &pBuffer);
- pResponseHeaders->AddKeyValue(pHeader->name(), pBuffer);
- HX_RELEASE(pBuffer);
- pHeader = pMessage->getNextHeader();
- }
- IHXValues* pResponseValues = NULL;
- if (HXR_OK == pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseValues))
- {
- pRequest->SetResponseHeaders(pResponseValues);
- }
- HandleAuthentication(pRequest, pMessage, m_pForiegnHost, m_pProxyHostName);
- HX_RELEASE(pResponseValues);
- HX_RELEASE(pResponseHeaders);
- }
- HX_RELEASE(pCCF);
- }
- HX_DELETE(pMessage);
- return TRUE;
- }
- HX_DELETE(pMessage);
- return FALSE;
- }
- #define CLOAKED_WWW_AUTHENTICATION_RECENT_KEY "authentication.http.realm.recent"
- #define CLOAKED_PROXY_AUTHENTICATION_RECENT_KEY "proxy-authentication.http.realm.recent"
- void
- HXClientCloakedTCPSocket::ObtainAuthenticationInformation(CHXString& strAuth)
- {
- IHXBuffer* pBuffer = NULL;
- CHXString key("no-authentication-information");
- CHXString recentAuthRealmInfo;
- CHXString recentProxyAuthRealmInfo;
- IHXBuffer* pHeaderBuffer = NULL;
-
- HX_RESULT theErr = HXR_OK;
- IHXRegistry* pRegistry = NULL;
-
- m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- HX_ASSERT(pRegistry);
-
- if (!pRegistry) return;
-
- theErr = pRegistry->GetStrByName(CLOAKED_WWW_AUTHENTICATION_RECENT_KEY, pHeaderBuffer);
- if (SUCCEEDED(theErr))
- {
- HX_ASSERT(pHeaderBuffer);
- recentAuthRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
- HX_RELEASE(pHeaderBuffer);
- }
- theErr = pRegistry->GetStrByName(CLOAKED_PROXY_AUTHENTICATION_RECENT_KEY, pHeaderBuffer);
- if (SUCCEEDED(theErr))
- {
- HX_ASSERT(pHeaderBuffer);
- recentProxyAuthRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
- HX_RELEASE(pHeaderBuffer);
- }
- key = "proxy-authentication.http:";
- key += m_pProxyHostName;
- key += ":";
- key += recentProxyAuthRealmInfo;
- if (HXR_OK == pRegistry->GetStrByName((const char*)key, pBuffer) )
- {
- if (pBuffer)
- {
- CHXString authString((const char*)pBuffer->GetBuffer(), pBuffer->GetSize());
- strAuth = "Proxy-Authorization: ";
- strAuth += (const char*)authString;
- }
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pRegistry);
- }
- HX_RESULT
- HXClientCloakedTCPSocket::HandleAuthentication(IHXRequest* pRequest, HTTPResponseMessage* pMessage,
- const char* pHost, const char* pProxyHost)
- {
- HX_RESULT ResultStatus = HXR_OK;
- UINT32 ulAltURL = 0;
- CHXString sConnection;
- IHXValues* pNewHeaders = NULL;
- // xxxbobclark The reason we need to extract the IHXPlayer is that
- // later on the authenticator smart pointer needs a context which knows
- // about authentication conversations. this->m_pContext does not know
- // about the authentication conversation. That's why we have to iterate
- // through the players looking for someone. Sheesh.
- if (!pRequest)
- {
- return HXR_UNEXPECTED;
- }
- HX_RESULT retVal = HXR_OK;
- IHXRegistry* pRegistry = NULL;
- retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- if (SUCCEEDED(retVal))
- {
- IHXCommonClassFactory* pCCF;
- retVal = m_pCloakContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF);
-
- if (SUCCEEDED(retVal))
- {
- IHXValues* pResponseHeaders = NULL;
-
- HX_ASSERT(pRequest);
- if (HXR_OK == pRequest->GetResponseHeaders(pResponseHeaders))
- {
- IHXBuffer* pServerHeaderBuffer = NULL;
- HX_ASSERT(pHost);
- if (pHost)
- {
- retVal = pCCF->CreateInstance(CLSID_IHXBuffer,
- (void**)&pServerHeaderBuffer);
- if (SUCCEEDED(retVal))
- {
- UINT32 ulHTTPStatus = atoi(pMessage->errorCode());
- if (ulHTTPStatus == 407 && pProxyHost)
- {
- pServerHeaderBuffer->Set((UCHAR*)pProxyHost, strlen(pProxyHost)+1);
- }
- else
- {
- pServerHeaderBuffer->Set((UCHAR*)pHost, strlen(pHost)+1);
- }
- pResponseHeaders->SetPropertyCString("_server", pServerHeaderBuffer);
- HX_RELEASE(pServerHeaderBuffer);
- }
- }
- // Add the protocol to the response headers because TLC needs it
- IHXBuffer* pProtocol = NULL;
- if (SUCCEEDED(pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pProtocol)))
- {
- pProtocol->Set((UCHAR*)"http", strlen("http") + 1);
- pResponseHeaders->SetPropertyCString("_protocol", pProtocol);
- HX_RELEASE(pProtocol);
- }
- }
- if (!spClientAuthConversationAuthenticator.IsValid())
- {
- DECLARE_SMART_POINTER_UNKNOWN spUnknownAuthenticator;
- DECLARE_SMART_POINTER
- (
- IHXObjectConfiguration
- ) spObjectConfigurationAuthenticator;
- DECLARE_SMART_POINTER
- (
- IHXCommonClassFactory
- ) spCommonClassFactoryHXCore;
- spCommonClassFactoryHXCore = m_pCloakContext;
- // Starting conversation
- ResultStatus = spCommonClassFactoryHXCore->CreateInstance
- (
- CLSID_CHXClientAuthenticator,
- (void**)&spUnknownAuthenticator
- );
- if ( SUCCEEDED(ResultStatus) && spUnknownAuthenticator.IsValid() )
- {
- spObjectConfigurationAuthenticator =
- (
- spUnknownAuthenticator
- );
- spObjectConfigurationAuthenticator->SetContext(m_pCloakContext);
- spClientAuthConversationAuthenticator =
- (
- spUnknownAuthenticator
- );
- }
- }
- if ( spClientAuthConversationAuthenticator.IsValid()
- && !spClientAuthConversationAuthenticator->IsDone() )
- {
- HX_ASSERT(pRequest);
- if (pRequest)
- {
- ResultStatus =
- (
- spClientAuthConversationAuthenticator->MakeResponse
- (
- this,
- pRequest
- )
- );
- // Flow continues in ResponseReady()
- }
- else
- {
- // Auth Failed!
- spClientAuthConversationAuthenticator->Authenticated(FALSE);
- ResponseReady(HXR_NOT_AUTHORIZED, pRequest);
- }
- }
- HX_RELEASE(pCCF);
- }
-
- HX_RELEASE(pRegistry);
- }
-
- return ResultStatus;
- }
- // IHXClientAuthResponse
- STDMETHODIMP
- HXClientCloakedTCPSocket::ResponseReady( HX_RESULT ResultStatus, IHXRequest* pRequestResponse)
- {
- // now if it's an OK result, then I can use pRequestResponse in a new get.
- if (FAILED(ResultStatus))
- {
- return ResultStatus;
- }
- IHXValues* pHeaders = NULL;
- HX_ASSERT(pRequestResponse);
- if (HXR_OK == pRequestResponse->GetRequestHeaders(pHeaders))
- {
- const char* pName;
- IHXBuffer* pBuf;
- HX_RESULT res = pHeaders->GetFirstPropertyCString(pName, pBuf);
- while (res == HXR_OK)
- {
- if (!strcasecmp(pName, "Proxy-Authorization"))
- {
- HX_RESULT retVal = HXR_OK;
- IHXRegistry* pRegistry = NULL;
- retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- IHXCommonClassFactory* pCCF = NULL;
- if (m_pContext)
- {
- m_pContext->AddRef();
- // get the CCF
- m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCCF);
- }
-
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pBuffer = NULL;
- retVal = pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- UINT32 regid = 0;
-
- HX_ASSERT(SUCCEEDED(retVal));
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pHeaderBuffer = NULL;
- CHXString key;
- CHXString recentRealmInfo = "";
- if (!strcasecmp(pName, "Proxy-Authorization"))
- {
- key = "proxy-authentication.http:";
- retVal = pRegistry->GetStrByName(CLOAKED_PROXY_AUTHENTICATION_RECENT_KEY,
- pHeaderBuffer);
- if (SUCCEEDED(retVal))
- {
- HX_ASSERT(pHeaderBuffer);
- recentRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
- HX_RELEASE(pHeaderBuffer);
- }
- key += m_pProxyHostName;
- }
- key += ":";
- key += recentRealmInfo;
- HX_ASSERT(!key.IsEmpty());
- pBuffer->Set(pBuf->GetBuffer(), pBuf->GetSize());
- regid = pRegistry->GetId((const char*)key);
- if (!regid)
- {
- pRegistry->AddStr((const char*)key, pBuffer);
- }
- else
- {
- pRegistry->SetStrByName((const char*)key, pBuffer);
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pHeaderBuffer);
- }
- }
- HX_RELEASE(pCCF);
- }
- HX_RELEASE(pBuf);
- res = pHeaders->GetNextPropertyCString(pName, pBuf);
- }
- }
- CleanUpAndReInitializeStuff();
- return HXR_OK;
- }
- STDMETHODIMP
- HXClientCloakedTCPSocket::HandleCallback(INT32 theCommand, HX_RESULT theError)
- {
- if (!m_bInDestructor)
- {
- m_pMutex->Lock();
- DoGetWrite();
- DoPutWrite();
- DoRead();
- m_pMutex->Unlock();
- }
- return HXR_OK;
- }
- HXClientCloakedTCPSocket::HTTPCloakTCPResponse::HTTPCloakTCPResponse(HXClientCloakedTCPSocket* pOwner, BOOL bIsRead) :
- m_pOwner(pOwner)
- ,m_lRefCount(0)
- ,m_bIsRead(bIsRead)
- {
- }
- HXClientCloakedTCPSocket::HTTPCloakTCPResponse::~HTTPCloakTCPResponse()
- {
- }
- /*
- * IUnknown methods
- */
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::QueryInterface
- // Purpose:
- // Implement this to export the interfaces supported by your
- // object.
- //
- STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IHXTCPResponse), (IHXTCPResponse*)this },
- { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*)this },
- { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXTCPResponse*)this },
- };
-
- return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::AddRef
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::HTTPCloakTCPResponse::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::Release
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32) HXClientCloakedTCPSocket::HTTPCloakTCPResponse::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- /*
- * IHXTCPResponse methods
- */
- STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::ConnectDone(HX_RESULT status)
- {
- // xxxbobclark this authentication kludge is to ensure that layers "above" me
- // never have to care whether they're using an authenticated proxy or not.
- // So since this cloaked socket has already called its owner with ConnectDone
- // messages, it won't resend those... rather, it will reconstruct the same state
- // that the above layer expects.
- // So we set it up so the next ReadDone will work through the proxy and pass
- // through to the above layer and everything should be cool.
- if (m_pOwner->m_bInAuthenticationKludge)
- {
- m_pOwner->m_bInAuthenticationKludge = FALSE;
- if (m_bIsRead)
- {
- m_pOwner->PreparePostMessage(NULL, 0);
- m_pOwner->DoPutWrite();
- m_pOwner->PrepareGetMessage();
- m_pOwner->DoGetWrite();
- }
- m_pOwner->Read(4096);
- m_pOwner->m_bConnected = TRUE;
- return HXR_OK;
- }
- if (m_bIsRead)
- {
- m_pOwner->GetConnectDone(status == HXR_OK ? TRUE : FALSE);/*m_pGetCtrl*/
- }
- else
- {
- m_pOwner->PutConnectDone(status == HXR_OK ? TRUE : FALSE);/*m_pPutCtrl*/
- }
- return HXR_OK;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::ReadDone( HX_RESULT status,
- IHXBuffer* pBuffer)
- {
- if (m_bIsRead)
- {
- m_pOwner->DoGetReadDone(status, pBuffer); /*m_pGetCtrl*/
- }
- else
- {
- m_pOwner->DoPutReadDone(status, pBuffer); /*m_pPutCtrl*/
- }
- return HXR_OK;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::WriteReady(HX_RESULT status)
- {
- if (m_bIsRead)
- {
- m_pOwner->m_pMutex->Lock();
- m_pOwner->DoGetWrite(); /*m_pGetCtrl*/
- m_pOwner->m_pMutex->Unlock();
- }
- else
- {
- m_pOwner->m_bPutWantWritePending = FALSE;
- m_pOwner->m_pMutex->Lock();
- m_pOwner->DoPutWrite(); /*m_pPutCtrl*/
- m_pOwner->m_pMutex->Unlock();
- }
- return HXR_OK;
- }
- STDMETHODIMP HXClientCloakedTCPSocket::HTTPCloakTCPResponse::Closed(HX_RESULT status)
- {
- return HXR_OK;
- }
- #ifdef _MACINTOSH
- HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::MacCloakedTCPSocketAuthenticationCallback (
- HXClientCloakedTCPSocket* pSocket)
- : m_lRefCount(0)
- , m_ulPendingCallbackID(NULL)
- , m_pSocket(pSocket)
- , m_Status(HXR_OK)
- , m_pInBuffer(NULL)
- {
- }
- HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::~MacCloakedTCPSocketAuthenticationCallback()
- {
- }
- STDMETHODIMP
- HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::QueryInterface(
- REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this },
- { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXCallback*)this },
- };
-
- return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- STDMETHODIMP_(ULONG32)
- HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::AddRef()
- {
- return InterlockedIncrement( &m_lRefCount );
- }
- STDMETHODIMP_(ULONG32)
- HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::Release()
- {
- if ( InterlockedDecrement( &m_lRefCount ) > 0 )
- {
- return m_lRefCount;
- }
-
- delete this;
- return 0;
- }
- STDMETHODIMP
- HXClientCloakedTCPSocket::MacCloakedTCPSocketAuthenticationCallback::Func()
- {
- m_ulPendingCallbackID = NULL;
-
- if (m_pInBuffer)
- {
- m_pSocket->DoGetReadDone(m_Status, m_pInBuffer);
- HX_RELEASE(m_pInBuffer);
- }
-
- return HXR_OK;
- }
- #endif