| 2 |      1 | // HttpClient.cpp
 | 
|  |      2 | 
 | 
|  |      3 | 
 | 
|  |      4 | #include <e32base.h>
 | 
|  |      5 | #include <http/rhttpheaders.h>
 | 
|  |      6 | #include <http.h>
 | 
|  |      7 | #include <commdb.h>
 | 
|  |      8 | #include <eikenv.h>
 | 
|  |      9 | #include <es_sock.h>
 | 
|  |     10 | #include <bautils.h>
 | 
|  |     11 | #include <CommDbConnPref.h>
 | 
|  |     12 | #include "debug.h"
 | 
|  |     13 | #include "constants.h"
 | 
|  |     14 | #include "HttpClient.h"
 | 
|  |     15 | #include "connectionengine.h"
 | 
|  |     16 | #include "settingsengine.h"
 | 
|  |     17 | 
 | 
|  |     18 | const TInt KTempBufferSize = 100;
 | 
|  |     19 | 
 | 
|  |     20 | CHttpClient::~CHttpClient()
 | 
|  |     21 |   {
 | 
|  |     22 |   if (iHandler)
 | 
|  |     23 |   	{
 | 
|  |     24 |   	iHandler->CloseSaveFile();
 | 
|  |     25 | 	delete iHandler;
 | 
|  |     26 |   	}
 | 
|  |     27 |   
 | 
|  |     28 |   iSession.Close();
 | 
|  |     29 |   }
 | 
|  |     30 | 
 | 
|  |     31 | CHttpClient* CHttpClient::NewL(CPodcastModel& aPodcastModel, MHttpClientObserver& aObserver)
 | 
|  |     32 |   {
 | 
|  |     33 |   CHttpClient* me = NewLC(aPodcastModel, aObserver);
 | 
|  |     34 |   CleanupStack::Pop(me);
 | 
|  |     35 |   return me;
 | 
|  |     36 |   }
 | 
|  |     37 | 
 | 
|  |     38 | CHttpClient::CHttpClient(CPodcastModel& aPodcastModel, MHttpClientObserver& aObserver) : iPodcastModel(aPodcastModel), iObserver(aObserver)
 | 
|  |     39 |   {
 | 
|  |     40 |   iResumeEnabled = EFalse;
 | 
|  |     41 |   }
 | 
|  |     42 | 
 | 
|  |     43 | CHttpClient* CHttpClient::NewLC(CPodcastModel& aPodcastModel, MHttpClientObserver& aObserver)
 | 
|  |     44 |   {
 | 
|  |     45 |   CHttpClient* me = new (ELeave) CHttpClient(aPodcastModel, aObserver);
 | 
|  |     46 |   CleanupStack::PushL(me);
 | 
|  |     47 |   me->ConstructL();
 | 
|  |     48 |   return me;
 | 
|  |     49 |   }
 | 
|  |     50 | 
 | 
|  |     51 | void CHttpClient::ConstructL()
 | 
|  |     52 |   {
 | 
|  |     53 |   iPodcastModel.ConnectionEngine().AddObserver(this);
 | 
|  |     54 |   }
 | 
|  |     55 | 
 | 
|  |     56 | void CHttpClient::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
 | 
|  |     57 | 	{
 | 
|  |     58 | 	RStringF valStr = iSession.StringPool().OpenFStringL(aHdrValue);
 | 
|  |     59 | 	THTTPHdrVal val(valStr);
 | 
|  |     60 | 	aHeaders.SetFieldL(iSession.StringPool().StringF(aHdrField, RHTTPSession::GetTable()), val);
 | 
|  |     61 | 	valStr.Close();
 | 
|  |     62 | 	}
 | 
|  |     63 | 
 | 
|  |     64 | TBool CHttpClient::IsActive()
 | 
|  |     65 | 	{
 | 
|  |     66 | 	return iIsActive;
 | 
|  |     67 | 	}
 | 
|  |     68 | 
 | 
|  |     69 | void CHttpClient::SetResumeEnabled(TBool aEnabled)
 | 
|  |     70 | 	{
 | 
|  |     71 | 	iResumeEnabled = aEnabled;
 | 
|  |     72 | 	}
 | 
