engine/src/HttpClient.cpp
author Sebastian Brannstrom <sebastianb@symbian.org>
Sun, 31 Oct 2010 14:15:37 +0000
branchRCL_3
changeset 321 7a0fb290f9c6
parent 310 2e0299e13cbf
child 341 a648d7ca5e27
permissions -rw-r--r--
Re-enabled max items parsed, because disabling this causes shows to turn up as new multiple times. This again breaks feeds that add new shows at the bottom, so we need to solve this properly.

// HttpClient.cpp


#include <e32base.h>
#include <http/rhttpheaders.h>
#include <http.h>
#include <commdb.h>
#include <eikenv.h>
#include <es_sock.h>
#include <bautils.h>
#include <CommDbConnPref.h>
#include "debug.h"
#include "constants.h"
#include "HttpClient.h"
#include "connectionengine.h"
#include "settingsengine.h"
#include "Podcatcher.pan"

const TInt KTempBufferSize = 100;

CHttpClient::~CHttpClient()
  {
	
	iPodcastModel.ConnectionEngine().RemoveObserver(this);
	 
  if (iHandler)
  	{
  	iHandler->CloseSaveFile();
	delete iHandler;
  	}
  
  iSession.Close();
  }

CHttpClient* CHttpClient::NewL(CPodcastModel& aPodcastModel, MHttpClientObserver& aObserver)
  {
  CHttpClient* me = NewLC(aPodcastModel, aObserver);
  CleanupStack::Pop(me);
  return me;
  }

CHttpClient::CHttpClient(CPodcastModel& aPodcastModel, MHttpClientObserver& aObserver) : iPodcastModel(aPodcastModel), iObserver(aObserver)
  {
  iResumeEnabled = EFalse;
  }

CHttpClient* CHttpClient::NewLC(CPodcastModel& aPodcastModel, MHttpClientObserver& aObserver)
  {
  CHttpClient* me = new (ELeave) CHttpClient(aPodcastModel, aObserver);
  CleanupStack::PushL(me);
  me->ConstructL();
  return me;
  }

void CHttpClient::ConstructL()
  {
  iPodcastModel.ConnectionEngine().AddObserver(this);
  }

void CHttpClient::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
	{
	RStringF valStr = iSession.StringPool().OpenFStringL(aHdrValue);
	THTTPHdrVal val(valStr);
	aHeaders.SetFieldL(iSession.StringPool().StringF(aHdrField, RHTTPSession::GetTable()), val);
	valStr.Close();
	}

TBool CHttpClient::IsActive()
	{
	return iIsActive;
	}

void CHttpClient::SetResumeEnabled(TBool aEnabled)
	{
	iResumeEnabled = aEnabled;
	}


void CHttpClient::ConnectHttpSessionL()
{
	DP("ConnectHttpSessionL START");	
	CConnectionEngine::TConnectionState connState = iPodcastModel.ConnectionEngine().ConnectionState();
	if(connState == CConnectionEngine::EConnected)
		{
		DP("ConnectionState == CConnectionEngine::EConnected");
		// Session already connected, call connect complete directly but return status since URLs or so might be faulty
		ConnectCompleteL(KErrNone);		
		return;
		}

	if(connState == CConnectionEngine::ENotConnected)
		{
		DP1("SpecificIAP() == %d",iPodcastModel.SettingsEngine().SpecificIAP());

		if(iPodcastModel.SettingsEngine().SpecificIAP() == -1)
			{
			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EUserSelectConnection);	
			}
		else if ( iPodcastModel.SettingsEngine().SpecificIAP() == 0 )
			{
			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EDefaultConnection);	
			}
		else if( (iPodcastModel.SettingsEngine().SpecificIAP()&KUseIAPFlag))
			{
			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EIAPConnection);
			}
		else
			{
			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EMobilityConnection);
			}
		}
	DP("ConnectHttpSessionL END");	
}

void CHttpClient::ConnectCompleteL(TInt aErrorCode)
	{
	DP1("CHttpClient::ConnectCompleteL BEGIN, aErrorCode=%d", aErrorCode);
	DP1("    iWaitingForGet=%d", iWaitingForGet);
	if(iWaitingForGet)
		{
		iWaitingForGet = EFalse;
		if( aErrorCode == KErrNone)
			{
			TRAP_IGNORE(iSession.OpenL());
			RHTTPConnectionInfo connInfo = iSession.ConnectionInfo();
			RStringPool pool = iSession.StringPool();
			// Attach to socket server
			connInfo.SetPropertyL(pool.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable()), THTTPHdrVal(iPodcastModel.ConnectionEngine().SockServ().Handle()));
			// Attach to connection
			TInt connPtr = REINTERPRET_CAST(TInt, &iPodcastModel.ConnectionEngine().Connection());
			connInfo.SetPropertyL(pool.StringF(HTTP::EHttpSocketConnection, RHTTPSession::GetTable()), THTTPHdrVal(connPtr));

			iPodcastModel.SetProxyUsageIfNeededL(iSession);
			DoGetAfterConnectL();
			}
		else
			{
			ClientRequestCompleteL(KErrCouldNotConnect);
			iSession.Close();			
			}
		}
	DP("CHttpClient::ConnectCompleteL END");
	}

