/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: HTTP class for HTTP::HEAD testing
*
*/
#include <implementationproxy.h>
#include <uri8.h>
#include "ictshttphandler.h"
#include "ictsengine.h"
#include "am_debug.h"
// CONSTANTS
_LIT8( KHeaderName, "X-Nokia-WLAN-Connectivity-Test" );
_LIT8( KHeaderValue, "true" );
_LIT8( KHttpPrefix, "http://" );
const TInt KMovedPermanently = 301;
const TInt KFound = 302;
const TInt KSeeOther = 303;
const TInt KTemporaryRedirect = 307;
// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// CIctsHttpHandler::CIctsHttpHandler
// C++ default constructor can NOT contain any code, that
// might leave.
// ---------------------------------------------------------------------------
//
CIctsHttpHandler::CIctsHttpHandler( CIctsEngine& aOwner,
TInt aHttpResponseTime ) :
CTimer( EPriorityLow ), iOwner( aOwner ),
iHttpResponseTime( aHttpResponseTime ), iAttachDone( EFalse )
{
CActiveScheduler::Add( this );
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::ConstructL
// ---------------------------------------------------------------------------
//
void CIctsHttpHandler::ConstructL()
{
DEBUG("CIctsHttpHandler::ConstructL()");
// Open channel to Socket Server
User::LeaveIfError( iSocketServ.Connect() );
// Open connection
User::LeaveIfError( iConnection.Open(iSocketServ) );
CTimer::ConstructL();
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::NewL
// ---------------------------------------------------------------------------
//
CIctsHttpHandler* CIctsHttpHandler::NewL( CIctsEngine& aOwner,
TInt aHttpResponseTime )
{
DEBUG("CIctsHttpHandler::NewL()");
CIctsHttpHandler* self = new( ELeave ) CIctsHttpHandler( aOwner, aHttpResponseTime );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::~CIctsHttpHandler
// ---------------------------------------------------------------------------
//
CIctsHttpHandler::~CIctsHttpHandler()
{
DEBUG("CIctsHttpHandler::~CIctsHttpHandler()");
RHTTPTransaction notActive;
if ( iHttpTransaction != notActive )
{
iHttpTransaction.Close();
}
iHttpSession.Close();
CTimer::Cancel();
iConnection.Close();
iSocketServ.Close();
DEBUG("CIctsHttpHandler::~CIctsHttpHandler() Done");
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::SetHttpConnectionInfoL
// ---------------------------------------------------------------------------
//
void CIctsHttpHandler::SetHttpConnectionInfoL( RConnection& aConnection,
RSocketServ& aSocketServ)
{
DEBUG("CIctsHttpHandler::SetHttpConnectionInfoL");
TInt result;
TBuf<16> serviceType;
TUint32 serviceId;
TBuf<100> query;
TUint connCount;
iHttpSession.Close();
iHttpSession.OpenL();
RStringPool strPool = iHttpSession.StringPool();
// Remove first session properties just in case.
RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
// Clear RConnection and Socket Server instances
connInfo.RemoveProperty(strPool.StringF(HTTP::EHttpSocketServ,RHTTPSession::GetTable()));
connInfo.RemoveProperty(strPool.StringF(HTTP::EHttpSocketConnection,RHTTPSession::GetTable()));
// Clear the proxy settings
THTTPHdrVal proxyUsage(strPool.StringF(HTTP::EUseProxy,RHTTPSession::GetTable()));
connInfo.RemoveProperty(strPool.StringF(HTTP::EProxyUsage,RHTTPSession::GetTable()));
connInfo.RemoveProperty(strPool.StringF(HTTP::EProxyAddress,RHTTPSession::GetTable()));
// RConnection has been started, set proxy (if defined) and RConnection and
// Socket Server session properties.
// Proxy
result = aConnection.EnumerateConnections(connCount);
User::LeaveIfError(result);
// Get service and service type for this connection
//
_LIT(string, "%s\\%s");
query.Format(string, IAP, IAP_SERVICE);
result = aConnection.GetIntSetting(query, serviceId);
query.Format(string, IAP, IAP_SERVICE_TYPE);
result = aConnection.GetDesSetting(query, serviceType);
User::LeaveIfError(result);
// RConnection and Socket Server
// Now bind the HTTP session with the socket server connection
connInfo.SetPropertyL (
strPool.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable()),
THTTPHdrVal (aSocketServ.Handle()) );
TInt connPtr1 = reinterpret_cast<TInt>(&aConnection);
connInfo.SetPropertyL (
strPool.StringF(HTTP::EHttpSocketConnection,
RHTTPSession::GetTable() ), THTTPHdrVal (connPtr1) );
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::SendHttpRequestL
// ---------------------------------------------------------------------------
//
TInt CIctsHttpHandler::SendHttpRequestL( TDesC8& aIPAddress,
TUint32 aIapID,
TUint32 aNetworkId )
{
DEBUG("CIctsHttpHandler::SendHttpRequestL");
// Cancel possibly outstanding request for polling reasons.
CTimer::Cancel();
TConnectionInfo info;
TPckg< TConnectionInfo > pckgInfo( info );
info.iIapId = aIapID;
info.iNetId = aNetworkId;
TInt err( KErrNone );
if ( !iAttachDone )
{
err = iConnection.Attach( pckgInfo, RConnection::EAttachTypeMonitor);
DEBUG1("CIctsHttpHandler::SendHttpRequestL attach: %d", err);
}
if ( KErrNone == err )
{
iAttachDone = ETrue;
SetHttpConnectionInfoL( iConnection, iSocketServ );
// Remove redirect filter
RStringPool stringPool = iHttpSession.StringPool();
RStringF filterName = stringPool.StringF(HTTP::ERedirect, RHTTPSession::GetTable());
iHttpSession.FilterCollection().RemoveFilter(filterName);
RStringPool strPool = iHttpSession.StringPool();
RStringF method = strPool.StringF(HTTP::EHEAD,RHTTPSession::GetTable());
TBuf8<KMaxIpLength> ip;
TBool httpExists = CheckHttp( aIPAddress );
if ( !httpExists )
{
ip.Copy( KHttpPrefix );
}
ip.Append( aIPAddress );
// Parse string to URI
TUriParser8 uri;
uri.Parse(ip);
iHttpTransaction = iHttpSession.OpenTransactionL(uri, *this, method);
RHTTPHeaders hdr = iHttpTransaction.Request().GetHeaderCollection();
RStringF headerStrName = strPool.OpenFStringL( KHeaderName() );
CleanupClosePushL( headerStrName );
RStringF headerStrValue = strPool.OpenFStringL( KHeaderValue() );
CleanupClosePushL( headerStrValue );
THTTPHdrVal headerValue( headerStrValue );
hdr.SetFieldL( headerStrName, headerValue );
CleanupStack::PopAndDestroy( &headerStrValue );
CleanupStack::PopAndDestroy( &headerStrName );
iHttpTransaction.SubmitL();
DEBUG("CIctsHttpHandler::SendHttpGetL SubmitL() done");
CTimer::After( iHttpResponseTime );
}
return err;
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::CancelHttpRequestL
// ---------------------------------------------------------------------------
//
void CIctsHttpHandler::CancelHttpRequestL()
{
DEBUG("CIctsHttpHandler::CancelHttpRequestL()");
CTimer::Cancel();
RHTTPTransaction notActive;
if ( iHttpTransaction != notActive )
{
iHttpTransaction.Close();
}
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::RunL
// ---------------------------------------------------------------------------
//
void CIctsHttpHandler::RunL()
{
DEBUG("CIctsHttpHandler::RunL()");
RHTTPTransaction notActive;
if ( iHttpTransaction != notActive )
{
iHttpTransaction.Close();
}
iString = KNullDesC;
iOwner.HttpEventL( ETimeout, iString );
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::MHFRunL
//
// Inherited from MHTTPTransactionCallback
// Called by framework to pass transaction events.
// ---------------------------------------------------------------------------
//
void CIctsHttpHandler::MHFRunL(RHTTPTransaction aTransaction,
const THTTPEvent& aEvent)
{
DEBUG("CIctsHttpHandler::MHFRunL");
switch (aEvent.iStatus)
{
case THTTPEvent::EGotResponseHeaders:
{
DEBUG("CIctsHttpHandler::THTTPEvent::EGotResponseHeaders");
}
break;
case THTTPEvent::EGotResponseBodyData:
{
DEBUG("CIctsHttpHandler::THTTPEvent::EGotResponseBodyData");
}
break;
case THTTPEvent::EResponseComplete:
{
DEBUG("CIctsHttpHandler::THTTPEvent::EResponseComplete");
}
break;
case THTTPEvent::ESucceeded:
{
DEBUG("CIctsHttpHandler::THTTPEvent::ESucceeded");
CTimer::Cancel();
iOwner.HttpEventL( EConnectionOk, iString );
iString = KNullDesC;
}
break;
case THTTPEvent::EFailed:
{
CTimer::Cancel();
DEBUG("CIctsHttpHandler::THTTPEvent::EFailed");
RHTTPResponse resp = aTransaction.Response();
TInt status = resp.StatusCode();
// Check if redirect was cause of EFailed
if( status == KMovedPermanently || status == KFound ||
status == KSeeOther || status == KTemporaryRedirect )
{
// Inform the hotspot server that authentication is needed
RHTTPHeaders hdr =aTransaction.Response().GetHeaderCollection();
RStringPool strP = aTransaction.Session().StringPool();
RStringF location = strP.StringF(HTTP::ELocation,RHTTPSession::GetTable());
//parse the headers and look for location header
THTTPHdrVal hVal;
if(hdr.GetField(location,0,hVal)== KErrNone)
{
DEBUG("CIctsHttpHandler::THTTPEvent::GetField");
// Location header is present
RStringF fieldValStr = strP.StringF(hVal.StrF());
const TDesC8& fieldValDesC = fieldValStr.DesC();
iString.Copy(fieldValDesC);
iOwner.HttpEventL( EHttpAuthenticationNeeded, iString );
}
else
{
// No location header. Can't use authentication -> redirect.
iOwner.HttpEventL( EConnectionNotOk, iString );
}
}
else
{
// Failed for other reason than redirect
iOwner.HttpEventL( EConnectionNotOk, iString );
}
iString = KNullDesC;
}
break;
case THTTPEvent::ERedirectedPermanently:
{
// Nothing here
DEBUG("CIctsHttpHandler::THTTPEvent::ERedirectedPermanently");
}
break;
case THTTPEvent::ERedirectedTemporarily:
{
// Nothing here
DEBUG("CIctsHttpHandler::THTTPEvent::ERedirectedTemporarily");
}
break;
default:
{
DEBUG1( "CIctsHttpHandler::MHFRunL::default iStatus: %d", aEvent.iStatus );
CTimer::Cancel();
if ( aEvent.iStatus < 0 )
{
_LIT(string, "Unknown error");
iString = string;
iOwner.HttpEventL( EConnectionNotOk, iString );
}
else
{
_LIT(string, "Default");
iString = string;
iOwner.HttpEventL( EConnectionNotOk, iString );
}
}
break;
}
}
// ---------------------------------------------------------------------------
// CIctsHttpHandler::MHFRunError
//
// Inherited from MHTTPTransactionCallback
// Called by framework to pass transaction error.
// ---------------------------------------------------------------------------
//
TInt CIctsHttpHandler::MHFRunError( TInt /*aError*/,
RHTTPTransaction /*aTransaction*/,
const THTTPEvent& /*aEvent*/)
{
DEBUG("CIctsHttpHandler::MHFRunError");
return KErrNone;
}
// ----------------------------------------------------------------------------
// CIctsHttpHandler::CheckHttp
// ----------------------------------------------------------------------------
TBool CIctsHttpHandler::CheckHttp( TDesC8& aIPAddress )
{
// The "http://" prefix is expected to be at the beginning of the URI.
return ( 0 == aIPAddress.Find( KHttpPrefix ) );
}
// End of File