|  |     73 | 
 | 
|  |     74 | 
 | 
|  |     75 | void CHttpClient::ConnectHttpSessionL()
 | 
|  |     76 | {
 | 
|  |     77 | 	DP("ConnectHttpSessionL START");	
 | 
|  |     78 | 	CConnectionEngine::TConnectionState connState = iPodcastModel.ConnectionEngine().ConnectionState();
 | 
|  |     79 | 	if(connState == CConnectionEngine::EConnected)
 | 
|  |     80 | 		{
 | 
|  |     81 | 		DP("ConnectionState == CConnectionEngine::EConnected");
 | 
|  |     82 | 		// Session already connected, call connect complete directly but return status since URLs or so might be faulty
 | 
|  |     83 | 		ConnectCompleteL(KErrNone);		
 | 
|  |     84 | 		return;
 | 
|  |     85 | 		}
 | 
|  |     86 | 
 | 
|  |     87 | 	if(connState == CConnectionEngine::ENotConnected)
 | 
|  |     88 | 		{
 | 
|  |     89 | 		DP1("SpecificIAP() == %d",iPodcastModel.SettingsEngine().SpecificIAP());
 | 
|  |     90 | 
 | 
|  |     91 | 		if(iPodcastModel.SettingsEngine().SpecificIAP() == -1)
 | 
|  |     92 | 			{
 | 
|  |     93 | 			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EUserSelectConnection);	
 | 
|  |     94 | 			}
 | 
|  |     95 | 		else if ( iPodcastModel.SettingsEngine().SpecificIAP() == 0 )
 | 
|  |     96 | 			{
 | 
|  |     97 | 			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EDefaultConnection);	
 | 
|  |     98 | 			}
 | 
|  |     99 | 		else if( (iPodcastModel.SettingsEngine().SpecificIAP()&KUseIAPFlag))
 | 
|  |    100 | 			{
 | 
|  |    101 | 			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EIAPConnection);
 | 
|  |    102 | 			}
 | 
|  |    103 | 		else
 | 
|  |    104 | 			{
 | 
|  |    105 | 			iPodcastModel.ConnectionEngine().StartL(CConnectionEngine::EMobilityConnection);
 | 
|  |    106 | 			}
 | 
|  |    107 | 		}
 | 
|  |    108 | 	DP("ConnectHttpSessionL END");	
 | 
|  |    109 | }
 | 
|  |    110 | 
 | 
|  |    111 | void CHttpClient::ConnectCompleteL(TInt aErrorCode)
 | 
|  |    112 | 	{
 | 
|  |    113 | 	if(iWaitingForGet)
 | 
|  |    114 | 		{
 | 
|  |    115 | 		iWaitingForGet = EFalse;
 | 
|  |    116 | 		if( aErrorCode == KErrNone)
 | 
|  |    117 | 			{
 | 
|  |    118 | 			RHTTPConnectionInfo connInfo = iSession.ConnectionInfo();
 | 
|  |    119 | 			RStringPool pool = iSession.StringPool();
 | 
|  |    120 | 			// Attach to socket server
 | 
|  |    121 | 			connInfo.SetPropertyL(pool.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable()), THTTPHdrVal(iPodcastModel.ConnectionEngine().SockServ().Handle()));
 | 
|  |    122 | 			// Attach to connection
 | 
|  |    123 | 			TInt connPtr = REINTERPRET_CAST(TInt, &iPodcastModel.ConnectionEngine().Connection());
 | 
|  |    124 | 			connInfo.SetPropertyL(pool.StringF(HTTP::EHttpSocketConnection, RHTTPSession::GetTable()), THTTPHdrVal(connPtr));
 | 
|  |    125 | 
 | 
|  |    126 | 
 | 
|  |    127 | 			iPodcastModel.SetProxyUsageIfNeededL(iSession);
 | 
|  |    128 | 			DoGetAfterConnectL();		
 | 
|  |    129 | 			}
 | 
|  |    130 | 		else
 | 
|  |    131 | 			{
 | 
|  |    132 | 			ClientRequestCompleteL(KErrCouldNotConnect);
 | 
|  |    133 | 			iSession.Close();			
 | 
|  |    134 | 			}
 | 
|  |    135 | 		}				
 | 
