// Copyright (c) 2003-2009 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:
//
#ifndef __CHTTPCONNECTIONMANAGER_H__
#define __CHTTPCONNECTIONMANAGER_H__
#include <e32base.h>
#include <babitflags.h>
#include <stringpool.h>
#include <http/framework/logging.h>
#include "msocketconnectobserver.h"
#include "minputstreamobserver.h"
#include "moutputstreamobserver.h"
#include "mhttprequestobserver.h"
#include "mhttpresponseobserver.h"
#include "mhttpbatchingpropertiescallback.h"
#include "chttpclientoptimiser.h"
class MSocketFactory;
class MSocketConnector;
class MOutputStream;
class MInputStream;
class MHttpRequest;
class MHttpResponse;
class CHttpConnectionInfo;
class CX509Certificate;
class CHttpRequestBatcher;
class MHttpBatchingPropertiesCallback;
class CHttpHostElement : public CBase
{
public:
static CHttpHostElement* New(const TDesC8& aHost);
~CHttpHostElement();
inline const TDesC8& Host() const;
inline void IncFailedCount();
inline TInt FailedCount() const;
inline HBufC8* AcquireHost();
static inline TInt LinkOffset();
private:
TBool Construct(const TDesC8& aHost);
public:
TSglQueLink iLink;
HBufC8* iHost;
};
class CHttpPipelineFallback : public CBase
{
public:
static CHttpPipelineFallback* NewL();
~CHttpPipelineFallback();
TBool NeedPipelineFallback(const TDesC8& aHost);
void InsertPipelineFailedHost(const TDesC8& aHost);
private:
CHttpPipelineFallback();
private:
RPointerArray<HBufC8> iPipelineFailedHosts;
TSglQue<CHttpHostElement> iProbablePipelineFailedHosts;
};
class CHttpConnectionManager : public CBase,
public MHttpRequestObserver,
public MHttpResponseObserver,
public MSocketConnectObserver,
public MInputStreamObserver,
public MOutputStreamObserver
{
public:
enum TConnectionStatus
{
ENotConnected = 0,
EConnectedAndAvailable,
EConnectedNotAvailable,
EConnectedAndBusy,
EConnectingNotAvailable
};
public:
static CHttpConnectionManager* NewL(MSocketFactory& aSocketFactory, MHttpBatchingPropertiesCallback& aCallback,
CHttpPipelineFallback& aPipelineFallback, TInt aMaxTransactionsToPipeline, TBool aEnableOptimalPipeline);
virtual ~CHttpConnectionManager();
void SubmitL(CHttpConnectionInfo& aConnectionInfo, MHttpRequest& aRequest, MHttpResponse& aResponse);
TConnectionStatus Status() const;
const CHttpConnectionInfo& ConnectionInfo() const;
void CancelSubmission(MHttpRequest& aRequest, MHttpResponse& aResponse);
const CX509Certificate* ServerCert();
TInt CipherSuite(TDes8& aCipherSuite);
void TunnelConnection(RStringF aHost);
TBool TunnelMatches(RStringF aHost) const;
void MakeConnectionNonPersistent();
void CheckRequestComplete(MHttpRequest& aRequest);
void DisablePipelining();
void InsertPipelineFailedHost(const TDesC8& aHost);
private: // methods from MHttpRequestObserver
virtual void SendRequestDataL(const TDesC8& aData);
virtual void RequestComplete();
virtual void SendingBodyData(TBool aValue);
private: // methods from MHttpResponseObserver
virtual void ResponseDataParsed();
virtual void ResponseComplete(const TDesC8& aExcessData);
private: // methods from MSocketConnnectObserver
virtual void ConnectionMadeL(MInputStream& aInputStream, MOutputStream& aOutputStream);
virtual TInt HandleConnectError(TInt aError);
virtual void MSocketConnectObserver_Reserved();
private: // methods from MInputStreamObserver
virtual void ReceivedDataIndL(const TDesC8& aBuffer);
virtual void SecureServerCnf();
virtual void InputStreamCloseInd(TInt aError);
virtual void MInputStreamObserver_Reserved();
virtual MHttpResponse* CurrentResponse();
virtual void OnReceiveTimeOut();
private: // methods from MOutputStreamObserver
virtual void SendDataCnfL();
virtual void SecureClientCnf();
virtual void OutputStreamCloseInd(TInt aError);
virtual void MOutputStreamObserver_Reserved();
virtual void OnSendTimeOut();
virtual TInt SendTimeOutVal();
private:
CHttpConnectionManager(MSocketFactory& aSocketFactory, MHttpBatchingPropertiesCallback& aCallback,
CHttpPipelineFallback& aPipelineFallback, TInt aMaxTransactionsToPipeline, TBool aEnableOptimalPipeline);
void HandleSocketError(TInt aError);
void CloseConnection();
void UpgradeConnectionL();
void SetIdleState();
TInt FindRequest(MHttpRequest& aRequest);
TInt FindResponse(MHttpResponse& aResponse);
void NotifyPendingTransactions(TInt aError);
void ReportSocketError(TInt aError);
void ReconnectSocketL();
void DoResponseCompletion ();
inline TBool CannotPipeline() const;
inline TBool IsFirstTransaction() const;
inline TBool IsPendingWriteInConnectedState() const;
inline TBool DiscardSndDataCnf() const;
void CreateOptimiserL(MHttpDataOptimiser* aDataOptimiser);
void StartRecvTimer();
private:
enum TManagerState
{
EIdle = 0,
EIdleConnected,
EConnecting,
EUpgrading,
EConnected,
EClosing
};
enum TConnectionFlag
{
// Cannot currently pipeline.
// So will not queue transactions on this connection Manager.
//
ECannotPipeline = 0,
// Currently sending/receiving the first transaction on this connection,
// so no other requests are sent out till the response from the server is
// examined to see of it can handle pipelining. However transactions are
// still queued on this connection. These will be cancelled with
// KErrNonPipeliningError should the server be HTTP/1.0.
//
EFirstTransaction = 1,
// Specifies that this transaction is waiting to write its
// request to the supposedly connected connection. Due to timing issues
// the server may have closed the connection, but connection manager has
// not been notified yet.
//
EPendingWriteInConnectedState = 2,
// The Response completed before notification, that a request was sent, was received.
// So now we know when confirmation arrives (SndDataCnf) can disregard it.
//
EDiscardSndDataCnf = 3
};
private:
TBool iEnableOptimalPipeline;
TBool iTunnel;
TInt iMaxTransactionsToPipeline;
TBitFlags8 iFlags;
MSocketFactory& iSocketFactory;
TManagerState iState;
MSocketConnector* iSocketConnector;
MOutputStream* iOutputStream;
MInputStream* iInputStream;
MHttpRequest* iCurrentRequest;
MHttpResponse* iCurrentResponse;
TPtrC8 iExcessData;
RStringF iTunnelHost;
CHttpConnectionInfo* iConnectionInfo;
CHttpRequestBatcher* iRequestBatcher;
MHttpBatchingPropertiesCallback& iCallback;
CHttpClientOptimiser* iOptimiser;
RPointerArray<MHttpRequest> iPendingRequests;
RPointerArray<MHttpResponse> iPendingResponses;
CHttpPipelineFallback& iPipelineFallback;
public:
__FLOG_DECLARATION_MEMBER2
};
inline TBool CHttpConnectionManager::CannotPipeline() const
{
return iFlags.IsSet(ECannotPipeline);
}
inline TBool CHttpConnectionManager::IsFirstTransaction() const
{
return iFlags.IsSet(EFirstTransaction);
}
inline TBool CHttpConnectionManager::IsPendingWriteInConnectedState() const
{
return iFlags.IsSet(EPendingWriteInConnectedState);
}
inline TBool CHttpConnectionManager::DiscardSndDataCnf() const
{
return iFlags.IsSet(EDiscardSndDataCnf);
}
inline const TDesC8& CHttpHostElement::Host() const
{
return *iHost;
}
inline HBufC8* CHttpHostElement::AcquireHost()
{
HBufC8* host = iHost;
iHost = NULL;
return host;
}
inline TInt CHttpHostElement::LinkOffset()
{
return _FOFF(CHttpHostElement, iLink);
}
#endif // __CHTTPCONNECTIONMANAGER_H__