applayerpluginsandutils/httpprotocolplugins/WspProtocolHandler/CWspCOProtocolHandler.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 // System includes
       
    17 #include <http/framework/crxdata.h>
       
    18 #include <http/rhttpheaders.h>
       
    19 #include <http/thttpevent.h>
       
    20 #include <httpstringconstants.h>
       
    21 #include <wsp/wsptypes.h>
       
    22 #include <wsp/cwsptransporthandler.h>
       
    23 #include <wsp/mwspcosessioninvoker.h>
       
    24 #include <wsp/mwspcomethodinvoker.h>
       
    25 #include <wspstringconstants.h>
       
    26 #include <wspstdconstants.h>
       
    27 #include <wsperror.h>
       
    28 
       
    29 // User includes
       
    30 #include "cwspcotransaction.h"
       
    31 #include "cwspcapabilityinfo.h"
       
    32 #include "cwspproxyinfoprovider.h"
       
    33 #include "cconnectiontimer.h"
       
    34 #include "cwspprimitivesender.h"
       
    35 #include "wsppanic.h"
       
    36 #include "cwspheaderutils.h"
       
    37 #include "cwspheadercodec.h"
       
    38 
       
    39 // Class signature
       
    40 #include "cwspcoprotocolhandler.h"
       
    41 
       
    42 const TInt KDefaultConnectionTimeMicroSeconds	= 180000000;		// 3 minutes
       
    43 
       
    44 /*
       
    45  * CWspCOProtocolHandler
       
    46  */
       
    47 
       
    48 CWspCOProtocolHandler* CWspCOProtocolHandler::NewL(TAny* aSession)
       
    49 	{
       
    50 	RHTTPSession* session = REINTERPRET_CAST(RHTTPSession*, aSession);
       
    51 	CWspCOProtocolHandler* self = new (ELeave) CWspCOProtocolHandler(*session);
       
    52 	CleanupStack::PushL(self);
       
    53 	self->ConstructL();
       
    54 	CleanupStack::Pop(self);
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 CWspCOProtocolHandler::~CWspCOProtocolHandler()
       
    59 	{
       
    60 	
       
    61 	if( iConnectionTimer )
       
    62 		iConnectionTimer->Cancel();
       
    63 	delete iConnectionTimer;
       
    64 
       
    65 	delete iClientSessionHeaders;
       
    66 	delete iTransportHandler;
       
    67 	delete iClientCapInfo;
       
    68 	delete iNegotiatedCapInfo;
       
    69 	delete iProxyInfoProvider;
       
    70 	delete iPrimitiveSender;
       
    71 	delete iHdrUtils;
       
    72 	}
       
    73 
       
    74 CWspCOProtocolHandler::CWspCOProtocolHandler(RHTTPSession aSession)
       
    75 : CProtocolHandler(aSession), /*iSessionState(ENull),*/ iTimedOutValue(KDefaultConnectionTimeMicroSeconds)
       
    76 	{
       
    77 	__OPEN_LOG("WspProtocolHandler.txt")
       
    78 	}
       
    79 
       
    80 void CWspCOProtocolHandler::ConstructL()
       
    81 	{
       
    82 	CProtocolHandler::ConstructL(iSession);
       
    83 
       
    84 	// Open the WSP header field names table
       
    85 	iSession.StringPool().OpenL(WSP::Table);
       
    86 
       
    87 	// Create the proposed client capability object and the negotiated session capability object
       
    88 	iClientCapInfo = CWspCapabilityInfo::NewL();
       
    89 	iNegotiatedCapInfo = CWspCapabilityInfo::NewL();
       
    90 
       
    91 	// Create the proxy info provider
       
    92 	iProxyInfoProvider = CWspProxyInfoProvider::NewL(iSession);
       
    93 
       
    94 	// Create the connection timer object
       
    95 	iConnectionTimer = CConnectionTimer::NewL(*this);
       
    96 
       
    97 	// Create the primitive sender active object
       
    98 	iPrimitiveSender = CWspPrimitiveSender::NewL(*this);
       
    99 
       
   100 	// Create the transport handler
       
   101 	CreateWspTransportHandlerL();
       
   102 
       
   103 	// Create the WSP header utilities
       
   104 	iHdrUtils = CWspHeaderUtils::NewL(*STATIC_CAST(CWspHeaderCodec*, iCodec));
       
   105 	}
       
   106 
       
   107 void CWspCOProtocolHandler::CreateWspTransportHandlerL()
       
   108 	{
       
   109 	// Assert that the transport handler doesn't already exist
       
   110 	__ASSERT_DEBUG(iTransportHandler == NULL, Panic(KWspPanicTransportHandlerAlreadyExists));
       
   111 
       
   112 	// Pass through the session string pool when creating the transport handler
       
   113 	RStringPool stringPool = iSession.StringPool();
       
   114 	iTransportHandler = CWspTransportHandler::NewL(
       
   115 												  stringPool,
       
   116 												  iSecurityPolicy,
       
   117 												  *this,				// Session CB
       
   118 												  *iProxyInfoProvider,	// Proxy info
       
   119 												  *this,				// Capability info
       
   120 												  *this					// Session headers info
       
   121 												  );
       
   122 
       
   123 	// Check the supported services
       
   124 	CWspTransportHandler::TWspSupportedServices suppSvc = iTransportHandler->SupportedServices();
       
   125 	TBool sessionSupport = suppSvc & CWspTransportHandler::ECOSessionService;
       
   126 	TBool methodSupport  = suppSvc & CWspTransportHandler::ECOMethodInvocationService;
       
   127 	if( !sessionSupport || !methodSupport )
       
   128 		{
       
   129 		__LOG(_L("Session management facility or method invoke facility not supported by transport handler"));
       
   130 		User::Leave(KWspErrRequiredServicesNotSupported);
       
   131 		}
       
   132 	// Configure the session invoker object
       
   133 	iSessionInvoker = &iTransportHandler->COSessionInvoker();
       
   134 	}
       
   135 
       
   136 
       
   137 void CWspCOProtocolHandler::CheckClientCapabilities()
       
   138 	{
       
   139 	// Reset the proposed client properties - sets the capabilities to the 
       
   140 	// default values.
       
   141 	iClientCapInfo->Reset();
       
   142 
       
   143 	// Check the session properties...
       
   144 	RHTTPConnectionInfo	connInfo = iSession.ConnectionInfo();
       
   145 	RStringPool stringPool = iSession.StringPool();
       
   146 
       
   147 	// ...client message size...
       
   148 	THTTPHdrVal clientMessageSize;
       
   149 	TBool hasClientMessageSize = connInfo.Property(stringPool.StringF(HTTP::EWspCapClientMessageSize, RHTTPSession::GetTable()), clientMessageSize);
       
   150 	if( hasClientMessageSize )
       
   151 		{
       
   152 		// Initial attempt to negotiate message size and SDU size will attempt to go
       
   153 		// for a single PDU transfers, so set them the same
       
   154 		__ASSERT_DEBUG( clientMessageSize.Type() == THTTPHdrVal::KTIntVal, Panic(KWspPanicBadClientMessageSize) );
       
   155 		iClientCapInfo->SetClientMessageSize(clientMessageSize.Int());
       
   156 		iClientCapInfo->SetClientSDUSize(clientMessageSize.Int());
       
   157 		}
       
   158 	// ... server message size...
       
   159 	THTTPHdrVal serverMessageSize;
       
   160 	TBool hasServerMessageSize = connInfo.Property(stringPool.StringF(HTTP::EWspCapServerMessageSize, RHTTPSession::GetTable()), serverMessageSize);
       
   161 	if( hasServerMessageSize )
       
   162 		{
       
   163 		// Initial attempt to negotiate message size and SDU size will attempt to go
       
   164 		// for a single PDU transfers, so set them the same
       
   165 		__ASSERT_DEBUG( serverMessageSize.Type() == THTTPHdrVal::KTIntVal, Panic(KWspPanicBadServerMessageSize) );
       
   166 		iClientCapInfo->SetServerMessageSize(serverMessageSize.Int());
       
   167 		iClientCapInfo->SetServerSDUSize(serverMessageSize.Int());
       
   168 		}
       
   169 	// ...method MOR...
       
   170 	THTTPHdrVal methodMOR;
       
   171 	TBool hasMethodMOR = connInfo.Property(stringPool.StringF(HTTP::EWspCapMaxOutstandingRequests, RHTTPSession::GetTable()), methodMOR);
       
   172 	if( hasMethodMOR )
       
   173 		{
       
   174 		__ASSERT_DEBUG( methodMOR.Type() == THTTPHdrVal::KTIntVal, Panic(KWspPanicBadMethodMOR) );
       
   175 		__ASSERT_DEBUG( STATIC_CAST(TUint8, methodMOR.Int()) <= KMaxTUint8, Panic(KWspPanicBadMethodMOR) );
       
   176 		__ASSERT_DEBUG( STATIC_CAST(TUint8, methodMOR.Int()) > 0, Panic(KWspPanicBadMethodMOR) );
       
   177 		iClientCapInfo->SetMethodMOR( STATIC_CAST(TUint8, methodMOR.Int()) );
       
   178 		}
       
   179 	// Sort out the protocol options - by default try to use Large Data Transfer
       
   180 	TUint8 protocolOptions = ELargeDataTransfer;
       
   181 	THTTPHdrVal notUsed;
       
   182 	// ...use acknowledgements...
       
   183 	TBool hasUseAcknowledgements = connInfo.Property(stringPool.StringF(HTTP::EWspCapUseAcknowledgements, RHTTPSession::GetTable()), notUsed);
       
   184 	if( hasUseAcknowledgements )
       
   185 		{
       
   186 		protocolOptions |= EAcknowledgementHeaders;
       
   187 		}
       
   188 	// ...support suspend resume facilty...
       
   189 	TBool hasSuspendResume = connInfo.Property(stringPool.StringF(HTTP::EWspCapSupportSuspendResume, RHTTPSession::GetTable()), notUsed);
       
   190 	if( hasSuspendResume )
       
   191 		{
       
   192 		protocolOptions |= ESessionResumeFacility;
       
   193 		}
       
   194 	iClientCapInfo->SetProtocolOptions(protocolOptions);
       
   195 
       
   196 	// Get the connection time-out value
       
   197 	THTTPHdrVal connectionTimeout;
       
   198 	TBool hasConnectionTimeout = connInfo.Property(stringPool.StringF(HTTP::EWspProxyConnectionTimeout, RHTTPSession::GetTable()), connectionTimeout);
       
   199 	if( hasConnectionTimeout )
       
   200 		{
       
   201 		__ASSERT_DEBUG((connectionTimeout.Type() == THTTPHdrVal::KTIntVal), Panic(KWspPanicBadConenctionTimeout));
       
   202 		iTimedOutValue = connectionTimeout.Int();
       
   203 		}
       
   204 	else
       
   205 		{
       
   206 		// Use the default value
       
   207 		iTimedOutValue = KDefaultConnectionTimeMicroSeconds;
       
   208 		}
       
   209 	}
       
   210 
       
   211 TBool CWspCOProtocolHandler::UpdateNegotiatedCapabilitiesL()
       
   212 	{
       
   213 	// Check the capabilities proposed by the client
       
   214 	TBool capabilitiesReduced = EFalse;
       
   215 
       
   216 	RHTTPConnectionInfo	connInfo = iSession.ConnectionInfo();
       
   217 	RStringPool stringPool = iSession.StringPool();
       
   218 
       
   219 	// ...client message size...
       
   220 	TUint32 clientMessageSize = iNegotiatedCapInfo->GetClientMessageSize();
       
   221 	if( clientMessageSize != iClientCapInfo->GetClientMessageSize() )
       
   222 		{
       
   223 		// The server has reduced the client message size - update the return flag...
       
   224 		capabilitiesReduced = ETrue;
       
   225 
       
   226 		// ...and the session property...
       
   227 		THTTPHdrVal clientMessageSizeProperty = clientMessageSize;
       
   228 		connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspCapClientMessageSize, RHTTPSession::GetTable()), clientMessageSizeProperty);
       
   229 		}
       
   230 	// ...server message size...
       
   231 	TUint32 serverMessageSize = iNegotiatedCapInfo->GetServerMessageSize();
       
   232 	if( serverMessageSize != iClientCapInfo->GetServerMessageSize() )
       
   233 		{
       
   234 		// The server has reduced the server message size - update the return flag...
       
   235 		capabilitiesReduced = ETrue;
       
   236 
       
   237 		// ...and the session property...
       
   238 		THTTPHdrVal serverMessageSizeProperty = serverMessageSize;
       
   239 		connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspCapServerMessageSize, RHTTPSession::GetTable()), serverMessageSizeProperty);
       
   240 		}
       
   241 	// ...method MOR...
       
   242 	TUint32 methodMOR = iNegotiatedCapInfo->GetMethodMOR();
       
   243 	if( methodMOR != iClientCapInfo->GetMethodMOR() )
       
   244 		{
       
   245 		// The server has reduced the method MOR - update the return flag...
       
   246 		capabilitiesReduced = ETrue;
       
   247 
       
   248 		// ...and the session property...
       
   249 		THTTPHdrVal methodMORProperty = methodMOR;
       
   250 		connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspCapMaxOutstandingRequests, RHTTPSession::GetTable()), methodMORProperty);
       
   251 		}
       
   252 	// Check the protocol options
       
   253 	TUint8 protocolOptions = iNegotiatedCapInfo->GetProtocolOptions();
       
   254 
       
   255 	// ...acknowledgements...
       
   256 	if( (protocolOptions & EAcknowledgementHeaders) != (iClientCapInfo->GetProtocolOptions() & EAcknowledgementHeaders) )
       
   257 		{
       
   258 		// The server has cleared the use acknowledgement headers flag - update
       
   259 		// the return flag...
       
   260 		capabilitiesReduced = ETrue;
       
   261 
       
   262 		// ...and the session property...
       
   263 		THTTPHdrVal notUsed = 0;
       
   264 		connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspCapUseAcknowledgements, RHTTPSession::GetTable()), notUsed);
       
   265 		}
       
   266 	// ...suspend resume facility...
       
   267 	if( (protocolOptions & ESessionResumeFacility) != (iClientCapInfo->GetProtocolOptions() & ESessionResumeFacility) )
       
   268 		{
       
   269 		// The server has cleared the support suspend/resume facility flag - 
       
   270 		// update the return flag...
       
   271 		capabilitiesReduced = ETrue;
       
   272 
       
   273 		// ...and the session property...
       
   274 		THTTPHdrVal notUsed = 0;
       
   275 		connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspCapSupportSuspendResume, RHTTPSession::GetTable()), notUsed);
       
   276 		}
       
   277 
       
   278 	return capabilitiesReduced;
       
   279 	}
       
   280 
       
   281 TBool CWspCOProtocolHandler::SupportSuspendResume() const
       
   282 	{
       
   283 	return (iNegotiatedCapInfo->GetProtocolOptions() & ESessionResumeFacility);
       
   284 	}
       
   285 
       
   286 TBool CWspCOProtocolHandler::CanResume() const
       
   287 	{
       
   288 	TBool canResume = SupportSuspendResume();
       
   289 
       
   290 	if( canResume && (iSessionState != EConnected && iSessionState != ESuspending && iSessionState != ESuspended) )
       
   291 		{
       
   292 		// In the wrong state
       
   293 		canResume = EFalse;
       
   294 		}
       
   295 	return canResume;
       
   296 	}
       
   297 
       
   298 TBool CWspCOProtocolHandler::CanSuspend() const
       
   299 	{
       
   300 	TBool canSuspend = SupportSuspendResume();
       
   301 
       
   302 	if( canSuspend && (iSessionState != EConnected && iSessionState != EResuming) )
       
   303 		{
       
   304 		// In the wrong state
       
   305 		canSuspend = EFalse;
       
   306 		}
       
   307 	return canSuspend;
       
   308 	}
       
   309 
       
   310 #if defined (_DEBUG)
       
   311 void CWspCOProtocolHandler::ResetAll()
       
   312 	{
       
   313 	// Delete helper objects and reset state
       
   314 	delete iClientSessionHeaders;
       
   315 	iClientSessionHeaders = NULL;
       
   316 	// 
       
   317 	if (iClientCapInfo)
       
   318 		iClientCapInfo->Reset();
       
   319 	if (iNegotiatedCapInfo)
       
   320 		iNegotiatedCapInfo->Reset();
       
   321 	if (iConnectionTimer)
       
   322 		iConnectionTimer->Cancel();
       
   323 	if (iProxyInfoProvider)
       
   324 		iProxyInfoProvider->ResetProxyInfo();
       
   325 	//
       
   326 	iSessionState = ENull; 
       
   327 	iTimedOutValue = 0;
       
   328 	iConnectTimedOut = EFalse;
       
   329 	iWaitingMethod  = EFalse;
       
   330 	iDisconnectRequested = EFalse;
       
   331 	iPendingCompletingMethods = 0;
       
   332 	//
       
   333 	// Reset the transport handler (stub only)
       
   334 	iSessionInvoker->DisconnectReq((TWspReason)(-999));
       
   335 	}
       
   336 #endif
       
   337 
       
   338 void CWspCOProtocolHandler::SessionConnectL()
       
   339 	{
       
   340 	__ASSERT_DEBUG( iSessionState == ENull, Panic(KWspPanicSessionNotInValidState) );
       
   341 
       
   342 	__LOG(_L("Initiating a session connect."));
       
   343 
       
   344 	// Check for any client proposed capabilities
       
   345 	CheckClientCapabilities();
       
   346 
       
   347 	// Update the client session headers
       
   348 	UpdateClientSessionHeadersL();
       
   349 
       
   350 	// Update the proxy info
       
   351 	iProxyInfoProvider->UpdateProxyInfoL();
       
   352 
       
   353 	// Start connection timed-out timer
       
   354 	iConnectionTimer->Start(iTimedOutValue);
       
   355 
       
   356 	// Send S-Connect.req primitive to transport handler
       
   357 	__LOG(_L("---Sending S-Connect.req primitive."));
       
   358 	iSessionInvoker->ConnectReq();
       
   359 
       
   360 	// Update session state
       
   361 	__LOG(_L("---WSP Session in Connecting state."));
       
   362 	iSessionState = EConnecting;
       
   363 
       
   364 	// Check to see if there is a method transactions waiting.
       
   365 	CheckWaitingMethod();
       
   366 	}
       
   367 
       
   368 void CWspCOProtocolHandler::SessionResumeL()
       
   369 	{
       
   370 	__ASSERT_DEBUG( CanResume(), Panic(KWspPanicSessionNotInValidState) );
       
   371 
       
   372 	__LOG(_L("Initiating a session resume."));
       
   373 
       
   374 	// Check to see if the proxy info has not changed.
       
   375 	if( iProxyInfoProvider->ProxyInfoChangedAndUpdateL() )
       
   376 		{
       
   377 		__LOG(_L("---Proxy has changed. Disconnect from the old proxy and connect to the new one."));
       
   378 
       
   379 		// The client has specified a different - disconnect this session
       
   380 		SessionDisconnect(EChangedProxyInSuspendedSession);
       
   381 		}
       
   382 	else
       
   383 		{
       
   384 		// Check for any client proposed capabilities
       
   385 		CheckClientCapabilities();
       
   386 
       
   387 		// Update the client session headers
       
   388 		UpdateClientSessionHeadersL();
       
   389 
       
   390 		// Start connection timed-out timer
       
   391 		iConnectionTimer->Start(iTimedOutValue);
       
   392 
       
   393 		// Send S-Resume.req primitive to transport handler
       
   394 		__LOG(_L("---Sending S-Resume.req primitive."));
       
   395 		iSessionInvoker->ResumeReq();
       
   396 
       
   397 		// Update session state
       
   398 		__LOG(_L("---WSP Session in Resuming state."));
       
   399 		iSessionState = EResuming;
       
   400 
       
   401 		// Check to see if there is a method transactions waiting.
       
   402 		CheckWaitingMethod();
       
   403 		}
       
   404 	}
       
   405 
       
   406 void CWspCOProtocolHandler::SessionDisconnect(TWspReason aReason)
       
   407 	{
       
   408 	__ASSERT_DEBUG( iSessionState != ENull && iSessionState != EClosing, Panic(KWspPanicSessionNotInValidState) );
       
   409 
       
   410 	// Are there any methods waiting to send their final .res primitive
       
   411 	if( iPendingCompletingMethods > 0 )
       
   412 		{
       
   413 		// Yep, need to wait until there are done.
       
   414 		iDisconnectRequested = ETrue;
       
   415 		return;
       
   416 		}
       
   417 	__LOG(_L("Disconnecting session."));
       
   418 
       
   419 	// Need to cancel the connection timer
       
   420 	iConnectionTimer->Cancel();
       
   421 
       
   422 	// Send S-Disconnect.req primitive to transport handler
       
   423 	__LOG1(_L("---Sending S-Disconnect.req primitive. Reason code : %d"), aReason);
       
   424 	iSessionInvoker->DisconnectReq(aReason);
       
   425 
       
   426 	// Update session state
       
   427 	__LOG(_L("---WSP Session in Closing state."));
       
   428 	iSessionState = EClosing;
       
   429 	}
       
   430 
       
   431 void CWspCOProtocolHandler::SessionSuspend()
       
   432 	{
       
   433 	__ASSERT_DEBUG( CanSuspend(), Panic(KWspPanicSessionNotInValidState) );
       
   434 	
       
   435 	// Are there any methods waiting to send their final .res primitive
       
   436 	if( iPendingCompletingMethods > 0 )
       
   437 		{
       
   438 		// Yep, need to wait until there are done.
       
   439 		iDisconnectRequested = ETrue;
       
   440 		return;
       
   441 		}
       
   442 	__LOG(_L("Suspending session."));
       
   443 
       
   444 	// Need to cancel the connection timer
       
   445 	iConnectionTimer->Cancel();
       
   446 
       
   447 	// Send S-Suspend.req primitive to transport handler
       
   448 	__LOG(_L("---Sending S-Suspend.req primitive."));
       
   449 	iSessionInvoker->SuspendReq();
       
   450 
       
   451 	// Update session state
       
   452 	__LOG(_L("---WSP Session in Suspending state."));
       
   453 	iSessionState = ESuspending;
       
   454 	}
       
   455 
       
   456 void CWspCOProtocolHandler::DoSessionConnectedL()
       
   457 	{
       
   458 	// Cancel the connection timer
       
   459 	iConnectionTimer->Cancel();
       
   460 
       
   461 	// Check for the Encoding-Version header in the server session headers
       
   462  	RHTTPHeaders headers = iSession.ResponseSessionHeadersL();
       
   463  	THTTPHdrVal negotiatedVersion;
       
   464  	TInt err = headers.GetField(
       
   465  							   iSession.StringPool().StringF(WSP::EEncodingVersion, WSP::Table),
       
   466  							   0,		// Zero index -> first part
       
   467  							   negotiatedVersion
       
   468  							   );
       
   469 	
       
   470 	// Default version is 1.2 - this is the case if the header is missing.
       
   471  	CWspHeaderCodec::TWspVersion version = CWspHeaderCodec::EVersion1_2;
       
   472 
       
   473 	if( (err != KErrNotFound) && (negotiatedVersion.Type() == THTTPHdrVal::KStrFVal) )
       
   474  		{
       
   475  		// Check what version the encoding is and set it accordingly in the codec
       
   476 		switch(negotiatedVersion.StrF().Index(WSPStdConstants::Table) )
       
   477 			{
       
   478 			case WSPStdConstants::EWspVersion11:
       
   479 				version = CWspHeaderCodec::EVersion1_1;
       
   480 				break;
       
   481 			case WSPStdConstants::EWspVersion13:
       
   482 				version = CWspHeaderCodec::EVersion1_3;
       
   483 				break;
       
   484 			case WSPStdConstants::EWspVersion14:
       
   485 				version = CWspHeaderCodec::EVersion1_4;
       
   486 				break;
       
   487 			default:
       
   488 				// If the version is 1.2 or anything else, stay at 1.2
       
   489 				break;
       
   490 			}
       
   491  		}
       
   492 	// Set the encoding value in the codec
       
   493 	STATIC_CAST(CWspHeaderCodec*, iCodec)->SetWspVersion(version);
       
   494 
       
   495 	// Inform client that the session is connected - check negotiated capabilities
       
   496 	THTTPSessionEvent connectEvent = THTTPSessionEvent::EConnectedOK;
       
   497 
       
   498 	// Check the negotiated capabilities
       
   499  	TBool capabilitiesReduced = UpdateNegotiatedCapabilitiesL();
       
   500 
       
   501 	if( capabilitiesReduced )
       
   502 		{
       
   503 		// At least one of the proposed client capabilities has been negotiated 
       
   504 		// down or rejected - need to inform client of this event.
       
   505 		connectEvent = THTTPSessionEvent::EConnectedWithReducedCapabilities;
       
   506 		}
       
   507 	SendSessionEvent(connectEvent);
       
   508 
       
   509 	// WSP session is connected - update state
       
   510 	__LOG(_L("---WSP Session in Connected state"));
       
   511 	iSessionState = EConnected;
       
   512 	}
       
   513 
       
   514 void CWspCOProtocolHandler::SendSessionEvent(THTTPSessionEvent aEvent)
       
   515 	{
       
   516 	// Send the event to the client - need to TRAPD
       
   517 	TRAPD(error, iSession.SendSessionEventL(aEvent, THTTPSessionEvent::EIncoming, THTTPFilterHandle::EProtocolHandler));
       
   518 	if( error != KErrNone )
       
   519 		{
       
   520 		__LOG1(_L("Error - Could not send event to the client, error code %d"), error);
       
   521 		iSession.FailSessionEvent(THTTPFilterHandle::EProtocolHandler);
       
   522 		}
       
   523 	}
       
   524 
       
   525 void CWspCOProtocolHandler::UpdateClientSessionHeadersL()
       
   526 	{
       
   527 	// Check for Encoding-Version header
       
   528 	RStringPool stringPool = iSession.StringPool();
       
   529 	RHTTPHeaders headers = iSession.RequestSessionHeadersL();
       
   530 	THTTPHdrVal version;
       
   531 	RStringF encodingVersionField = stringPool.StringF(WSP::EEncodingVersion, WSP::Table);
       
   532 	TInt err = headers.GetField(encodingVersionField, 0 /* Zero index -> first part*/, version);
       
   533 	TBool foundHeader = EFalse;
       
   534 
       
   535 	// If the encoding-version header exists, check that it is valid
       
   536 	if( err == KErrNone )
       
   537 		{
       
   538 		if( version.Type() == THTTPHdrVal::KStrFVal )
       
   539 			{
       
   540 			switch( version.StrF().Index(WSPStdConstants::Table) )
       
   541 				{
       
   542 				case WSPStdConstants::EWspVersion11:
       
   543 				case WSPStdConstants::EWspVersion12:
       
   544 				case WSPStdConstants::EWspVersion13:
       
   545 				case WSPStdConstants::EWspVersion14:
       
   546 					foundHeader = ETrue;
       
   547 					break;
       
   548 				default:
       
   549 					break;
       
   550 				}
       
   551 			}
       
   552 		}
       
   553 
       
   554 	// If the header is not found or is invalid, then use WSP encoding v1.4
       
   555 	if(!foundHeader)
       
   556 		{
       
   557 		// Remove existing header first if its invalid, this won't do anything if it doesn't exist
       
   558 		headers.RemoveField(encodingVersionField);
       
   559 		THTTPHdrVal encodingVersionValue(stringPool.StringF(WSPStdConstants::EWspVersion14, WSPStdConstants::Table));
       
   560 		headers.SetFieldL(encodingVersionField, encodingVersionValue);
       
   561 		__LOG(_L("---Updated WSP encoding version request to 1.4"));
       
   562 		}
       
   563 
       
   564    	// Encode the headers...
       
   565 	HBufC8* buf = iHdrUtils->EncodeHeadersL(stringPool, headers);
       
   566 
       
   567 	// Update the client session headers buffer;
       
   568 	delete iClientSessionHeaders;
       
   569 	iClientSessionHeaders = buf;
       
   570 	}
       
   571 
       
   572 void CWspCOProtocolHandler::HandleConnectRequestL()
       
   573 	{
       
   574 	// Check the WSP session state
       
   575 	switch( iSessionState )
       
   576 		{
       
   577 	case ENull:
       
   578 		{
       
   579 		// Initiate a session connect
       
   580 		SessionConnectL();
       
   581 		} break;
       
   582 	case ESuspended:
       
   583 	case ESuspending:
       
   584 		{
       
   585 		// In suspending or suspended state - this implies that the WSP 
       
   586 		// session supports the Suspend Resume facility and was suspended 
       
   587 		// rather than disconnected for a more efficient re-connection.
       
   588 
       
   589 		// Initiate a session resume
       
   590 		SessionResumeL();
       
   591 		} break;
       
   592 	case EConnecting:
       
   593 	case EResuming:
       
   594 		{
       
   595 		// A connect request has already been sent - inform the client
       
   596 		SendSessionEvent(THTTPSessionEvent::EAlreadyConnecting);
       
   597 		} break;
       
   598 	case EConnected:
       
   599 		{
       
   600 		// A connect request has already been sent and the session is 
       
   601 		// connected - inform the client
       
   602 		SendSessionEvent(THTTPSessionEvent::EAlreadyConnected);
       
   603 		} break;
       
   604 	case EClosing:
       
   605 		{
       
   606 		// A disconnect request has already been sent - inform the client
       
   607 		SendSessionEvent(THTTPSessionEvent::EAlreadyDisconnecting);
       
   608 		} break;
       
   609 	default:
       
   610 		Panic(KWspPanicIllegalSessionState);
       
   611 		break;
       
   612 		}
       
   613 	}
       
   614 
       
   615 void CWspCOProtocolHandler::HandleDisconnectRequest()
       
   616 	{
       
   617 	// Disconnect has been requestd. Action depends of the WSP session state.
       
   618 	switch( iSessionState )
       
   619 		{
       
   620 	case ENull:
       
   621 	case ESuspended:
       
   622 		{
       
   623 		// A disconnect request has already been fulfilled - inform the client
       
   624 		SendSessionEvent(THTTPSessionEvent::EAlreadyDisconnected);
       
   625 		} break;
       
   626 	case EClosing:
       
   627 	case ESuspending:
       
   628 		{
       
   629 		// A disconnect request has already been sent - inform the client
       
   630 		SendSessionEvent(THTTPSessionEvent::EAlreadyDisconnecting);
       
   631 		} break;
       
   632 	case EConnecting:
       
   633 		{
       
   634 		// The WSP session is in the Connecting state, then the session should be
       
   635 		// disconnected - do SessionDisconnect. This will issue the 
       
   636 		// S-Disconnect.req primitive and tell the transport handler to stop the 
       
   637 		// connection. The transport handler will send the S-Disconnect.ind 
       
   638 		// primitive which results in the client being notified.
       
   639 		SessionDisconnect(EUserReq);
       
   640 		} break;
       
   641 	case EResuming:
       
   642 		{
       
   643 		// If the WSP session is resuming, then the Suspend Resume facility is
       
   644 		// supported - can suspend the WSP session. This will issue the 
       
   645 		// S-Suspend.req primitive and tell the transport handler to stop the 
       
   646 		// session resume. The transport handler will send the S-Suspend.ind 
       
   647 		// primitive to the protocol handler who will then inform the client.
       
   648 		SessionSuspend();
       
   649 		} break;
       
   650 	case EConnected:
       
   651 		{
       
   652 		// Check if the Suspend Resume facility is supported. If so, then 
       
   653 		// suspend the WSP session, rather then disconnect it.
       
   654 		if( SupportSuspendResume() )
       
   655 			{
       
   656 			// Suspend the WSP session
       
   657 			SessionSuspend();
       
   658 			}
       
   659 		else
       
   660 			{
       
   661 			// Disconnect the WSP session
       
   662 			SessionDisconnect(EUserReq);
       
   663 			}
       
   664 		} break;
       
   665 	default:
       
   666 		Panic(KWspPanicIllegalSessionState);
       
   667 		break;
       
   668 		}
       
   669 	}
       
   670 
       
   671 void CWspCOProtocolHandler::CheckWaitingMethod()
       
   672 	{
       
   673 	if( iWaitingMethod )
       
   674 		{
       
   675 		// Self-complete the base class - this will start servicing the pending
       
   676 		// transaction.
       
   677 		CompleteSelf();
       
   678 
       
   679 		// Clear the flag
       
   680 		iWaitingMethod = EFalse;
       
   681 		}
       
   682 	}
       
   683 
       
   684 /*
       
   685  * Methods from CProtocolHandler
       
   686  */
       
   687 
       
   688 void CWspCOProtocolHandler::CreateCodecL()
       
   689 	{
       
   690 	iCodec = CWspHeaderCodec::NewL(iSession.StringPool(), WSP::Table);
       
   691 	}
       
   692 
       
   693 CProtTransaction* CWspCOProtocolHandler::CreateProtTransactionL(RHTTPTransaction aTransaction)
       
   694 	{
       
   695 	return CWspCOTransaction::NewL(aTransaction, iTransportHandler->COTransactionInvoker(), *iNegotiatedCapInfo, *this, *iHdrUtils);
       
   696 	}
       
   697 
       
   698 TBool CWspCOProtocolHandler::ServiceL(CProtTransaction& aTrans)
       
   699 	{
       
   700 	__LOG(_L("Attempting to invoke request."));
       
   701 
       
   702 	// Check the WSP session state
       
   703 	if( iSessionState == EClosing || iSessionState == ESuspending )
       
   704 		{
       
   705 		__LOG(_L("---Session is Closing or Suspending - cannot invoke methods."));
       
   706 
       
   707 		// The WSP session is either disconnecting or suspending - leave
       
   708 		User::Leave(KWspErrSessionClosingOrSuspending);
       
   709 		}
       
   710 	if( iSessionState == ENull || iSessionState == ESuspended )
       
   711 		{
       
   712 		__LOG(_L("---Session is Null or Suspended - cannot invoke methods. Wait for session connect initiation."));
       
   713 		
       
   714 		// Send back an event saying that session is not connected yet
       
   715 		SendSessionEvent(THTTPSessionEvent::ENotConnected);
       
   716 
       
   717 		// Set a flag to indicate that there is a transaction waiting to be 
       
   718 		// serviced - need to self-complete once connected.
       
   719 		iWaitingMethod = ETrue;
       
   720 
       
   721 		//  Cannot service the method transaction now.
       
   722 		return EFalse;
       
   723 		}
       
   724 	// Check to see if the method MOR has been reached.
       
   725 	TUint32 activeTransactions = NumActiveTransactions();
       
   726 	if( activeTransactions == iNegotiatedCapInfo->GetMethodMOR() )
       
   727 		{
       
   728 		__LOG1(_L("---Have reached method MOR (=%d) - cannot invoke request."), iNegotiatedCapInfo->GetMethodMOR());
       
   729 
       
   730 		// Have reached the method MOR - cannot service this method transaction.
       
   731 		return EFalse;
       
   732 		}
       
   733 	// Have not yet reached the negotiated method MOR - can service this 
       
   734 	// transaction.
       
   735 
       
   736 	// Create the Tx Data object for this transaction
       
   737 	aTrans.CreateTxDataL();
       
   738 
       
   739 	// Do the method invocation
       
   740 	STATIC_CAST(CWspCOTransaction&, aTrans).InitRequestL();
       
   741 
       
   742 	__LOG1(_L("---Initiated request - trans %d is active"), aTrans.Transaction().Id() );
       
   743 
       
   744 	return ETrue;
       
   745 	}
       
   746 
       
   747 void CWspCOProtocolHandler::ClosedTransactionHook(CProtTransaction* aTrans)
       
   748 	{
       
   749 	__LOG1(_L("Trans %d has been closed"), aTrans->Transaction().Id() );
       
   750 
       
   751 	// Down-cast the CProtTransaction
       
   752 	CWspCOTransaction& wspTransaction = *STATIC_CAST(CWspCOTransaction*, aTrans);
       
   753 
       
   754 	// Abort this transaction
       
   755 	wspTransaction.AbortRequest();
       
   756 
       
   757 	// Tell the method transaction to suicide - the transaction will ensure that 
       
   758 	// it deletes itself at the appropriate time.
       
   759 	wspTransaction.Suicide();
       
   760 	}
       
   761 
       
   762 void CWspCOProtocolHandler::CancelTransactionHook(CProtTransaction& aTransaction)
       
   763 	{
       
   764 	__LOG1(_L("Trans %d has been cancelled"), aTransaction.Transaction().Id() );
       
   765 
       
   766 	// Abort this transaction
       
   767 	STATIC_CAST(CWspCOTransaction&, aTransaction).AbortRequest();
       
   768 	}
       
   769 
       
   770 void CWspCOProtocolHandler::NotifyNewRequestBodyPart(CProtTransaction& aTransaction)
       
   771 	{
       
   772 	__LOG(_L("Client has more request data..."));
       
   773 
       
   774 	// Send the S-MethodInvokeData primitive
       
   775 	STATIC_CAST(CWspCOTransaction&, aTransaction).NotifyMoreRequestData();
       
   776 	}
       
   777 
       
   778 void CWspCOProtocolHandler::GetInterfaceL(TUid aInterfaceId, MProtHandlerInterface*& aInterfacePtr)
       
   779 	{
       
   780 	switch(aInterfaceId.iUid)
       
   781 		{
       
   782 	case KProtHandlerSessionServerCertUid:
       
   783 		{
       
   784 		aInterfacePtr = this;
       
   785 		break;
       
   786 		}
       
   787 	default:
       
   788 		{
       
   789 		CProtocolHandler::GetInterfaceL(aInterfaceId, aInterfacePtr);
       
   790 		break;
       
   791 		}
       
   792 		}
       
   793 	}
       
   794 
       
   795 /*
       
   796  * Methods from MHTTPFilterBase
       
   797  */
       
   798 
       
   799 void CWspCOProtocolHandler::MHFSessionRunL(const THTTPSessionEvent& aEvent)
       
   800 	{
       
   801 	__ASSERT_DEBUG( iTransportHandler, Panic(KWspPanicTransportHandlerDoesNotExist) );
       
   802 
       
   803 	// Check the session event
       
   804 	switch(aEvent.iStatus)
       
   805 		{
       
   806 	case THTTPSessionEvent::EConnect:
       
   807 		{
       
   808 		__LOG(_L("Processing EConnect session event"));
       
   809 
       
   810 		// Handle the connect request
       
   811 		HandleConnectRequestL();
       
   812 		} break;
       
   813 	case THTTPSessionEvent::EDisconnect:
       
   814 		{
       
   815 		__LOG(_L("Processing EDisconnect session event"));
       
   816 
       
   817 		// Handle the disconnect request
       
   818 		HandleDisconnectRequest();
       
   819 		} break;
       
   820 #if defined (_DEBUG)
       
   821 	case -999:
       
   822 		{
       
   823 		// This unpublished value is used in testing to cause a whole protocol
       
   824 		// handler reset and to reset the transport handler. It should be used with caution!
       
   825 		__LOG(_L("PROTOCOL HANDLER RESETTING!"));
       
   826 		ResetAll();
       
   827 
       
   828 		// Ack the owner
       
   829 		SendSessionEvent(-999);
       
   830 		} break;
       
   831 #endif
       
   832 	default:
       
   833 		// Ignore the unknown session event.
       
   834 		__LOG1(_L("Received unknown session event : %d"), aEvent.iStatus);
       
   835 		break;
       
   836 		}
       
   837 	}
       
   838 
       
   839 TInt CWspCOProtocolHandler::MHFSessionRunError(TInt aError, const THTTPSessionEvent& /*aEvent*/)
       
   840 	{
       
   841 	// Send the error as a session event.
       
   842 	SendSessionEvent(aError);
       
   843 	return KErrNone;
       
   844 	}
       
   845 
       
   846 /*
       
   847  * Methods from MWspCOSessionCallback
       
   848  */
       
   849 
       
   850 void CWspCOProtocolHandler::ConnectCnf()
       
   851 	{
       
   852 	__LOG(_L("Received S-Connect.cnf primitive"));
       
   853 
       
   854 	// Did we connect to a secure proxy?  If so, send the 'authenticated OK' session event
       
   855 	MWspProxyInfoProvider& proxyInfo = STATIC_CAST(MWspProxyInfoProvider&, *iProxyInfoProvider);
       
   856 	if( proxyInfo.SecureConnection() )
       
   857 		{
       
   858 		__LOG(_L("---WTLS authentication was successful."));
       
   859 
       
   860 		// Send EAuthenticatedOK event...
       
   861 		SendSessionEvent(THTTPSessionEvent::EAuthenticatedOK);
       
   862 		}
       
   863 
       
   864 	// Process the session connected event
       
   865 	DoSessionConnected();
       
   866 	}
       
   867 
       
   868 void CWspCOProtocolHandler::ResumeCnf()
       
   869 	{
       
   870 	__LOG(_L("Received S-Resume.cnf primitive"));
       
   871 
       
   872 	// Process the session connected event
       
   873 	DoSessionConnected();
       
   874 	}
       
   875 
       
   876 void CWspCOProtocolHandler::DoSessionConnected()
       
   877 	{
       
   878 	// Process the session connected event
       
   879 	TRAPD(error, DoSessionConnectedL());
       
   880  	if( error != KErrNone )
       
   881  		{
       
   882  		__LOG(_L("Error - Could not process S-Connect.cnf/S-Resume.cnf. Disconnect the WSP session."));
       
   883  
       
   884  		// Disconnect this session
       
   885  		SessionDisconnect(EPeerReq);
       
   886  		}
       
   887 	}
       
   888 
       
   889 void CWspCOProtocolHandler::DisconnectInd(TWspReason					aReason, 
       
   890 										  TBool							/*aRedirectSecurity*/, 
       
   891 										  TWspRedirectedAddress&		aRedirectAddress, 
       
   892 										  const TDesC8&					/*aErrorHeader*/, 
       
   893 										  const TDesC8&					/*aErrorBody*/)
       
   894 	{
       
   895 	__ASSERT_DEBUG( NumActiveTransactions() == 0, Panic(KWspPanicMethodsStillOutstanding) );
       
   896 
       
   897 	__LOG(_L("Received S-Disconnect.ind primitive"));
       
   898 	__LOG1(_L("---Reason code : %d"), aReason);
       
   899 
       
   900 	// Cancel the connection timer
       
   901 	iConnectionTimer->Cancel();
       
   902 
       
   903 	// Check the reason for the disconnect
       
   904 	switch( aReason )
       
   905 		{
       
   906 	case EPermanentRedirectedProxy:
       
   907 		{
       
   908 		__LOG(_L("---Permanent proxy redirection"));
       
   909 
       
   910 		// Update the proxy info with the redirected proxy addresses. This will
       
   911 		// place the new address in the EWspProxyAddress session property.
       
   912 		TRAPD(error, iProxyInfoProvider->SetPermanentRedirectedProxyL(aRedirectAddress) );
       
   913 
       
   914 		if( error != KErrNone )
       
   915 			{
       
   916 			// Something went wrong - just disconnect
       
   917 			SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
   918 			}
       
   919 		else
       
   920 			{
       
   921 			// Need to inform client that the proxy has been redirected permanently.
       
   922 			SendSessionEvent(THTTPSessionEvent::ERedirected);
       
   923 
       
   924 			// Send the S-Connect primitive
       
   925 			iPrimitiveSender->InitiateSend(ESConnect);
       
   926 			}
       
   927 		} break;
       
   928 	case ETemporaryRedirectedProxy:
       
   929 		{
       
   930 		__LOG(_L("---Temporary proxy redirection"));
       
   931 
       
   932 		// Update the proxy info with the redirected proxy addresses.
       
   933 		TRAPD(error, iProxyInfoProvider->SetTemporaryRedirectedProxyL(aRedirectAddress) );;
       
   934 
       
   935 		if( error != KErrNone )
       
   936 			{
       
   937 			// Something went wrong - just disconnect
       
   938 			SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
   939 			}
       
   940 		else
       
   941 			{
       
   942 			// Send the S-Connect primitive
       
   943 			iPrimitiveSender->InitiateSend(ESConnect);
       
   944 			}
       
   945 		} break;
       
   946 	case EChangedProxyInSuspendedSession:
       
   947 		{
       
   948 		__LOG(_L("---Client changed proxy whilst suspended"));
       
   949 		__LOG(_L("---Forced disconnect, then connection to new proxy"));
       
   950 
       
   951 		// The client had disconnected the session (resulting in the session
       
   952 		// being suspended) and then did a connect, but with a different 
       
   953 		// proxy. This resulted in the suspended session being disconnected.
       
   954 		// Now need to initiate a session connect to the new proxy.
       
   955 		iPrimitiveSender->InitiateSend(ESConnect);
       
   956 		} break;
       
   957 	case EWtlsConfigurationFailed:
       
   958 	case EWtlsPhase1HandshakeFailed:
       
   959 	case EWtlsPhase2HandshakeFailed:
       
   960 	case EWtlsInvalidServerCert:
       
   961 	case EWtlsUntrustedServerCert:
       
   962 	case EWtlsNegotiatedConfigRejected:
       
   963 		{
       
   964 		__LOG(_L("---WTLS handshake failure"));
       
   965 
       
   966 		// Various failure modes for the WTLS handshake.  All result in a
       
   967 		// 'authentication failure' event being sent to the client, followed by
       
   968 		// a 'disconnected' event.
       
   969 		SendSessionEvent(THTTPSessionEvent::EAuthenticationFailure);
       
   970 		SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
   971 		} break;
       
   972 	case EOutOfMemory:
       
   973 		{
       
   974 		// There was a memory allocation failure in the transport handler - inform
       
   975 		// the client.
       
   976 		SendSessionEvent(KErrNoMemory);
       
   977 
       
   978 		// Inform the client that the sesion is disconnected
       
   979 		SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
   980 		} break;
       
   981 	case ESessionStateFailure:
       
   982 		{
       
   983 		// The session is effectively disconnected
       
   984 		SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
   985 
       
   986 		// The transport handler has entered an invalid or indeterminate state - possibly due
       
   987 		// to a memory allocation failure - the session is no longer valid and should be
       
   988 		// discontinued by the client - inform the client.
       
   989 		__LOG(_L("Transport Handler has signalled a session state failure"));
       
   990 		iSession.FailSessionEvent(THTTPFilterHandle::EProtocolHandler);
       
   991 		} break;
       
   992 	case EUserReq:
       
   993 		{
       
   994 		// This is ind to a S-Disconnect.req. Was it due to a connect time-out?
       
   995 		if( iConnectTimedOut )
       
   996 			{
       
   997 			__LOG(_L("---Connection has timed-out"));
       
   998 
       
   999 			// Inform the client that the resume timed-out
       
  1000 			SendSessionEvent(THTTPSessionEvent::EConnectionTimedOut);
       
  1001 			iConnectTimedOut = EFalse;
       
  1002 			break;
       
  1003 			}
       
  1004 		// Drop-through if there was no connect time-out
       
  1005 		} 
       
  1006 	default:
       
  1007 		// Session disconnected for some other reason. Inform the client, but 
       
  1008 		// ignore the information in aErrorHeader and aErrorBody. The WSP 
       
  1009 		// Specification states that the provider MAY choose not to communicate
       
  1010 		// this information - the protocol handler is making that choice!!
       
  1011 		SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
  1012 		break;
       
  1013 		}
       
  1014 	// WSP session is disconnected - update state
       
  1015 	__LOG(_L("---WSP Session in Null state"));
       
  1016 	iSessionState = ENull;
       
  1017 	}
       
  1018 
       
  1019 void CWspCOProtocolHandler::SuspendInd(TWspReason /*aReason*/)
       
  1020 	{
       
  1021 	__ASSERT_DEBUG( NumActiveTransactions() == 0, Panic(KWspPanicMethodsStillOutstanding) );
       
  1022 
       
  1023 	__LOG(_L("Received S-Suspend.ind primitive"));
       
  1024 
       
  1025 	// Do not care about the reason, just inform the client. First check if this
       
  1026 	// suspend is the result of a session resume timed-out.
       
  1027 	if( iConnectTimedOut )
       
  1028 		{
       
  1029 		__LOG(_L("---Resume has timed-out"));
       
  1030 
       
  1031 		// Inform the client that the resume timed-out
       
  1032 		SendSessionEvent(THTTPSessionEvent::EConnectionTimedOut);
       
  1033 		iConnectTimedOut = EFalse;
       
  1034 		}
       
  1035 	else
       
  1036 		{
       
  1037 		// Inform the client that the session is disconnected - this event is 
       
  1038 		// sent as the the client does not understand suspend/resume and the 
       
  1039 		// Suspend Resume facility is being used for efficiency.
       
  1040 		SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
  1041 		}
       
  1042 	// WSP session is suspended - update state
       
  1043 	__LOG(_L("---WSP Session in Suspended state"));
       
  1044 	iSessionState = ESuspended;
       
  1045 	}
       
  1046 
       
  1047 void CWspCOProtocolHandler::ExceptionInd(const TDesC8& aExceptionData)
       
  1048 	{
       
  1049 	RStringPool stringPool = iSession.StringPool();
       
  1050 
       
  1051 	// Generic handling for exception data
       
  1052 	__LOG(_L("Have received exception information."));
       
  1053 
       
  1054 	// Add the exception data as the EWspProxyExceptionInfo property
       
  1055 	RHTTPConnectionInfo	connInfo = iSession.ConnectionInfo();
       
  1056 	TRAP_IGNORE(
       
  1057 		RStringF exceptionData = stringPool.OpenFStringL(aExceptionData);
       
  1058 		CleanupClosePushL(exceptionData);
       
  1059 		THTTPHdrVal exceptionProperty = exceptionData;
       
  1060 		connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspProxyExceptionInfo, RHTTPSession::GetTable()), exceptionProperty);
       
  1061 		CleanupStack::PopAndDestroy(&exceptionData);
       
  1062 		);
       
  1063 	
       
  1064 	// Send the exception info event
       
  1065 	SendSessionEvent(THTTPSessionEvent::EExceptionInfo);
       
  1066 	}
       
  1067 
       
  1068 /*
       
  1069  * Methods from MWspCapabilityInfoProvider
       
  1070  */
       
  1071 
       
  1072 const MWspCapabilityViewer& CWspCOProtocolHandler::ClientCapabilities() const
       
  1073 	{
       
  1074 	return *iClientCapInfo;
       
  1075 	}
       
  1076 
       
  1077 MWspCapabilitySetter& CWspCOProtocolHandler::ServerCapabilities() const
       
  1078 	{
       
  1079 	return *iNegotiatedCapInfo;
       
  1080 	}
       
  1081 
       
  1082 /*
       
  1083  * Methods from MWspSessionHeadersProvider
       
  1084  */
       
  1085 
       
  1086 const TDesC8& CWspCOProtocolHandler::ClientHeaders() const
       
  1087 	{
       
  1088 	return *iClientSessionHeaders;
       
  1089 	}
       
  1090 
       
  1091 void CWspCOProtocolHandler::SetServerHeadersL(const TDesC8& aBuffer)
       
  1092 	{
       
  1093 	RHTTPHeaders serverHeaders = iSession.ResponseSessionHeadersL();
       
  1094 	iHdrUtils->DecodeHeadersL(iSession.StringPool(), aBuffer, serverHeaders);
       
  1095 	}
       
  1096 
       
  1097 /*
       
  1098  *	Methods from MConnectionTimerCallback
       
  1099  */
       
  1100 
       
  1101 void CWspCOProtocolHandler::HandleConnectionTimedOut()
       
  1102 	{
       
  1103 	__LOG(_L("Connection timed-out - appropriate action taken"));
       
  1104 
       
  1105 	// The connection has timed-out - flag
       
  1106 	iConnectTimedOut = ETrue;
       
  1107 
       
  1108 	// Request a disconnect. 
       
  1109 	HandleDisconnectRequest();
       
  1110 	}
       
  1111 
       
  1112 /*
       
  1113  * Methods from MWspPrimitiveSenderCallback
       
  1114  */
       
  1115 
       
  1116 void CWspCOProtocolHandler::SendPrimitiveL(TWspPrimitive aPrimitive)
       
  1117 	{
       
  1118 	// Check that the primitive is one that is supported
       
  1119 	switch( aPrimitive )
       
  1120 		{
       
  1121 	case ESConnect:
       
  1122 		{
       
  1123 		SessionConnectL();
       
  1124 		} break;
       
  1125 	case ESDisconnect:
       
  1126 	case ESSuspend:
       
  1127 		{
       
  1128 		HandleDisconnectRequest();
       
  1129 		} break;
       
  1130 	default:
       
  1131 		// Unsupported primitive
       
  1132 		User::Leave(KWspErrUnsupportedSendPrimitive);
       
  1133 		break;
       
  1134 		}
       
  1135 	}
       
  1136 
       
  1137 TInt CWspCOProtocolHandler::WspPrimitiveSenderCallbackError(TInt /*aError*/)
       
  1138 	{
       
  1139 	// The initiate session connect has failed. Need to unlock the proxy info.
       
  1140 	iProxyInfoProvider->UnlockProxyInfo();
       
  1141 
       
  1142 	// Inform the client - send disconnected signal
       
  1143 	SendSessionEvent(THTTPSessionEvent::EDisconnected);
       
  1144 
       
  1145 	return KErrNone;
       
  1146 	}
       
  1147 
       
  1148 /*
       
  1149  * Methods from MWspCOMethodObserver
       
  1150  */
       
  1151 
       
  1152 void CWspCOProtocolHandler::HandleMethodAbort(CWspCOTransaction& aTransaction)
       
  1153 	{
       
  1154 	// The CWspCOTransaction has failed the transaction - inform the base class
       
  1155 	// protocol handler to change the state of this transaction.
       
  1156 	TransactionFailed(aTransaction.Transaction());
       
  1157 
       
  1158 	__LOG1(_L("Transaction %d has failed."), aTransaction.Transaction().Id() );
       
  1159 	}
       
  1160 
       
  1161 void CWspCOProtocolHandler::NotifyPendingCompletingMethod()
       
  1162 	{
       
  1163 	// Increment the number of pending methods waiting to move from Completing
       
  1164 	// to Null state.
       
  1165 	++iPendingCompletingMethods;
       
  1166 
       
  1167 	__LOG1(_L("Number of methods waiting to send final .res primitive : %d"), iPendingCompletingMethods);
       
  1168 	}
       
  1169 
       
  1170 void CWspCOProtocolHandler::NotifyMethodComplete()
       
  1171 	{
       
  1172 	// The final .res primitive has been sent for one of the methods - decrement
       
  1173 	// count.
       
  1174 	--iPendingCompletingMethods;
       
  1175 
       
  1176 	__LOG1(_L("Number of methods waiting to send final .res primitive : %d"), iPendingCompletingMethods);
       
  1177 
       
  1178 	if( iPendingCompletingMethods == 0 && iDisconnectRequested )
       
  1179 		{
       
  1180 		__LOG(_L("---All methods have sent final .res primitive. Requesting disconnect."));
       
  1181 
       
  1182 		// No more methods waiting to send the final .res primitive and the
       
  1183 		// client has requested the session be disconnected - request it now.
       
  1184 		iPrimitiveSender->InitiateSend(ESDisconnect);
       
  1185 		}
       
  1186 	}
       
  1187 
       
  1188 
       
  1189 /*
       
  1190  * Methods from MRxDataObserver
       
  1191  */
       
  1192 
       
  1193 void CWspCOProtocolHandler::SetStatusL(CRxData& aRxData, TInt aStatus)
       
  1194 	{
       
  1195 	// Have received a status message from an Rx data object - check the status.
       
  1196 	switch( aStatus )
       
  1197 		{
       
  1198 	case THTTPEvent::EResponseComplete:
       
  1199 		{
       
  1200 		__LOG1(_L("Transaction %d has completed"), aRxData.ProtTrans().Transaction().Id() );
       
  1201 		// The response is complete - the client has been passed all the data
       
  1202 		// and released it. It has no further use for the Rx data object. The
       
  1203 		// transaction is now complete - inform the base class.
       
  1204 		TransactionCompletedL(aRxData.ProtTrans().Transaction(), THTTPEvent::EResponseComplete);
       
  1205 		} break;
       
  1206 	default:
       
  1207 		// Unknown status - do nothing.
       
  1208 		__LOG1(_L("Received unknown status %d"), aStatus);
       
  1209 		break;
       
  1210 		}
       
  1211 	}
       
  1212 
       
  1213 TInt CWspCOProtocolHandler::SessionServerCert(TCertInfo& aServerCert)
       
  1214 	{
       
  1215 	return iTransportHandler->ServerCert(aServerCert);
       
  1216 	}
       
  1217 
       
  1218 const CCertificate* CWspCOProtocolHandler::SessionServerCert()
       
  1219 	{
       
  1220 	return iTransportHandler->ServerCert();
       
  1221 	}
       
  1222 
       
  1223 /*
       
  1224  * Methods from MProtHandlerInterface
       
  1225  */
       
  1226 
       
  1227 TInt CWspCOProtocolHandler::TransactionServerCert(TCertInfo& /*aServerCert*/, RHTTPTransaction /*aTransaction*/)
       
  1228 	{
       
  1229 	// Transaction Server certificate does not make sense for WSP
       
  1230 	return KErrNotSupported;
       
  1231 	}
       
  1232 
       
  1233 const CCertificate* CWspCOProtocolHandler::TransactionServerCert(RHTTPTransaction /*aTransaction*/)
       
  1234 
       
  1235 	{
       
  1236 	return NULL;
       
  1237 	}