|  |    136 | 	}
 | 
|  |    137 | 
 | 
|  |    138 | void CHttpClient::Disconnected()
 | 
|  |    139 | 	{
 | 
|  |    140 | 	iIsActive = EFalse;
 | 
|  |    141 | 	iSession.Close();
 | 
|  |    142 | 	}
 | 
|  |    143 | 
 | 
|  |    144 | void  CHttpClient::DoGetAfterConnectL()
 | 
|  |    145 | 	{	
 | 
|  |    146 | 	// since nothing should be downloading now. Delete the handler
 | 
|  |    147 | 	if (iHandler)
 | 
|  |    148 | 		{
 | 
|  |    149 | 		delete iHandler;
 | 
|  |    150 | 		iHandler = NULL;
 | 
|  |    151 | 		}
 | 
|  |    152 | 		
 | 
|  |    153 | 	iHandler = CHttpEventHandler::NewL(this, iObserver, iPodcastModel.FsSession());
 | 
|  |    154 | 	iHandler->SetSilent(iSilentGet);
 | 
|  |    155 | 
 | 
|  |    156 | 	TEntry entry;
 | 
|  |    157 | 	TBuf8<KTempBufferSize> rangeText;
 | 
|  |    158 | 
 | 
|  |    159 | 	if (iResumeEnabled && iPodcastModel.FsSession().Entry(iCurrentFileName, entry) == KErrNone) {
 | 
|  |    160 | 		DP1("Found file, with size=%d", entry.iSize);
 | 
|  |    161 | 		// file exists, so we should probably resume
 | 
|  |    162 | 		rangeText.Format(_L8("bytes=%d-"), entry.iSize-KByteOverlap);
 | 
|  |    163 | 		iHandler->SetSaveFileName(iCurrentFileName, ETrue);
 | 
|  |    164 | 	} else {
 | 
|  |    165 | 		// otherwise just make sure the directory exists
 | 
|  |    166 | 		BaflUtils::EnsurePathExistsL(iPodcastModel.FsSession(),iCurrentFileName);
 | 
|  |    167 | 		iHandler->SetSaveFileName(iCurrentFileName);
 | 
|  |    168 | 	}
 | 
|  |    169 | 	
 | 
|  |    170 | 	RStringPool strP = iSession.StringPool();
 | 
|  |    171 | 	RStringF method;
 | 
|  |    172 | 	method = strP.StringF(HTTP::EGET, RHTTPSession::GetTable());
 | 
|  |    173 | 	
 | 
|  |    174 | 	iTrans = iSession.OpenTransactionL(iUriParser, *iHandler, method);
 | 
|  |    175 | 	RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection();
 | 
|  |    176 | 	// Add headers appropriate to all methods
 | 
|  |    177 | 	SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent);
 | 
|  |    178 | 	SetHeaderL(hdr, HTTP::EAccept, KAccept);
 | 
|  |    179 | 	TBuf<KTempBufferSize> range16;
 | 
|  |    180 | 	range16.Copy(rangeText);
 | 
|  |    181 | 	DP1("range text: %S", &range16);
 | 
|  |    182 | 	if (rangeText.Length() > 0) {
 | 
|  |    183 | 		SetHeaderL(hdr, HTTP::ERange, rangeText);
 | 
|  |    184 | 	}
 | 
|  |    185 | 	iTransactionCount++;
 | 
|  |    186 | 	// submit the transaction
 | 
|  |    187 | 	iTrans.SubmitL();
 | 
|  |    188 | 	iIsActive = ETrue;	
 | 
|  |    189 | 	DP("CHttpClient::Get END");		
 | 
|  |    190 | 	}
 | 
|  |    191 | 
 | 