void CHttpClient::Disconnected()
	{
	iIsActive = EFalse;
	iSession.Close();
	}

void  CHttpClient::DoGetAfterConnectL()
	{	
	DP("CHttpClient::DoGetAfterConnectL BEGIN");
	// since nothing should be downloading now. Delete the handler
	if (iHandler)
		{
		delete iHandler;
		iHandler = NULL;
		}
		
	iHandler = CHttpEventHandler::NewL(this, iObserver, iPodcastModel.FsSession());
	iHandler->SetSilent(iSilentGet);

	TEntry entry;
	TBuf8<KTempBufferSize> rangeText;

	if (iResumeEnabled && iPodcastModel.FsSession().Entry(iCurrentFileName, entry) == KErrNone) {
		DP1("    Found file, with size=%d", entry.iSize);
		// file exists, so we should probably resume
		rangeText.Format(_L8("bytes=%d-"), (entry.iSize-KByteOverlap > 0 ? entry.iSize-KByteOverlap : 0));
		iHandler->SetSaveFileName(iCurrentFileName, ETrue);
	} else {
		// otherwise just make sure the directory exists
		BaflUtils::EnsurePathExistsL(iPodcastModel.FsSession(),iCurrentFileName);
		iHandler->SetSaveFileName(iCurrentFileName);
	}
	
	RStringPool strP = iSession.StringPool();
	RStringF method;
	method = strP.StringF(HTTP::EGET, RHTTPSession::GetTable());
	
	iTrans = iSession.OpenTransactionL(iUriParser, *iHandler, method);
	RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection();
	// Add headers appropriate to all methods
	SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent);
	SetHeaderL(hdr, HTTP::EAccept, KAccept);
	TBuf<KTempBufferSize> range16;
	range16.Copy(rangeText);
	DP1("    range text: %S", &range16);
	if (rangeText.Length() > 0) {
		SetHeaderL(hdr, HTTP::ERange, rangeText);
	}
	iTransactionCount++;
	// submit the transaction
	iTrans.SubmitL();
	iIsActive = ETrue;	
	DP("CHttpClient::DoGetAfterConnectL END");
	}

TBool CHttpClient::GetL(const TDesC& aUrl, const TDesC& aFileName,  TBool aSilent) {
	DP("CHttpClient::Get START");
	DP2("Getting '%S' to '%S'", &aUrl, &aFileName);
	
	if (iIsActive)
		{
		return EFalse;
		}
	iCurrentURL.Copy(aUrl);	
		
	TInt urlError = iUriParser.Parse(iCurrentURL);

	if(urlError != KErrNone ||!iUriParser.IsSchemeValid())
		{		
		iCurrentURL = KNullDesC8;
		iSession.Close();		
		iObserver.CompleteL(this, KErrHttpInvalidUri);
		return EFalse;		
		}	
	
	iSilentGet = aSilent;
	iCurrentFileName.Copy(aFileName);
	
	if (iTransactionCount == 0) 
		{
		DP("CHttpClient::GetL\t*** Opening HTTP session ***");
		iSession.Close();
		iSession.OpenL();
		iWaitingForGet = ETrue;
		ConnectHttpSessionL();			
		}
	else
		{
		iWaitingForGet = EFalse;
		DoGetAfterConnectL();		
		}
	return ETrue;
}

void CHttpClient::Stop()
	{
	iIsActive = EFalse;
	if(iHandler != NULL)
		{
		// cancel the ongoing transaction
		iTrans.Cancel();
		iTransactionCount = 0;
		
		// make sure that we save the file
		iHandler->CloseSaveFile();
		
		// we could now delete the handler since a new will be created
		delete iHandler;
		iHandler = NULL;
		
		// close the session
		DP("CHttpClient::Stop\t*** Closing HTTP session ***");
		iSession.Close();
		}

	TRAP_IGNORE(iObserver.CompleteL(this, KErrDisconnected));

	}

void CHttpClient::ClientRequestCompleteL(TInt aErrorCode) {
	DP1("CHttpClient::ClientRequestCompleteL, aErrorCode=%d", aErrorCode);
	iIsActive = EFalse;
	iObserver.CompleteL(this, aErrorCode);
	DP1("    iTransactionCount=%d", iTransactionCount);
	if(iTransactionCount>0)
		{
		iTransactionCount--;
	
		if(iTransactionCount == 0) 
			{
			DP("CHttpClient::ClientRequestCompleteL\t*** Closing HTTP session ***");
			delete iHandler;
			iHandler = NULL;
			iSession.Close();
			}
		}
}