|  |    192 | TBool CHttpClient::GetL(const TDesC& aUrl, const TDesC& aFileName,  TBool aSilent) {
 | 
|  |    193 | 	DP("CHttpClient::Get START");
 | 
|  |    194 | 	DP2("Getting '%S' to '%S'", &aUrl, &aFileName);	
 | 
|  |    195 | 	__ASSERT_DEBUG((iIsActive==EFalse), User::Panic(_L("Already active"), -2));
 | 
|  |    196 | 	iCurrentURL.Copy(aUrl);	
 | 
|  |    197 | 		
 | 
|  |    198 | 	TInt urlError = iUriParser.Parse(iCurrentURL);
 | 
|  |    199 | 
 | 
|  |    200 | 	if(urlError != KErrNone ||!iUriParser.IsSchemeValid())
 | 
|  |    201 | 		{		
 | 
|  |    202 | 		iCurrentURL = KNullDesC8;
 | 
|  |    203 | 		iSession.Close();		
 | 
|  |    204 | 		iObserver.CompleteL(this, KErrHttpInvalidUri);
 | 
|  |    205 | 		return EFalse;		
 | 
|  |    206 | 		}	
 | 
|  |    207 | 	
 | 
|  |    208 | 	iSilentGet = aSilent;
 | 
|  |    209 | 	iCurrentFileName.Copy(aFileName);
 | 
|  |    210 | 	iWaitingForGet = ETrue;
 | 
|  |    211 | 	
 | 
|  |    212 | 	if (iTransactionCount == 0) 
 | 
|  |    213 | 		{
 | 
|  |    214 | 		DP("CHttpClient::GetL\t*** Opening HTTP session ***");
 | 
|  |    215 | 		iSession.Close();
 | 
|  |    216 | 		iSession.OpenL();
 | 
|  |    217 | 		ConnectHttpSessionL();			
 | 
|  |    218 | 		}
 | 
|  |    219 | 	else
 | 
|  |    220 | 		{
 | 
|  |    221 | 		DoGetAfterConnectL();		
 | 
|  |    222 | 		}
 | 
|  |    223 | 	return ETrue;
 | 
|  |    224 | }
 | 
|  |    225 | 
 | 
|  |    226 | void CHttpClient::Stop()
 | 
|  |    227 | 	{
 | 
|  |    228 | 	iIsActive = EFalse;
 | 
|  |    229 | 	if(iHandler != NULL)
 | 
|  |    230 | 		{
 | 
|  |    231 | 		// cancel the ongoing transaction
 | 
|  |    232 | 		iTrans.Cancel();
 | 
|  |    233 | 		iTransactionCount = 0;
 | 
|  |    234 | 		
 | 
|  |    235 | 		// make sure that we save the file
 | 
|  |    236 | 		iHandler->CloseSaveFile();
 | 
|  |    237 | 		
 | 
|  |    238 | 		// we could now delete the handler since a new will be created
 | 
|  |    239 | 		delete iHandler;
 | 
|  |    240 | 		iHandler = NULL;
 | 
|  |    241 | 		
 | 
|  |    242 | 		// close the session
 | 
|  |    243 | 		DP("CHttpClient::Stop\t*** Closing HTTP session ***");
 | 
|  |    244 | 		iSession.Close();
 | 
|  |    245 | 		}
 | 
|  |    246 | 
 | 
|  |    247 | 	TRAP_IGNORE(iObserver.CompleteL(this, KErrDisconnected));
 | 
|  |    248 | 
 | 
|  |    249 | 	}
 | 
|  |    250 | 
 | 
|  |    251 | void CHttpClient::ClientRequestCompleteL(TInt aErrorCode) {
 | 
|  |    252 | 	iIsActive = EFalse;
 | 
|  |    253 | 	iObserver.CompleteL(this, aErrorCode);
 | 
|  |    254 | 	DP("CHttpClient::ClientRequestCompleteL");
 | 
|  |    255 | 	if(iTransactionCount>0)
 | 
|  |    256 | 		{
 | 
|  |    257 | 		iTransactionCount--;
 | 
|  |    258 | 	
 | 
|  |    259 | 		if(iTransactionCount == 0) 
 | 
|  |    260 | 			{
 | 
|  |    261 | 			DP("CHttpClient::ClientRequestCompleteL\t*** Closing HTTP session ***");
 | 
|  |    262 | 			delete iHandler;
 | 
|  |    263 | 			iHandler = NULL;
 | 
|  |    264 | 			iSession.Close();
 | 
|  |    265 | 			}
 | 
|  |    266 | 		}
 | 
|  |    267 | }
 |