--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IMPSengine/engsrv/src/impscspsession.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,3805 @@
+/*
+* Copyright (c) 2004 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: Session for IMPS.
+*
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <e32math.h>
+#include "impsserver.h"
+#include "impssession.h"
+#include "impssubsession.h"
+#include "impscspsession.h"
+#include "impsfields.h"
+#include "impsutils.h"
+#include "impserrors.h"
+#include "impstimer.h"
+#include "impssendreceive.h"
+#include "impsservices.h"
+#include "impscommonenums.h"
+#include "impssdatautils.h"
+#include "impsmessageinterpreterapi.h"
+#include "impsdataaccessor.h"
+#include "impsdigestbytes.h"
+#include "impsvariant.h"
+#include "impsalivemanager.h"
+#include "impsactivecirmonitor.h"
+#include "ImpsVariantAPI.h"
+#include "impstidqueue.h"
+#include "impsactivecirmonitor.h"
+
+#ifdef LOCAL_IMPS
+#ifndef _FAKE_RESPONSE
+#define _FAKE_RESPONSE
+#endif
+#endif
+
+#ifdef _FAKE_RESPONSE
+#include "impssrvtestutils.h"
+#endif
+
+// MACROS
+#ifndef _DEBUG
+#define _NO_IMPS_LOGGING_
+#endif
+
+// CONSTANTS
+// Adative polling policy time increment
+const TInt KImpsPollIncrement = 10;
+
+// ================= MEMBER FUNCTIONS =======================
+
+CImpsCSPSession::CImpsCSPSession( CImpsServer& aServer,
+ TImpsSrvSettings& aSettings,
+ RFs& aFs,
+ CImpsVariant& aVariant,
+ TImpsCspVersion aVer ):
+ iServer( aServer ),
+ iCSPVersion( aVer ),
+ iFs( aFs ),
+ iVariant( aVariant ),
+ iTransactionList( _FOFF( CTransaction, iLink ) ), //lint !e413
+ iRequestList( _FOFF( CReq, iLink ) ), //lint !e413
+ iCSPState( EImpsCSPIdle ),
+ iPendingLogout( EFalse ),
+ iAliveMgr( NULL ),
+ iPollTime( KImpsPollTime ),
+ iPollWasRequested( EFalse ),
+ iUserId( NULL ),
+ iIntStatus ( EInternal_NOT_LOGGED ),
+ iMultiTrans( KImpsMultiTrans ),
+ iNegoExpiry( ),
+ iCirManager( NULL ),
+ iLogoutTID( KNullDesC ),
+ iConAllowed( ETrue ),
+ iPendingAlive( EFalse ),
+ iSAP( NULL ),
+ iIAP( 0 ),
+ iPollState( EImpsPollNone ),
+ iPollInResume( 0 ),
+ iPendingPDP( EImpsPDPPendNone ), // PDP:
+ iPendPDPLogout ( EFalse ), // PDP:
+ iTidSapHistory( NULL ),
+ iTidCliHistory( NULL ),
+ iTcpCIRError( EFalse ),
+ iCancelLogin ( EFalse )
+ {
+ iCSPSessionId = KNullDesC;
+ iLogCID = KNullDesC;
+ iTempTid = KNullDesC;
+ iTempTid2 = KNullDesC;
+ iMsg = EImpsMessageNone;
+ iLoginPhase = 1;
+ iKey1 = NULL;
+ iKey2 = NULL;
+ iSettings = aSettings;
+ }
+
+// Create and start a new server.
+
+CImpsCSPSession* CImpsCSPSession::NewL( CImpsServer& aServer,
+ TImpsSrvSettings& aSettings,
+ RFs& aFs,
+ CImpsVariant& aVariant,
+ TImpsCspVersion aVer )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ if ( aVer == EImpsCspVersion11 )
+ {
+ CImpsClientLogger::Log( _L( "CSPSession: NewL rel200542.2+ WV 1.1" ) );
+ }
+ else
+ {
+ CImpsClientLogger::Log( _L( "CSPSession: NewL rel200542.2+ WV 1.2" ) );
+ }
+#endif
+
+ CImpsCSPSession* self = new ( ELeave ) CImpsCSPSession( aServer,
+ aSettings, aFs, aVariant, aVer );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CImpsCSPSession::~CImpsCSPSession()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DESTRUCTOR csp=%d **" ), ( TInt )this );
+#endif
+ // deallocate all memory
+ DeleteTransactions();
+ DeleteRequests();
+
+ delete iTransportOut;
+
+ delete iCirManager;
+ delete iReceiver2;
+ delete iAllMessages;
+ delete iRcv;
+ delete iSnd;
+
+ delete iIdleTimer;
+ delete iAliveMgr;
+
+ delete iSendQ;
+
+ delete iTCPAddr;
+ delete iLogPwd;
+ delete iLogTid;
+ delete iKey1;
+ delete iKey2;
+ delete iUserId;
+
+ delete iSAP;
+
+ if ( iDecoder )
+ {
+ iDecoder->Destroy();
+ }
+ if ( iEncoder )
+ {
+ iEncoder->Destroy();
+ }
+
+ delete iPDPIdleTimer;
+ delete iPDPOpenTimer;
+ delete iTidSapHistory;
+ delete iTidCliHistory;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::Destroy()
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::Destroy()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Destroy csp=%d" ), ( TInt )this );
+#endif
+ // You MUST delete ip-cir entity before conn-manager entity.
+ // refer to ImpsIpCirWatcherApi.h.
+ delete iCirManager;
+ iCirManager = NULL;
+ iReceiver2->Destroy();
+ delete iReceiver2;
+ iReceiver2 = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::ConstructL()
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::ConstructL()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: ConstructL begins csp=%d **" ), ( TInt )this );
+#endif
+
+ iTransportOut = CBufFlat::NewL( KImpsStreamSize / 2 );
+ iTransportOut->ResizeL( KImpsStreamSize );
+
+ iDecoder = NewDecoderL( this );
+ iEncoder = NewEncoderL();
+
+ iTidSapHistory = CImpsTidQueue::NewL();
+ iTidCliHistory = CImpsTidQueue::NewL();
+
+ iSnd = CImpsFields::NewL();
+ iRcv = CImpsFields::NewL();
+ iIdleTimer = new ( ELeave ) CImpsIdleTimer( *this, CActive::EPriorityStandard );
+ iPDPIdleTimer = new ( ELeave ) CImpsPDPIdleTimer( *this, CActive::EPriorityStandard );
+ iPDPOpenTimer = new ( ELeave ) CImpsPDPOpenTimer( *this, CActive::EPriorityStandard );
+ iAliveMgr = CImpsAliveManager::NewL( *this );
+
+ iSendQ = new ( ELeave ) CImpsSendQueued( * this, CActive::EPriorityStandard );
+
+ // Just initialize undefined address
+ iTCPAddr = HBufC::NewL( 1 );
+ *iTCPAddr = KNullDesC;
+
+ TPtrC8 myMime = iEncoder->MimeType();
+ iReceiver2 = CImpsSendReceive2::NewL(
+ iFs, *this, *iTransportOut, myMime );
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession:ConstructL ends" ) );
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::CloseAll()
+// CImpsServer::CloseEngine calls this. TransportStatus handles the callback.
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::CloseAll( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CloseAll %d csp=%d" ), ( TInt )this );
+#endif
+
+ NewState( EImpsCSPShuttingDown );
+
+ if ( iIdleTimer )
+ {
+ iIdleTimer->Stop( );
+ }
+ iPollState = EImpsPollNone;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+#endif
+
+ if ( iAliveMgr )
+ {
+ iAliveMgr->StopTimer( );
+ }
+
+ if ( iSendQ )
+ {
+ iSendQ->Cancel( );
+ }
+
+ if ( iCirManager )
+ {
+ iCirManager->CloseCh( 0xF );
+ delete iCirManager;
+ iCirManager = NULL;
+ }
+
+ // Close the transport
+ if ( iReceiver2 )
+ {
+ iReceiver2->CloseTr( );
+ }
+ // TransportStatus handles rest of shut down activities
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::ClosePDP
+// called by - CImpsPDPIdleTimer
+// ClosePDP method needed to close PDP-context.
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::ClosePDP()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: ClosePDP" ) );
+#endif
+
+ if ( iPollState != EImpsPollCIR )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: ClosePDP IGNORED iPollState = %d****" ),
+ iPollState );
+#endif
+ return;
+ }
+ if ( IsPDPIdle() )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: ClosePDP PDP already IDLE ****" ) );
+#endif
+ if ( iCSPState == EImpsCSPOnLineIdleEnd )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: ClosePDP -> EImpsPDPPendClose" ) );
+#endif
+ // set pending close request if PDP is opening
+ iPendingPDP = EImpsPDPPendClose;
+ }
+ return;
+ }
+
+ NewState( EImpsCSPOnLineIdleStart );
+
+ // This does not close WAP-SMS-CIR
+ if ( iCirManager )
+ {
+ iCirManager->CloseCh( 0xF );
+ delete iCirManager;
+ iCirManager = NULL;
+ }
+
+ // Close the transport
+ if ( iReceiver2 )
+ {
+ iReceiver2->ClosePDP( );
+ }
+ // TransportStatus handles rest of shut down activities
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::OpenPDP
+// Called by LogoutL, SendAliveL, SendDataL, TransportStatus, SendAllQueued
+// Called by CIRMessageL directly and by the CImpsPDPTimer class too.
+// OpenPDP method needed to re-open PDP-context
+// -----------------------------------------------------------------------------
+TInt CImpsCSPSession::OpenPDP()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: OpenPDP" ) );
+#endif
+ if ( !IsPDPIdle() )
+ {
+ // Nothing to do
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: OpenPDP IGNORED - not idle" ) );
+#endif
+ return KErrAlreadyExists;
+ }
+ else if ( iCSPState == EImpsCSPOnLineIdleEnd )
+ {
+ // already opening
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: OpenPDP IGNORED - EImpsCSPOnLineIdleEnd" ) );
+#endif
+ return KErrNotReady;
+ }
+ else if ( iCSPState == EImpsCSPOnLineIdleStart )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: OpenPDP -> EImpsPDPPendOpen" ) );
+#endif
+ iPendingPDP = EImpsPDPPendOpen;
+ return KErrNone;
+ }
+
+ NewState( EImpsCSPOnLineIdleEnd );
+ TRAPD( errx, iReceiver2->OpenPDPL( SAP(), iIAP ) );
+ if ( errx )
+ {
+ NewState( EImpsCSPOnLineIdle );
+ // Does not matter which error code is returned. Used in Logout only
+ // to start internal logout routines.
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: openpdp E1 ****" ) );
+#endif
+ return KErrGeneral;
+ }
+ return KErrNone;
+ // TransportStatus/transportError handles rest of open activities
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::LoginL
+// -----------------------------------------------------------------------------
+TPtrC CImpsCSPSession::LoginL(
+ const TDesC& aUser,
+ const TDesC& aPassword,
+ const TDesC& aClientId,
+ const TDesC& aSAP,
+ TUint32 aAP,
+ const TDesC& aKey1,
+ const TDesC& aKey2,
+ TTime aLoginExpiry,
+ TBool aReactive )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: LoginL state=%d csp=%d" ), iCSPState, ( TInt )this );
+#endif
+
+ // AOL Login
+ if ( aKey1.Length() && aKey2.Length() )
+ {
+ // this should be the case anyway
+ iSettings.iFourWayLogin = ETrue;
+ delete iKey1;
+ iKey1 = NULL;
+ iKey1 = aKey1.AllocL();
+ delete iKey2;
+ iKey2 = NULL;
+ iKey2 = aKey2.AllocL();
+ }
+ TPtrC tid ( KNullDesC );
+
+ delete iSAP;
+ iSAP = NULL;
+ iSAP = aSAP.AllocL();
+ iIAP = aAP;
+
+ iPendingAlive = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPendingAlive->F" ) );
+#endif
+
+ if ( iCSPState >= EImpsCSPLogged )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: Login when logged ***" ) );
+#endif
+ User::Leave( KImpsErrorAlreadyLogged );
+ }
+ else if ( iCSPState == EImpsCSPDisconnecting )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: Login when CSP logging out ***" ) );
+#endif
+ User::Leave( KErrNotReady );
+ }
+ // Check that no active CSP session exists
+ // This should not happen before login
+ else if ( iReceiver2->NbrOfPending() >= KImpsMaxPending ||
+ iCSPState == EImpsCSPLogging )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: Login when busy ***" ) );
+#endif
+ User::Leave( KErrNotReady );
+ }
+ // Close old connections if any in re-login case (wrong psw first time e.g.)
+ // The pending logout response is handled above, not here.
+ else if ( iReceiver2->isConnected() )
+ {
+ // These are for re-login without logout after an error response
+ NewState( EImpsCSPIdle );
+ iPollState = EImpsPollNone;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+ CImpsClientLogger::Log( _L( "CSPSession: err: transport was connected ***" ) );
+#endif
+ iAliveMgr->StopTimer();
+ iSendQ->Cancel();
+ iIntStatus = EInternal_NOT_LOGGED;
+ iReceiver2->CloseTr();
+ User::Leave( KErrNotReady );
+ }
+
+ // aPassword cannot be NULL
+ delete iLogPwd;
+ iLogPwd = NULL;
+ delete iUserId;
+ iUserId = NULL;
+ iLogPwd = aPassword.AllocL();
+ iUserId = aUser.AllocL();
+ iLogCID = aClientId;
+ iLogoutTID = KNullDesC;
+ iNegoExpiry = aLoginExpiry;
+ iReactive = aReactive;
+ TImpsSrvUtils::InitializeServices( iServices, iReactive );
+
+ // Make a login request
+ iSnd->Reset();
+ tid.Set( GenerateTid() );
+ iSnd->SetTidL( tid );
+ iSnd->SetMessageType( EImpsLoginReq );
+ // Session type is OUTBAND
+ iSnd->SetSessionTypeL( EImpsOutband );
+
+ TImpsDataAccessor myAccess( iSnd );
+ CImpsKey* myKey = CImpsKey::NewLC(); // <<< myKey
+
+ iAliveTime = iSettings.iAliveTime;
+
+ if ( iSettings.iFourWayLogin == EFalse )
+ {
+ TImpsSDataUtils::CreateLoginReqL(
+ myKey,
+ &myAccess,
+ aUser,
+ iLogCID,
+ LogPwd(),
+ GenerateCookie(),
+ iAliveTime );
+ // set this, that response goes to the right place
+ iLoginPhase = 2;
+ }
+ else
+ {
+ TImpsDigestSchema aSchema = EImpsMD5;
+ TImpsSDataUtils::CreateLoginReqPhaseOneL(
+ myKey,
+ &myAccess,
+ aUser,
+ iLogCID,
+ aSchema,
+ GenerateCookie(),
+ iAliveTime );
+ // just to be sure
+ iLoginPhase = 1;
+ }
+
+ // Add TImpsTransactionMode now
+ myKey->Reset();
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ KTransModeElements,
+ sizeof( KTransModeElements ) /
+ sizeof( KTransModeElements[0] ) );
+ myAccess.StoreIntegerL( myKey, EImpsRequest );
+ CleanupStack::PopAndDestroy( 1 ); // >>> myKey
+
+ // Save login id for error handling purposes
+ iTempTid2 = tid;
+
+ // Set WV version
+ iSnd->SetCspVersion( iCSPVersion );
+
+ // Encode login request
+ iEncoder->EncodeMessageL( myAccess, *iTransportOut );
+ iLastSent = EImpsLoginReq;
+
+ delete iLogTid;
+ iLogTid = NULL;
+ iLogTid = tid.AllocL();
+
+ // This does not leave immediately if network is not available
+ NewState( EImpsCSPLogging );
+ TRAPD( errx, iReceiver2->OpenL( tid, iSettings.iXmlLog, aSAP, aAP ) );
+ if ( errx )
+ {
+ // In rare situations the previous call may leave
+ NewState( EImpsCSPIdle );
+ User::Leave( errx );
+ }
+
+ // iReceiver callback handles the rest of the login method.
+ // This handles interrupted logout request as well as shut down interrupt
+
+ iMsg = EImpsMessageNone;
+
+ return tid;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::LogoutL
+// Notice that subsession class prevents calling this in certain
+// situations, if not iLogged or not pending login operation.
+// Therefore shut down situation is not handled here.
+// -----------------------------------------------------------------------------
+TPtrC CImpsCSPSession::LogoutL( TBool aCancel )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: LogoutL state=%d cancel=%d csp=%d" ), iCSPState,
+ aCancel, ( TInt )this );
+#endif
+
+ if ( iCSPState == EImpsCSPIdle )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: LogoutL LEAVES KImpsErrorNotLogged" ) );
+#endif
+ iPendingPDP = EImpsPDPPendNone;
+ iPendPDPLogout = EFalse;
+ User::Leave( KImpsErrorNotLogged );
+ }
+
+ if ( iCancelLogin && aCancel )
+ {
+ // cancel login already requested!
+ return TPtrC();
+ }
+
+ // Make a logout request (encode)
+ TPtrC tid;
+ tid.Set( GenerateTid() );
+ iLogoutTID = tid;
+ // Use iLogoutTID when loggin out later after PDP-open
+ // Check if PDP is closed and start to re-open it here (Logout)
+ if ( IsPDPIdle() )
+ {
+ // check this flag when PDP has been re-opened
+ iPendPDPLogout = ETrue;
+ if ( iCSPState == EImpsCSPOnLineIdle )
+ {
+ // E1: error handling; return boolean to speed up error handling
+ // E2: fix:
+ if ( OpenPDP() )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: Ex2 OpenPDP FAILS ****" ) );
+#endif
+ DoLogout();
+ }
+ return tid;
+ }
+ }
+
+ if ( iCSPState != EImpsCSPLogging )
+ {
+ // Clear buffers from old stuff
+ DeleteRequests();
+ DeleteTransactions();
+ // Send Logout primitive and set state to EImpsCSPDisconnecting.
+ TRAPD( errx, DoSendLogoutL( tid ) );
+ if ( errx )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendLogoutL error %d ***" ), errx );
+#endif
+ // Do logout routines immediately if transport gives an error
+ DoLogout();
+ // The following error code is handled in a special way in
+ // client session classes.
+ User::Leave( KImpsErrorTerminalOffLine );
+ }
+ }
+ else // LoggingIn
+ {
+ if ( !aCancel )
+ {
+ iPendingLogout = ETrue;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPendingLogout->TRUE ***" ) );
+#endif
+ }
+ else
+ {
+ iCancelLogin = ETrue;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iCancelLogin->TRUE ***" ) );
+#endif
+ }
+ // Logout must not ever fail so this must not leave.
+ StartLoginCancel( );
+ }
+
+ return tid;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::CirMessageL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::CirMessageL(
+ const TDesC8& aCookie )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CirMessageL csp=%d" ), ( TInt )this );
+#endif
+
+ // if CIR is not negotiated then ignore
+ if ( ( iSettings.iUDPWAPCIR != 2 && iSettings.iSMSWAPCIR != 2 &&
+ iSettings.iTCPSCIR != 2 && iSettings.iUDPSCIR != 2 ) ||
+ !IsNegotiated() )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CirMessage IGNORED" ) );
+#endif
+ return;
+ }
+
+ // check session cookie but not CSP-version.
+ // CIR syntax: WVCI <CSP-version> <Session-cookie>
+
+ TPtrC8 cookie = aCookie.Left( 4 );
+ if ( cookie.CompareF( _L8( "WVCI" ) ) )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CirMessage SYNTAX ERROR" ) );
+#endif
+ User::Leave( KErrArgument );
+ }
+
+ cookie.Set( aCookie );
+ // Find if the cookie exists in this push body
+ if ( cookie.Find( iCookie8 ) == KErrNotFound )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CirMessage COOKIE ERROR" ) );
+#endif
+ User::Leave( KImpsErrorUnauthorized );
+ }
+
+ // reset PDP idle timer when CIR received
+ iPDPIdleTimer->Reset();
+
+ // If PDP-context is idle or shutting down then set pending open request.
+ if ( IsPDPIdle() )
+ {
+ if ( iCSPState == EImpsCSPOnLineIdle ||
+ iCSPState == EImpsCSPOnLineIdleStart )
+ {
+ iPendingPDP = EImpsPDPPendOpen;
+ }
+ if ( !iPollInResume )
+ {
+ iPollInResume = 1;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollInResume %d" ),
+ iPollInResume );
+#endif
+ }
+ // This is a fix for cases when GPRS bearer event has not been received
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CIR -> openPDP ****" ) );
+#endif
+ OpenPDP();
+ iPDPOpenTimer->Start( KImpsPDPRetryOpenTime );
+ }
+
+ // Send the actual Poll message
+ else if ( iIntStatus == EInternal_ON_LINE ) // && !PDPIdle
+ {
+ TRAPD( errPoll, SendPollL() );
+ if ( errPoll && !iPollInResume )
+ {
+ iPollInResume = 1;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollInResume %d" ), iPollInResume );
+#endif
+ }
+ }
+ else // NOT ON_LINE && !PDPIdle
+ {
+ // WAP SMS CIR causes OFF-LINE and therefore has to wait ON-LINE
+ iPollState = EImpsPollPending;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+#endif
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SendDataL
+// -----------------------------------------------------------------------------
+TPtrC CImpsCSPSession::SendDataL(
+ CImpsFields* aFields, TInt aExpiry, TBool& aOwnerCh )
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SendDataL begins csp=%d" ), ( TInt )this );
+#endif
+
+ // reset PDP idle timer
+ iPDPIdleTimer->Reset();
+
+ aOwnerCh = EFalse;
+
+ // generate TID
+ CImpsFields* fields = aFields;
+ TPtrC tid;
+ tid.Set( GenerateTid() );
+ fields->SetTidL( tid );
+ // Insert CSP Session-id
+ fields->SetSessionIdL( iCSPSessionId );
+ // Session-type
+ fields->SetSessionTypeL( EImpsInband );
+
+ TImpsDataAccessor myAccess( fields );
+ CImpsKey* myKey = CImpsKey::NewLC(); // <<< myKey
+
+ // Add TImpsTransactionMode now
+ myKey->Reset();
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ KTransModeElements,
+ sizeof( KTransModeElements ) /
+ sizeof( KTransModeElements[0] ) );
+ myAccess.StoreIntegerL( myKey, EImpsRequest );
+
+ // API supports deliver method and thus do not overwrite it here anymore
+
+ CleanupStack::PopAndDestroy( 1 ); // >>> myKey
+
+ // We have to check if queued messages exist
+ TBool queuedMsg = EFalse;
+ queuedMsg = RequestExist();
+
+ // if PDP-idle then queue request + start to open PDP
+ TInt nbrPend = iReceiver2->NbrOfPending();
+ if ( nbrPend >= KImpsMaxPending ||
+ iIntStatus != EInternal_ON_LINE ||
+ iTr >= iMultiTrans ||
+ queuedMsg ||
+ IsPDPIdle() )
+ {
+ // Transport adapter is busy so queue the request
+ QueueClientRequestL( fields, aExpiry );
+ aOwnerCh = ETrue;
+ if ( iCSPState == EImpsCSPOnLineIdle )
+ {
+ // Try to open PDP only once, don't start open PDP timer.
+ // The request will expiry if this fails anyway and it's
+ // a task of application to retry sending of this message.
+ OpenPDP( );
+ }
+ else if ( iCSPState == EImpsCSPOnLineIdleStart ||
+ iCSPState == EImpsCSPOnLineIdle )
+ {
+ iPendingPDP = EImpsPDPPendOpen;
+
+ /* Notice:
+ Thus CImpsConnManager DLL
+ does not give bearer event for GPRS resume in all situations
+ it is better to try to open the connection always.
+ */
+ OpenPDP();
+ }
+
+ else if ( queuedMsg )
+ {
+ // This must not leave because of the error is not message specific
+ SendAllQueued();
+ }
+ }
+ else
+ {
+ // Message sending should be possible without PDP open
+ DoSendSingleL(
+ &myAccess, tid, ( TImpsMessageType ) fields->MessageType() );
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SendData ends" ) );
+#endif
+
+ return tid;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::TransportResponseL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::TransportResponseL( HBufC8** aDataPtr )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: TransportResponseL csp=%d" ), ( TInt )this );
+#endif
+
+ HBufC8* rawData = *aDataPtr;
+
+ // reset PDP idle timer
+ iPDPIdleTimer->Reset();
+
+ SendAllQueued();
+
+ TInt myError = KErrNone;
+ // Handle pending logout here
+ if ( iPendingLogout || iCancelLogin )
+ {
+ DoPendingLogout();
+ return;
+ }
+
+ if ( rawData == NULL || rawData->Des().Length() == 0 )
+ {
+ // SAP did not send anything in the response
+ iLastReceived = 0;
+ // Increase adaptive polling time if necessary
+ if ( iLastSent == EImpsPolling )
+ {
+ IncreasePollTime();
+ }
+ return;
+ }
+
+ if ( iLastSent != EImpsKeepAliveReq )
+ {
+ // Reset poll timer
+ ResetPollTime();
+ }
+
+ if ( iRcv )
+ {
+ iRcv->Reset();
+ }
+ else
+ {
+ // QueueTidL may have leaved and this is NULL
+ iRcv = CImpsFields::NewL();
+ }
+
+ CImpsDataAccessor* myAccess = CImpsDataAccessor::NewLC( iRcv ); // <<<
+
+ TInt retCode = KErrNone;
+
+// ----------- NORMAL CASE -------------------------
+#ifndef _FAKE_RESPONSE
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Gonna to call Decode" ) );
+#endif
+ // Decode to iRcv
+ iDecoder->DecodeMessageL( *myAccess, aDataPtr );
+ retCode = iRcv->ResponseStatusL();
+ // Decode errors cancel this method and error are
+ // reported to client by expiry timers.
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Decoded status = %d" ), iRcv->Status() );
+ CImpsClientLogger::Log( _L( "CSPSession: Decoded ResponseStatus = %d" ),
+ retCode );
+#endif
+
+// ----------- NORMAL CASE ENDS -------------------------
+
+// ----------- TEST CASE -------------------------
+#endif // ifndef _FAKE_RESPONSE
+
+#ifdef _FAKE_RESPONSE
+ TImpsSrvTestUtils tests( *this, iFs );
+ tests.MakeFakeResponseL( myAccess, aDataPtr );
+#endif
+// ----------- TEST CASE ENDS -------------------------
+
+ // Message successfully received from SAP
+ // Session-id check
+ if ( iRcv->SessionTypeL() == EImpsInband )
+ {
+ TPtrC sesId = iRcv->SessionIdL();
+ // This is case sensitive
+ if ( sesId.Length( ) > 0 && sesId.Compare( iCSPSessionId ) )
+ {
+ // Invalid session id
+ User::Leave( KImpsErrorSID );
+ }
+ }
+
+ // KeepAlive handling
+ iAliveMgr->CheckResp( retCode );
+
+ // ---------------------------------
+ // check if multiTrans messages
+ // ---------------------------------
+ TInt trs = myAccess->NbrOfTransactionsL( );
+ if ( trs < 1 )
+ {
+ // If no transaction content then it is handled as encode error
+ myError = KImpsErrorDecode;
+ }
+ else if ( trs == 1 )
+ {
+ // regular case, one transaction content in a transport messages
+ // Update internal data structure (CImpsFields)
+#ifndef _FAKE_RESPONSE
+ if ( !( myAccess->GetTransactionL( 0, NULL ) ) )
+ {
+ // internal error
+ myError = KErrCorrupt;
+ }
+#endif
+ }
+
+ // ----------------------------------
+ // checking multiTrans messages ends
+ // ----------------------------------
+
+ // If error then stop further progress of transport response
+ if ( myError )
+ {
+ User::Leave( myError );
+ }
+
+ // Check if PollRequest was requested in incoming transport message
+ if ( iRcv->PollL() )
+ {
+ iPollWasRequested = ETrue;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollWasRequested->T in msg" ) );
+#endif
+ }
+ else
+ {
+ iPollWasRequested = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollWasRequested->F in msg" ) );
+#endif
+ }
+
+ if ( trs > 1 )
+ {
+ delete iAllMessages;
+ iAllMessages = iRcv;
+ iRcv = CImpsFields::NewL();
+ }
+ else
+ {
+ // paranoid about memory leaks
+ delete iAllMessages;
+ iAllMessages = NULL;
+ }
+
+ // ---------------------------------
+ // Send each new message to sessions
+ // ---------------------------------
+ for ( TInt i = 0; i < trs; i ++ )
+ {
+
+ if ( trs == 1 )
+ {
+ // No need for split
+ }
+ else
+ {
+ // Data accessor points to the original iRcv (allMessages)
+ iRcv->Reset();
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: MULTI-TRANS nbr=%d" ), i );
+#endif
+ if ( !( myAccess->GetTransactionL( i, iRcv ) ) )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Error with MultiTrans" ) );
+#endif
+ // error, continue
+ continue;
+ }
+ }
+
+ iLastReceived = iRcv->MessageType();
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: TransportResponse msg = 0x%x" ),
+ iLastReceived );
+#endif
+
+ // Check if csp Session startup routines needed
+ // TID is case sensitive
+ if ( ( iCSPState == EImpsCSPLogging || iCSPState == EImpsCSPNegotiation ) &&
+ ( iRcv->MessageType() == EImpsLoginRes ||
+ iRcv->MessageType() == EImpsClientCapabilityRes ||
+ iRcv->MessageType() == EImpsServiceRes ||
+ ( iRcv->MessageType() == EImpsStatus &&
+ !iRcv->TidL().Compare( iTempTid2 ) ) ) )
+ {
+ SessionStartupL( iRcv );
+ }
+ // Sent events to all sub-sessions interested in this type of event
+ // This also handles login-resposes and removes the login-req from
+ // queues.
+ if ( iRcv->MessageType() != 0 &&
+ iRcv->MessageType() != EImpsClientCapabilityRes &&
+ iRcv->MessageType() != EImpsServiceRes &&
+ iLoginPhase != 2 )
+ {
+ RouteMessageL();
+ }
+ } // for
+
+ // CIR-error-flag check in WV 1.2.
+ // WV 1.1 messages returns always EFalse.
+ // Check this flag only if TCP/IP CIR channel is negotiated.
+ if ( !iTcpCIRError && iSettings.TCPSCIR() == 2 && IsLogged() )
+ {
+ // Close and re-open TCP/IP CIR if CIR flag is on.
+ TInt erx = KErrNone;
+ TRAP( erx, iTcpCIRError = TImpsSDataUtils::GetCIRL( myAccess ) );
+ // iTcpCIRError is reset in CirChOpened()
+ if ( iTcpCIRError )
+ {
+ if ( iCirManager )
+ {
+ iCirManager->CloseCh( KImpsCirTcp );
+ }
+ TRAP( erx, DoStartIpCIRL() );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( 1 ); // >>> myAccess
+
+ delete iAllMessages;
+ iAllMessages = NULL;
+
+ SendAllQueued();
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: TransportResponse ends" ) );
+#endif
+
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::TransportErrorL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::TransportErrorL(
+ const TDesC& aTID,
+ TInt aError )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: TransportError err=%d tid=%S csp=%d" ), aError, &aTID, ( TInt )this );
+#endif
+
+ TImpsCSPState origCSP = iCSPState;
+ // reset PDP idle timer
+ iPDPIdleTimer->Reset();
+
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+
+
+ // Handle pending logout here
+ // CSP destroyer is started finally
+ if ( iPendingLogout || iCancelLogin )
+ {
+ NewState( EImpsCSPDisconnecting );
+ DoPendingLogout();
+ return;
+ }
+
+ // Do not let the PDP start up again if it has just shut down.
+ if ( origCSP == EImpsCSPOnLineIdleEnd && aTID.Length() == 0 &&
+ aError == KImpsErrorNoIAP )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DON'T START UP PDP AGAIN ****" ) );
+#endif
+ if ( iPollState > EImpsPollAdaptive )
+ {
+ iPollState = EImpsPollCIR;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+#endif
+ }
+ ResetPollTime();
+ iPendingAlive = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPendingAlive->F" ) );
+#endif
+ NewState( EImpsCSPOnLineIdle );
+
+ // KeepAlive handling
+ iAliveMgr->CheckError( aTID );
+
+ // Discard all the current requests
+ // We change the error code for UI.
+ // First we have to check if there is Logout request so that
+ // it is completed with OK status!
+ if ( LogoutTID().Length() )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Err: Discard logout ****" ) );
+#endif
+ // This is for normal logout response error, i.e. no pending logout nor login-cancel.
+ iServer.DiscardLogout( LogoutTID(), csp );
+ DoLogout();
+ }
+ iServer.DiscardRequests( EImpsEventAll, KImpsErrorBearerSuspended, csp, this );
+ return;
+ }
+
+ // Let's call this to be sure that new messages are sent
+ SendAllQueued();
+
+ // Reset poll timer to resume from error case
+ ResetPollTime();
+
+ TInt myErr = KErrNone;
+
+ if ( iRcv )
+ {
+ iRcv->Reset();
+ }
+ else
+ {
+ // QueueTidL may have leaved and this is NULL
+ iRcv = CImpsFields::NewL();
+ }
+
+ // This ensures that login gets a response in 4-way login later phase
+ if ( origCSP == EImpsCSPLogging && !LogTid().CompareF( aTID ) )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Special LogTid ****" ) );
+#endif
+ // Route response to a requestion client and later below do logout.
+ iRcv->SetTidL( LogTid() );
+ }
+ else
+ {
+ iRcv->SetTidL( aTID );
+ }
+ iRcv->SetMessageType( EImpsStatus );
+ iRcv->SetStatus( aError );
+ TRAP( myErr, RouteMessageL( ) );
+
+ // KeepAlive handling
+ iAliveMgr->CheckError( aTID );
+
+ if ( origCSP == EImpsCSPLogging )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: Ex ****" ) );
+#endif
+ DoLogout();
+ }
+ // If RouteMessage has not done internal logout then let's do it here
+ else if ( origCSP == EImpsCSPDisconnecting )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: E6 ****" ) );
+#endif
+ // Message type is used in subsession to prevent sending logout event twice
+ iServer.DiscardLogout( iLogoutTID, csp );
+ DoLogout();
+ }
+
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::RouteMessageL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::RouteMessageL( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: RouteMessageL begins csp=%d" ), ( TInt )this );
+#endif
+
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+
+ // *****************************************************
+ // First check keep alive reponses
+ // *****************************************************
+
+ TInt32 resstatus = iRcv->ResponseStatusL();
+
+ // KeepAlive time may be reset on fly
+ if ( iRcv->MessageType() == EImpsKeepAliveRes )
+ {
+ if ( resstatus != KImpsStatusOk )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: RouteMessageL ends 1" ) );
+#endif
+ return;
+ }
+ // get new KeepAlive time if any
+ TInt newTime = 0;
+ TImpsDataAccessor myAc( iRcv );
+ if ( TImpsSDataUtils::GetKeepAliveL( &myAc, newTime ) )
+ {
+ iAliveTime = newTime;
+ iAliveMgr->StartTimer( iAliveTime );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Server: new AliveTime %d" ), iAliveTime );
+#endif
+ }
+ // Keep alive response does not cause events to clients
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: RouteMessageL ends 2" ) );
+#endif
+ return;
+ }
+
+ // *************************************************************
+ // Ignore informational messages from server status code 100-199
+ // *************************************************************
+ if ( resstatus >= 100 && resstatus < 200 )
+ {
+ iTr--;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: 100-200 iTr = %d" ), iTr );
+ CImpsClientLogger::Log( _L( "CSPSession: RouteMessageL ends 3" ) );
+#endif
+ return;
+ }
+
+ // *************************************************************
+ // Harmonize WV 1.1 and WV 1.2 logout responses
+ // *************************************************************
+ TImpsLogoutTrans logoutRsp = IsLogoutResp( iRcv );
+
+ // *****************************************************
+ // Handle regular request
+ // *****************************************************
+
+ // Check requests
+ TBool someFound = EFalse;
+ TBool notOrphan = EFalse;
+ TInt error = 0;
+ // The following sends logout reponse to a requesting client
+ TRAP( error, iServer.CheckRequestsL ( iRcv, someFound, csp ) );
+
+ if ( someFound )
+ {
+ // Message was response to our request, login phase has not
+ // increased this counter, that's why if statement here
+ TrMinus();
+ }
+ else if ( iRcv->MessageType() != EImpsDisconnect )
+ {
+ // Check that SAP initiated TID is not sent to clients already.
+ if ( ValidateTid( ETrue ) )
+ {
+ // Notifications check.
+ notOrphan = iServer.CheckNotifications( iRcv, csp );
+ }
+ }
+
+ // Check error that means cancelled CSP session
+ // notice: fullfill the list of serious erros
+ if ( logoutRsp != EImpsLogoutNone ||
+ resstatus == 600 || resstatus == 601 || resstatus == 604 )
+ {
+ TInt myOpId = 0;
+ if ( logoutRsp == EImpsLogoutSAP )
+ {
+ // Detect SAP initiated logout. disconnect primitive and
+ // TID not matching to our own logout TID.
+ myOpId = KImpsNullId;
+ }
+ // Both logout callback events and Status change events
+ // are sent here in logout.
+ DoLogoutNow( myOpId );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: RouteMessageL ends 4" ) );
+#endif
+ return;
+ }
+
+ // No reason to do this:
+ // if ( someFound ) notOrphan = ETrue;
+
+ // If the message was not a response to our TID then it was SAP originated
+ // Update pending transaction queue
+ if ( ( iRcv->MessageType() != EImpsDisconnect ) &&
+ ( iRcv->MessageType() != EImpsMessageNone ) &&
+ ( iRcv->MessageType() != EImpsStatus ) &&
+ ( !someFound )
+ )
+ {
+ // Make SAP response to wait actions
+ QueueTidL( !notOrphan );
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: RouteMessageL ends 5" ) );
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::GetNextMessageL
+// Called by SendReceive2
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::GetNextMessageL( )
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: GetNextMessageL begins" ) );
+#endif
+
+ // Use this to generate response for SAP intiated transactions
+ iSnd->Reset();
+
+ // Rejected, nothing to send
+ if ( !IsLogged() )
+ {
+ return;
+ }
+
+ // Send next buffered user request if any
+ // search. Not immediately, but via active object scheduler
+ SendAllQueued();
+
+ iLastSent = 0;
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::CheckExpiry
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::CheckExpiry(
+ TImpsEventType aType, const TTime aExpiry )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CheckExpiry begins" ) );
+#endif
+
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+
+ // Login negotiation phase is a special case.
+ // Access timer handles that.
+ // Because of there may be messages not initiated by
+ // API methods, server must check special time-out variable iNegoExpiry.
+ // Internal iRequestList cannot be used for that purpose
+ // because of requests are deleted after transport has
+ // got them succesfully, but we are not satisfied until get response.
+
+ if ( IsLogged() && !IsNegotiated() && iNegoExpiry < aExpiry )
+ {
+ // Expired negotiation in session startup negotiation
+ TInt errorCode = KErrTimedOut;
+ switch ( iMsg )
+ {
+ case EImpsClientCapabilityReq:
+ errorCode = KImpsErrorCapabilities;
+ break;
+ case EImpsServiceReq:
+ errorCode = KImpsErrorServices;
+ break;
+ default:
+ break;
+ }
+ iServer.SendErrorEvent( EImpsEventServerLogin, errorCode, 0, csp );
+ // goto to NOT_LOGGED
+ DoLogout();
+ }
+ else if ( iCSPState == EImpsCSPDisconnecting && iNegoExpiry < aExpiry )
+ {
+ if ( iCancelLogin || iPendingLogout )
+ {
+ DoPendingLogout();
+ }
+ else
+ {
+ iServer.DiscardLogout( LogoutTID(), csp );
+ // goto to NOT_LOGGED
+ DoLogout();
+ }
+ }
+ else if ( iCSPState == EImpsCSPLogging && iNegoExpiry < aExpiry )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CheckExpiry in EImpsCSPLogging ***" ) );
+#endif
+ iServer.DiscardRequests( aType, aExpiry, csp, this );
+ DoLogout();
+ }
+ else
+ {
+ // Regular mode.
+ // Go through all sessions (each having an own request list)
+ // The following ends up calling CancelTrans and there
+ // we can check if login or logout is expired and change the
+ // iCSPState.
+ iServer.DiscardRequests( aType, aExpiry, csp, this );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SessionStartupL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::SessionStartupL( CImpsFields* aFields )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SessionStartupL begins csp=%d" ), ( TInt )this );
+#endif
+
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ TInt errx = KErrNone;
+ TrMinus();
+
+ // check if error for 2-way login
+ if ( ( !IsLogged() ) &&
+ (
+ aFields->MessageType() == EImpsLoginRes ||
+ aFields->MessageType() == EImpsStatus ) &&
+ aFields->ResponseStatusL() != KImpsStatusOk &&
+ !iSettings.iFourWayLogin
+ )
+ {
+ // RouteMessageL handles errors if iLoginPhase != 2
+ // iLoginPhase starts from 2 in 2-way login
+ // See LoginL method
+ NewState( EImpsCSPIdle );
+ iReceiver2->CloseTr();
+ return;
+ }
+
+ // Login response, 4-way login phase one
+ // *************************************
+ if ( aFields->MessageType() == EImpsLoginRes &&
+ aFields->Status() == KErrNone &&
+ ( aFields->ResponseStatusL() == KImpsStatusOk ||
+ aFields->ResponseStatusL() == 401 ) &&
+ iLoginPhase == 1 )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SessionStartupL 4-login phase one" ) );
+#endif
+ iLoginPhase++;
+ TRAP( errx, HandleLoginResponseL( aFields ) );
+ if ( errx )
+ {
+ iServer.DiscardRequest( LogTid(), EImpsEventServerLogin, errx, csp );
+ NewState( EImpsCSPIdle );
+ }
+ return;
+ } // LOGIN RESPONSE1
+
+ // Login response, 4-way login phase two or 2-way login
+ // ****************************************************
+ // save session id if received
+ if ( aFields->MessageType() == EImpsLoginRes &&
+ aFields->Status() == KErrNone &&
+ aFields->ResponseStatusL() == KImpsStatusOk &&
+ iLoginPhase == 2 )
+ {
+ iLoginPhase++;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SessionStartupL 4-login phase two" ) );
+#endif
+ TImpsDataAccessor myAc( aFields );
+
+ TPtrC newId;
+ TImpsSDataUtils::GetLoginSessionIDL( &myAc, newId );
+ // protect us against illegal data from SAP
+ if ( newId.Length() > KImpsMaxSID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ iCSPSessionId = newId;
+
+ // get TimeToLive
+ TInt newTime( 0 );
+ if ( TImpsSDataUtils::GetKeepAliveL( &myAc, newTime ) )
+ {
+ iAliveTime = newTime;
+ }
+
+ NewState( EImpsCSPLogged );
+ // This is next message to be sent
+ iMsg = EImpsClientCapabilityReq;
+
+ // KeepAlive timer started when logged in
+ iAliveMgr->StartTimer( iAliveTime );
+ // Start polling timer with a static value to be sure that
+ // something is received if SAP happened to send an empty response.
+ // After capability negotiation a proper value is set for polling timer.
+ iPollState = EImpsPollAdaptive;
+ iIdleTimer->Start( iSettings.iMaxPollTime );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+ CImpsClientLogger::Log( _L( "CSPSession: PollTime %d" ), iSettings.iMaxPollTime );
+ CImpsClientLogger::Log( _L( "CSPSession: AliveTime %d" ), iAliveTime );
+#endif
+
+ // Let's send Client Capability request
+ TRAP( errx, DoSendClientCapabilityReqL() );
+ if ( errx )
+ {
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ iServer.SendErrorEvent( EImpsEventServerLogin,
+ KImpsErrorCapabilities, 0, csp );
+ }
+ return;
+ } // LOGIN RESPONSE
+
+
+ // Client capability response
+ // ***************************
+ if ( aFields->MessageType() == EImpsClientCapabilityRes &&
+ aFields->Status() == KErrNone &&
+ IsLogged() )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SessionStartupL ClientCapabality" ) );
+#endif
+ TRAP( errx, HandleClientCapabilityResL ( aFields ) );
+ if ( errx )
+ {
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ iServer.SendErrorEvent( EImpsEventServerLogin, KImpsErrorCapabilities, 0, csp );
+ NewState( EImpsCSPLogged );
+ }
+ // Let's send Service Negotiation request
+ TRAP( errx, DoSendServiceNegotiationReqL () );
+ if ( errx )
+ {
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ iServer.SendErrorEvent( EImpsEventServerLogin, KImpsErrorServices, 0, csp );
+ NewState( EImpsCSPLogged );
+ }
+ return;
+ }
+
+ // Service Negotiation response
+ // ****************************
+ if ( aFields->MessageType() == EImpsServiceRes &&
+ aFields->Status() == KErrNone &&
+ IsLogged() )
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SessionStartupL ServiceRes" ) );
+#endif
+ iTempTid2 = KNullDesC;
+
+ if ( aFields->MessageType() == EImpsServiceRes )
+ {
+ TImpsDataAccessor myAccess( aFields );
+ // Calculate agreed features and functions
+ TImpsSrvUtils::DiscardServicesL(
+ &myAccess,
+ &iServices );
+ }
+
+ // WV engine state in ON_LINE now
+ iIntStatus = EInternal_ON_LINE;
+ NewState( EImpsCSPOnLine );
+ iMsg = EImpsMessageNone;
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: status ON_LINE" ) );
+#endif
+ // Send events to clients
+ iServer.TransportStatus( EInternal_ON_LINE, this );
+
+ // Start PDP idle time if WAP-SMS-CIR is negotiated as only CIR channel.
+ if ( iSettings.iSMSWAPCIR == 2 ||
+ iSettings.iUDPWAPCIR == 2 ||
+ iSettings.iTCPSCIR == 2 ||
+ iSettings.iUDPSCIR == 2 )
+ {
+ // goto CIR-polling-mode
+ iPollState = EImpsPollCIR;
+ iPollTime = iSettings.CIRModePollTime();
+ iIdleTimer->Start( iPollTime );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+ CImpsClientLogger::Log( _L( "CSPSession: iPollTime %d" ), iPollTime );
+#endif
+ }
+ if ( iSettings.iSMSWAPCIR == 2 )
+ {
+ // PDP Idle timer closes PDP-context
+ iPDPIdleTimer->Start( iSettings.PDPExpiryTime() );
+ }
+
+ TInt errxy = KErrNone;
+ TRAP( errxy, DoStartIpCIRL() );
+ }
+
+ // Error handling in negotiation phase AND FOR 4-WAY-LOGIN
+ // ********************************************************
+ if ( ( aFields->Status() != KErrNone ) ||
+ ( aFields->ResponseStatusL() != KImpsStatusOk &&
+ aFields->ResponseStatusL() != 0 ) )
+ {
+ TInt errorCode = KErrNone;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SessionStartupL Error handling %d" ), iMsg );
+#endif
+ switch ( iMsg )
+ {
+ case EImpsClientCapabilityReq:
+ errorCode = KImpsErrorCapabilities;
+ break;
+ case EImpsServiceReq:
+ errorCode = KImpsErrorServices;
+ break;
+ default:
+ break;
+ }
+ if ( errorCode )
+ {
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ iServer.SendErrorEvent( EImpsEventServerLogin, errorCode, 0, csp );
+ // We assume that an application will call logout in this case
+ // and thus we do not close PDP here.
+ }
+ else
+ {
+ // RouteMessageL handles errors if iLoginPhase != 2
+ NewState( EImpsCSPIdle );
+ // routeMessaegL does not close PDP context so let't do it now
+ iReceiver2->CloseTr();
+ }
+ }
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SessionStartupL ends" ) );
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoSendClientCapabilityReqL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoSendClientCapabilityReqL ()
+ {
+ CImpsFields* tempFields = CImpsFields::NewL();
+ CleanupStack::PushL( tempFields ); // <<< tempFields
+ tempFields->SetMessageType( EImpsClientCapabilityReq );
+ tempFields->SetSessionTypeL( EImpsInband );
+ iTempTid2 = GenerateTid();
+ TImpsDataAccessor myAccess( tempFields );
+
+ iMultiTrans = iSettings.iMultiTrans;
+ iPollTime = iSettings.iPollTime;
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: MaxParserSize=%d" ), iSettings.MaximumParserSize() );
+ CImpsClientLogger::Log( _L( "CSPSession: MaxMessageSize=%d" ), iSettings.MaximumMessageSize() );
+#endif
+
+ TImpsSDataUtils::CreateClientCapabilityReqL(
+ &myAccess,
+ iCSPSessionId,
+ iTempTid2,
+ iLogCID,
+ iMultiTrans,
+ iPollTime,
+ iSettings );
+ // Put Client Capability request into queue to wait sending
+ // Do not copy but add this instance.
+ // Negotiation phase expiry time is saved in iNegoExpiry so does not
+ // matter what we set here.
+ iMsg = EImpsClientCapabilityReq;
+ QueueClientRequestL( tempFields, 0, EFalse );
+ SendAllQueued();
+ CleanupStack::Pop( 1 ); // tempFields >>>
+ iNegoExpiry = iServer.ExpiryTime( EImpsEventServerLogin );
+ NewState( EImpsCSPNegotiation );
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoSendServiceNegotiationReqL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoSendServiceNegotiationReqL()
+ {
+ iMsg = EImpsServiceReq;
+ CImpsFields* tempFields = CImpsFields::NewL();
+ CleanupStack::PushL( tempFields ); // <<< tempfields
+ tempFields->SetMessageType( EImpsServiceReq );
+ tempFields->SetSessionTypeL( EImpsInband );
+ iTempTid2 = GenerateTid();
+ TImpsDataAccessor myAcc( tempFields );
+
+ // Initialize the iServices again (in case of re-login)
+ TImpsSrvUtils::InitializeServices( iServices, iReactive );
+ TImpsSDataUtils::CreateServiceRequestL(
+ &myAcc,
+ iServices,
+ iCSPSessionId,
+ iTempTid2,
+ iLogCID,
+ iReactive );
+
+ // Put Service Negotiation request into queue to wait sending.
+ // Negotiation phase expiry time is saved in iNegoExpiry so does not
+ // matter what we set here.
+ QueueClientRequestL( tempFields, 0, EFalse );
+ SendAllQueued();
+ CleanupStack::Pop( 1 ); // >>> tempFields
+ iNegoExpiry = iServer.ExpiryTime( EImpsEventServerLogin );
+ NewState( EImpsCSPNegotiation );
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::HandleLoginResponseL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::HandleLoginResponseL ( CImpsFields* aFields )
+ {
+ // protect us against illegal data from SAP
+ TImpsDataAccessor myAc( aFields );
+
+ TPtrC newId;
+ TImpsSDataUtils::GetLoginSessionIDL( &myAc, newId );
+ if ( newId.Length() > KImpsMaxSID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ iCSPSessionId = newId;
+
+ TDesC8* nonce = NULL;
+ CImpsKey* myKey = CImpsKey::NewLC();
+ myKey->AddL( EImpsKeySession );
+ myKey->AddL( EImpsKeyTransaction );
+ myKey->AddL( EImpsKeyTransactionContent );
+ myKey->AddL( EImpsKeyLogin_Response );
+ myKey->AddL( EImpsKeyDigestSchema );
+ TInt schema;
+ TBool sendPwd = myAc.RestoreIntegerL( myKey, schema );
+ if ( sendPwd )
+ {
+ if ( schema == EImpsPWD )
+ {
+ // Now we have to send the PWD
+ sendPwd = ETrue;
+ }
+ else
+ sendPwd = EFalse;
+ }
+ myKey->PopL();
+ myKey->AddL( EImpsKeyNonce );
+ ( void )myAc.RestoreDesc8L( myKey, nonce );
+ TInt newTime( 0 );
+ if ( TImpsSDataUtils::GetKeepAliveL( &myAc, newTime ) )
+ {
+ iAliveTime = newTime;
+ }
+
+ TImpsSDataUtils::SetResultStatusL( myKey, &myAc, KImpsStatusOk );
+
+ CleanupStack::PopAndDestroy( 1 );
+ CImpsFields* tempFields = CImpsFields::NewL();
+ CleanupStack::PushL( tempFields );
+ tempFields->SetMessageType( EImpsLoginReq );
+ iTempTid2 = LogTid();
+
+ TImpsDataAccessor myAcc( tempFields );
+
+ TImpsSDataUtils::CreateLoginReqPhaseTwoL(
+ sendPwd,
+ &myAcc,
+ iCSPSessionId,
+ LogTid(),
+ UserId(),
+ iLogCID,
+ LogPwd(),
+ nonce,
+ iCookie,
+ iAliveTime,
+ iKey1,
+ iKey2 );
+
+ iMsg = EImpsMessageNone;
+
+ // Send 2nd login phase request
+ // Login expiry time is saved in iNegoExpiry so no need to calculate it here.
+ QueueClientRequestL( tempFields, 0, EFalse );
+ SendAllQueued();
+
+ CleanupStack::Pop( 1 );
+ delete iKey1; // not needed anymore
+ iKey1 = NULL;
+ delete iKey2; // not needed anymore
+ iKey2 = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::HandleClientCapabilityResL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::HandleClientCapabilityResL ( CImpsFields* aFields )
+ {
+ iTempTid2 = KNullDesC;
+
+ TImpsDataAccessor myAccess( aFields );
+ CImpsKey* myKey = CImpsKey::NewLC(); // <<< myKey
+
+ const TImpsContent* myContent = KClientCapabilityResElements;
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ myContent,
+ sizeof( KClientCapabilityResElements ) /
+ sizeof( KClientCapabilityResElements[0] ) );
+
+
+ // WV CSP versions are not fully compatible
+ if ( iCSPVersion == EImpsCspVersion11 )
+ {
+ // WV 1.1 code
+ // CapabilityList element
+ myKey->AddL( CREATEKEY( EImpsKeyCapabilityList, 0 ) );
+
+ // We are interested in supported CIR methods, TCP/IP CIR addresses
+ // and polltime.
+ // SupportedBearer is ignored because of we support HTTP only.´
+ // WV 1.1 specific ClientID is ignored too.
+ // AcceptedContentType not in a response based on
+ // Corrigenda Catalog for WV ver 1.1
+ }
+ else
+ {
+ // WV 1.2 code
+ // AgreedCapabilityList element
+ myKey->AddL( CREATEKEY( EImpsKeyAgreedCapabilityList, 0 ) );
+
+ // We are interested in supported CIR methods, TCP/IP CIR addresses
+ // and polltime.
+ // SupportedBearer is ignored because of we support HTTP only.
+ // CIRURL is ignored too because of it is for HTTP CIR binding only
+ // that is not supported by this sw.
+ // <!ELEMENT AgreedCapabilityList
+ // (SupportedBearer*, SupportedCIRMethod*, TCPAddress?, TCPPort?,
+ // ServerPollMin?, CIRURL?)>
+ }
+
+ // ServerPollMin
+ myKey->AddL( CREATEKEY( EImpsKeyServerPollMin, 0 ) );
+ TInt myInt;
+ if ( myAccess.RestoreIntegerL( myKey, myInt ) )
+ {
+ if ( myInt > iPollTime )
+ {
+ iPollTime = myInt;
+ }
+ }
+ // Save new minimum polling time value in settings
+ iSettings.iPollTime = iPollTime;
+
+ // Reset polling timer, ServerPollMin is optional, but if we do not get
+ // new value then we start to us our own suggestion
+ iPollState = EImpsPollAdaptive;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: PollTime %d" ), iPollTime );
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+#endif
+ iIdleTimer->Start( iPollTime );
+
+ // MultiTrans response
+ myKey->ReplaceLastL( CREATEKEY( EImpsKeyMultiTrans, 0 ) );
+ if ( myAccess.RestoreIntegerL( myKey, myInt ) )
+ {
+ iMultiTrans = myInt;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: new iMultiTrans %d" ), iMultiTrans );
+#endif
+ }
+
+ myKey->PopL();
+
+ // SupportedCIRMethod update
+ iSettings.SetCirBindingsL( &myAccess, myKey );
+
+ // TCPAddress
+ TDesC* myPtr;
+ myKey->AddL( CREATEKEY( EImpsKeyTCPAddress, 0 ) );
+ if ( myAccess.RestoreDescL( myKey, myPtr ) )
+ {
+ HBufC* newAttrib = myPtr->AllocL();
+ delete iTCPAddr;
+ iTCPAddr = newAttrib;
+ }
+
+ // TCPPort
+ myKey->ReplaceLastL( CREATEKEY( EImpsKeyTCPPort, 0 ) );
+ if ( myAccess.RestoreIntegerL( myKey, myInt ) )
+ {
+ iTCPPort = ( TUint )myInt;
+ }
+
+ CleanupStack::PopAndDestroy( 1 ); // >>> mKey
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SendPollL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::SendPollL()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SendPollL csp=%d" ), ( TInt )this );
+#endif
+
+ TInt orig = iPollInResume;
+ iPollInResume = 0;
+
+ if ( iIntStatus != EInternal_ON_LINE || IsPDPIdle() )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SendPollL IGNORED" ) );
+#endif
+ iPollInResume = 2;
+ User::Leave( KErrNotReady );
+ }
+
+ // Create Poll request
+ iSnd->Reset();
+ iSnd->SetSessionTypeL( EImpsInband );
+ iSnd->SetMessageType( EImpsPolling );
+ iSnd->SetSessionIdL( iCSPSessionId );
+ CImpsDataAccessor* myAccess = CImpsDataAccessor::NewLC( iSnd ); // <<<
+ CImpsKey* myKey = CImpsKey::NewLC(); // <<<
+ // Add TImpsTransactionMode now
+ myKey->Reset();
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ KTransModeElements,
+ sizeof( KTransModeElements ) /
+ sizeof( KTransModeElements[0] ) );
+ myAccess->StoreIntegerL( myKey, EImpsRequest );
+ myKey->Reset();
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ KTransContentElements,
+ sizeof( KTransContentElements ) /
+ sizeof( KTransContentElements[0] ) );
+ myKey->AddL( CREATEKEY( EImpsKeyPolling_Request, 0 ) );
+ myAccess->StoreEmptyL( myKey );
+
+ // Send
+ iTempTid = KNullDesC;
+ iSnd->SetTidL( iTempTid );
+
+ iPollWasRequested = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollWasRequested->F in SendPollL" ) );
+#endif
+
+ if ( orig >= 1 )
+ {
+ iPollInResume = 2;
+ }
+ DoSendSingleL( myAccess, iTempTid, EImpsPolling, KImpsPollTO );
+ iPollInResume = 0;
+
+ CleanupStack::PopAndDestroy( 2 ); // >> myKey, myAccess
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SendAliveL
+// -----------------------------------------------------------------------------
+TPtrC CImpsCSPSession::SendAliveL( )
+ {
+ return DoSendAliveL();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SendAliveInResume
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::SendAliveInResume( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SendAliveInResume iPendingAlive->T" ) );
+#endif
+ iPendingAlive = ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoSendAliveL
+// -----------------------------------------------------------------------------
+TPtrC CImpsCSPSession::DoSendAliveL( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendAliveL csp=%d" ), ( TInt )this );
+#endif
+
+ // send poll request. Do not update Transaction queue
+ iSnd->Reset();
+ iSnd->SetSessionTypeL( EImpsInband );
+ iSnd->SetMessageType( EImpsKeepAliveReq );
+ iSnd->SetSessionIdL( iCSPSessionId );
+
+ // Set TID
+ TPtrC tid;
+ tid.Set( GenerateTid() );
+ iSnd->SetTidL( tid );
+
+ // Add KeepAlive
+ CImpsDataAccessor* myAc = CImpsDataAccessor::NewLC( iSnd ); // <<< myAc
+ CImpsKey* myk = CImpsKey::NewLC(); // <<< myk
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myk,
+ KKeepAliveReq,
+ sizeof( KKeepAliveReq ) /
+ sizeof( KKeepAliveReq[0] ) );
+ myAc->StoreEmptyL( myk );
+ // Add Transaction mode
+ myk->Reset();
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myk,
+ KTransModeElements,
+ sizeof( KTransModeElements ) /
+ sizeof( KTransModeElements[0] ) );
+ myAc->StoreIntegerL( myk, EImpsRequest );
+
+ if ( IsPDPIdle() ) // PDP idle-> start to open
+ {
+ iPendingAlive = ETrue;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPendingAlive->T" ) );
+#endif
+ if ( iCSPState == EImpsCSPOnLineIdle )
+ {
+ OpenPDP();
+ }
+ else if ( iCSPState == EImpsCSPOnLineIdleStart )
+ {
+ iPendingPDP = EImpsPDPPendOpen;
+ }
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendAliveL POSTPONED ***" ) );
+#endif
+ }
+ else if ( iIntStatus != EInternal_ON_LINE )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendAliveL IGNORED" ) );
+#endif
+ iSnd->Reset();
+ User::Leave( KImpsGeneralError );
+ }
+ else
+ {
+ DoSendSingleL( myAc, iTempTid, EImpsKeepAliveReq, KImpsKeepATO );
+ iPendingAlive = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPendingAlive->F" ) );
+#endif
+ }
+
+ CleanupStack::PopAndDestroy( 2 ); // >>> myk myAc
+
+ return iTempTid;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SendAllQueued
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::SendAllQueued()
+ {
+ // Actually this does not send all messages at once but one by one.
+ // iSendQ calls DoSendAllQueued that calls (in most cases)
+ // this again and so on until no more valid messages found!
+ // DoSendAllQueued handles SAP initiated requests in same way.
+ if ( RequestExist() || SapReqExist() || iPendingAlive ||
+ iPollState == EImpsPollExtWait || iPollInResume == 1 ||
+ iPollWasRequested )
+ {
+ if ( !IsPDPIdle() )
+ {
+ iSendQ->Send();
+ }
+ else if ( iCSPState == EImpsCSPOnLineIdle )
+ {
+ iPollState = EImpsPollCIR;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+#endif
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::CreateSapResponse
+// -----------------------------------------------------------------------------
+TImpsSAPResStatus CImpsCSPSession::CreateSapResponse()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CreateSapResponse begins csp=%d" ), ( TInt )this );
+#endif
+
+ TImpsSAPResStatus ret( EImpsSAPNone );
+ TInt err = KErrNone;
+ // Check if pending SAP initiated CSP transactions exists
+ TDblQueIter<CTransaction> iter2 ( iTransactionList );
+ iter2.SetToFirst();
+ if ( iter2 )
+ {
+ ret = EImpsSAPMore;
+ CTransaction* trans = iter2;
+ // Get first
+ iter2++;
+ CImpsFields* fields = trans->iFields;
+ TInt messageType = fields->MessageType();
+
+ // Try to get actual message type
+ if ( messageType == EImpsPureData )
+ {
+ TRAP( err, TImpsDataAccessor temp ( fields );
+ messageType = TImpsSDataUtils::GetPureMessageTypeL( &temp ) );
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CreateSapResponse messageType=%x" ), messageType );
+#endif
+ // Here we have a list of supported push messages, i.e.
+ // SAP initiated transactions.
+ // Other pushed messages are not supported!
+ // Notice: add new methods as needed
+ // Disconnect is a special case handled before this method call
+ if ( messageType == EImpsNewMessage ||
+ messageType == EImpsLeaveGroupRes ||
+ messageType == EImpsInviteUserReq ||
+ messageType == EImpsInviteRes ||
+ messageType == EImpsCancelInviteUserReq ||
+ messageType == EImpsPresenceNotification ||
+ messageType == EImpsGroupChangeNotice ||
+ messageType == EImpsPresenceAuthReq ||
+ messageType == EImpsDeliveryReportReq
+ )
+ {
+ // This also tries to send a SAP initiated transaction response once immediately
+ TRAP( err, DoMakeSapResponseL( trans ) );
+ if ( !err )
+ {
+ iPollInResume = 0;
+ }
+ // Last request handled.
+ if ( !iter2 )
+ {
+ ret = EImpsSAPLast;
+ iPollInResume = 0;
+
+ // All the WV servers do not work according to WV specs and they seems to need
+ // to get a Poll request instead for SAP initiated transactions, therefore the
+ // extra polling is needed.
+ err = KErrNone;
+ TBool polli ( EFalse );
+ TRAP( err, polli = fields->PollL() )
+ if ( polli )
+ {
+ iPollWasRequested = ETrue;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollWasRequested->T in CreateSapResponse" ) );
+#endif
+ }
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ if ( err )
+ {
+ CImpsClientLogger::Log( _L( "CSPSession: DoMakeSapResponseL ERROR %d" ), err );
+ }
+
+#endif
+ }
+
+ // Transaction is deleted. If the response has failed the WV server should send
+ // the transaction again. Timer limit is not implemented in terminal side here.
+ trans->Destroy();
+
+ } // if (iter2)
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CreateSapResponse returns %d" ), ret );
+#endif
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoSendAllQueuedL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoSendAllQueuedL()
+ {
+
+ TInt errx = KErrNone;
+
+ // Handle login phase specials first
+ // ---------------------------------
+ if ( iLoginPhase != 2 )
+ {
+ if ( !IsLogged() || !iReceiver2->isConnected() ||
+ ( iReceiver2->NbrOfPending() >= KImpsMaxPending ) ||
+ IsPDPIdle() ) // no reason to try if PDP is not open
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendAllQueuedL IGNORED" ) );
+#endif
+ return;
+ }
+ }
+
+ // Pending Alive messages and pending Poll messages
+ // -------------------------------------------------
+ if ( iPendingAlive )
+ {
+ // Pending Alive overrides pending Poll
+ iPendingAlive = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPendingAlive->F" ) );
+#endif
+ iPollInResume = 0;
+ iAliveMgr->SendKeepAlive( EFalse );
+ SendAllQueued();
+ return;
+ }
+ else if ( iPollState == EImpsPollExtWait )
+ {
+ iPollState = EImpsPollCIR;
+ iPollTime = iSettings.CIRModePollTime();
+ iIdleTimer->Start( iPollTime );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+ CImpsClientLogger::Log( _L( "CSPSession: iPollTime %d" ), iPollTime );
+#endif
+ errx = KErrNone;
+ TRAP( errx, SendPollL() );
+ // If Polling fails then try again
+ if ( errx && !iPollInResume )
+ {
+ iPollInResume = 1;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollInResume %d" ), iPollInResume );
+#endif
+ }
+
+ SendAllQueued();
+ return;
+ }
+
+ // Reqular cases
+ // --------------------------
+ CReq* request = NULL;
+
+ if ( iTr < iMultiTrans )
+ {
+ // Try to send terminal initiated request
+ request = GiveNextRequestL();
+
+ // Block messages in negotiation phase
+ if ( request && request->iFields )
+ {
+ TInt msgType = request->iFields->MessageType();
+ if ( iIntStatus != EInternal_ON_LINE &&
+ ( msgType != EImpsKeepAliveReq &&
+ msgType != EImpsClientCapabilityReq &&
+ msgType != EImpsServiceReq &&
+ msgType != EImpsLoginReq &&
+ msgType != EImpsLogoutReq ) )
+
+ {
+ request = NULL;
+ }
+ }
+
+ if ( request )
+ {
+ iPollInResume = 0;
+ // Send next buffered user request if any
+ // search. Not immediately, but via active object scheduler
+ SendAllQueued();
+
+ CImpsFields* fields = request->iFields;
+ errx = KErrNone;
+ TRAP( errx, DoSendNextBufferedL( fields ) );
+ // Delete the client request
+ request->Destroy();
+ } // if request
+ }
+
+ if ( !request )
+ {
+ // Check if SAP initiated message instead of terminal initiated one.
+ // This sends data and calls SendAllQueued if needed.
+ // comment: SAP responses should not exists in PDP-idle state
+
+ // CreateSapResponse not only create the response but also tries to send it..
+ TImpsSAPResStatus sapr = CreateSapResponse();
+ if ( ( sapr != EImpsSAPMore ) &&
+ ( iPollWasRequested || iPollInResume == 1 ) &&
+ ( IsLogged() ) )
+ {
+ errx = KErrNone;
+ // If Poll fails then re-try polling when GPRS resumes
+ TRAP( errx, SendPollL() );
+ if ( errx && !iPollInResume )
+ {
+ iPollInResume = 1;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: iPollInResume %d" ), iPollInResume );
+#endif
+ }
+ }
+ else if ( sapr == EImpsSAPMore )
+ {
+ SendAllQueued();
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::CancelTrans
+// client subsession calls this when request expires
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::CancelTrans( const TDesC& aTID )
+ {
+ DeleteRequest( aTID );
+ // CancelTrans does not cause callback.
+ iReceiver2->CancelTrans( aTID );
+ TrMinus();
+ // Check if login-req expires and change CSP state
+ if ( iCSPState == EImpsCSPLogging && !aTID.Compare( LogTid() ) )
+ {
+ NewState( EImpsCSPIdle );
+ CancelData();
+ }
+
+ SendAllQueued();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::GenerateTid
+// -----------------------------------------------------------------------------
+TPtrC CImpsCSPSession::GenerateTid( )
+ {
+ // iCounter++;
+ // TInt tidNbr = iCounter;
+ TInt tidNbr = iServer.TidSeed();
+ iTempTid = KNullDesC;
+ iTempTid = _L( "nok" );
+ iTempTid.AppendFormat( _L( "%d" ), tidNbr );
+ return iTempTid;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::GenerateCookie
+// -----------------------------------------------------------------------------
+TPtrC CImpsCSPSession::GenerateCookie( )
+ {
+ TTime myTime;
+ myTime.HomeTime();
+ const TInt64& seed = myTime.Int64();
+ TUint low = I64LOW( seed );
+ TUint high = I64HIGH( seed );
+ TInt64 seed2 MAKE_TINT64( high, low );
+ iCookie = KNullDesC;
+ iCookie = _L( "wv:nokia." );
+#ifndef _FAKE_RESPONSE
+ TInt tidNbr = Math::Rand( seed2 );
+ iCookie.AppendFormat( _L( "%d" ), tidNbr );
+#else
+ iCookie.AppendFormat( _L( "%d" ), 12345 );
+#endif
+ // copy to 8-bit buffer for CIR
+ iCookie8.Copy( iCookie );
+ return iCookie;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoLogout
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoLogout( )
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoLogout" ) );
+#endif
+ DoLogoutNow( 0 );
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoLogoutNow
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoLogoutNow( TInt aOpId )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoLogoutNow opid=%d, log=%d csp=%d" ),
+ aOpId, IsLogged(), ( TInt )this );
+#endif
+
+ // save old status for this method
+ TBool oldLogged = IsLogged();
+ TImpsCSPState oldState = iCSPState;
+ NewState( EImpsCSPIdle );
+
+ iAliveMgr->StopTimer();
+ iIdleTimer->Stop();
+ // stop PDP idle timer in logout routines
+ iPDPIdleTimer->Stop( );
+ iPDPOpenTimer->Stop( );
+ iPollState = EImpsPollNone;
+ iPendingPDP = EImpsPDPPendNone;
+ iPendPDPLogout = EFalse;
+ iPollWasRequested = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d iPollWasRequested->F in logout" ), iPollState );
+#endif
+
+ // Reset settings for further logins
+ ResetSession();
+
+ iSendQ->Cancel();
+
+ // Reset local variables
+ iIntStatus = EInternal_NOT_LOGGED;
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: status NOT_LOGGED" ) );
+#endif
+
+ // Clean own queues
+ DeleteRequests();
+ DeleteTransactions();
+ iTidSapHistory->DeleteAll();
+ iTidCliHistory->DeleteAll();
+
+ // Close ip cir
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CLOSE IP-CIR CHANNEL" ) );
+#endif
+ if ( iCirManager )
+ {
+ // Close all cir bindings
+ iCirManager->CloseCh( 0xF );
+ }
+
+ // Cancel the HTTP transport in logout
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CANCEL TRANSPORT IN DOLOGOUT" ) );
+#endif
+ CancelData();
+
+ // Clean server core and send logout and status events there.
+ // We first detect if this is really CSP disconnect situation.
+ TBool cspDisconnect = ( oldLogged || oldState == EImpsCSPDisconnecting ) ?
+ ETrue : EFalse ;
+ iServer.DoLogoutSrv( aOpId, cspDisconnect, this );
+
+ delete iSAP;
+ iSAP = NULL;
+ iIAP = 0;
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CLOSE TRANSPORT SOON..." ) );
+#endif
+ if ( iReceiver2->Close2() == KErrCancel )
+ {
+ // Start to delete this session asynchronously
+ // if there is nothing to close.
+ iServer.TransportStatus( EInternal_NO_IAP, this );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::CancelData
+// server CloseSession calls this
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::CancelData( )
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CancelData csp=%d" ), ( TInt )this );
+#endif
+ // Cancel the HTTP transport now, no callback
+ iReceiver2->Cancel();
+ // Must reset variables because if new Login request mey be
+ // received before WV Engine is shut down and CloseEngine() called.
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::QueueClientRequestL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::QueueClientRequestL(
+ CImpsFields* aFields,
+ TInt aExpiry,
+ TBool aLast )
+ {
+ // Check if subsession specific expiry time needed
+ CReq* req = new ( ELeave ) CReq( aFields );
+ if ( !aExpiry )
+ {
+ req->iExpiry = iServer.ExpiryTime( ( TImpsMessageType ) aFields->MessageType() );
+ }
+ else
+ {
+ req->iExpiry = iServer.ExpiryTime( aExpiry );
+ }
+
+ // Put request into queue in a right place,
+ if ( aLast )
+ {
+ iRequestList.AddLast( *req );
+ }
+ else
+ {
+ iRequestList.AddFirst( *req );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::QueueTidL
+// This resets iRcv!
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::QueueTidL( TBool aOrphan )
+ {
+
+ if ( !ValidateTid( EFalse ) )
+ {
+ // TID is already responded to SAP
+ return;
+ }
+
+ TPtrC tid;
+ TImpsDataAccessor myAccess( iRcv );
+ TImpsDataUtils::GetTransactionIDL( &myAccess, tid );
+
+ if ( tid.Length() > 0 )
+ {
+
+ // Add new Sap initiated transaction to queue
+ CTransaction* trans = new ( ELeave ) CTransaction(
+ aOrphan,
+ tid, // tid
+ iRcv->SessionIdL(), // session-id
+ ( TImpsMessageType ) iRcv->MessageType(),
+ iRcv );
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: QUEUE SAP TID=%S csp=%d" ),
+ &( trans->iTID ), ( TInt )this ); //lint !e525
+#endif
+
+ iTransactionList.AddLast( *trans );
+ iRcv = NULL;
+ iRcv = CImpsFields::NewL();
+ iRcv->Reset();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::ValidateTid
+// Validate SAP initiated TID
+// -----------------------------------------------------------------------------
+TBool CImpsCSPSession::ValidateTid( TBool aClientHistory )
+ {
+
+ // The requesting entity may resend the request message using the same
+ // transaction identifier. The responding entity should
+ // guarantee that the requested operation or data is carried out only once,
+ // even if multiple request messages with the same transaction identifier
+ // are received.
+
+ // Check that TID has not already sent to clients or has not responded to SAP.
+
+ TPtrC tid;
+ TImpsDataAccessor myAccess( iRcv );
+ TInt errx = KErrNone;
+ TRAP( errx, TImpsDataUtils::GetTransactionIDL( &myAccess, tid ) );
+
+ if ( tid.Length() > 0 )
+ {
+ if ( aClientHistory && iTidCliHistory->TidFound( tid ) )
+ {
+ // TID has sent to clients
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: already received TID=%S ***" ), &tid );
+#endif
+ return EFalse;
+ }
+ else if ( aClientHistory /* && !iTidCliHistory->TidFound( tid )*/ )
+ {
+ // Save TId into client history
+ iTidCliHistory->Add( tid );
+ }
+ else if ( !aClientHistory && iTidSapHistory->TidFound( tid ) )
+ {
+ // TID has already responded to SAP
+ // TID-SAP-history has been updated when the transport response is sent
+ // successfully to SAP (i.e. no transport error)
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: already responded TID=%S ***" ), &tid );
+#endif
+ return EFalse;
+ }
+ }
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DiscardTid
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DiscardTid( const TDesC& aTid )
+ {
+ // Delete buffered transaction
+ TDblQueIter<CTransaction> rIter( iTransactionList );
+ rIter.SetToFirst();
+ while ( rIter )
+ {
+ CTransaction* trans = rIter;
+ rIter++;
+ if ( !trans->iTID.Compare( aTid ) )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DiscardTid deletes a request " ) );
+#endif
+ trans->Destroy();
+ return;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DeleteTransactions
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DeleteTransactions()
+ {
+ // Delete all buffered transactions
+ TDblQueIter<CTransaction> rIter( iTransactionList );
+
+ rIter.SetToFirst();
+
+ while ( rIter )
+ {
+ CTransaction* trans = rIter;
+ rIter++;
+ trans->Destroy();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DeleteRequests
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DeleteRequests()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DeleteRequests csp=%d" ), ( TInt )this );
+#endif
+ // Delete all buffered transaction requests
+ TDblQueIter<CReq> rIter( iRequestList );
+ rIter.SetToFirst();
+
+ while ( rIter )
+ {
+ CReq* req = rIter;
+ rIter++;
+ req->Destroy();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DeleteRequest
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DeleteRequest( const TDesC& aTID )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DeleteRequest tid=%S csp=%d" ), &aTID, ( TInt )this );
+#endif
+ // Delete buffered transaction request
+ TInt errx = KErrNone;
+ TPtrC p( KNullDesC );
+
+ TDblQueIter<CReq> rIter( iRequestList );
+ rIter.SetToFirst();
+
+ while ( rIter )
+ {
+ CReq* req = rIter;
+ rIter++;
+ TRAP( errx, p.Set( req->iFields->TidL() ) );
+ if ( !p.Compare( aTID ) )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DeleteRequest MATCH tid=%S csp=%d" ), &aTID, ( TInt )this );
+#endif
+ req->Destroy();
+
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::RequestExist
+// -----------------------------------------------------------------------------
+TBool CImpsCSPSession::RequestExist()
+ {
+ // Check buffered transactions
+ TDblQueIter<CReq> rIter( iRequestList );
+
+ rIter.SetToFirst();
+
+ if ( rIter )
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SapReqExist
+// -----------------------------------------------------------------------------
+TBool CImpsCSPSession::SapReqExist()
+ {
+ TDblQueIter<CTransaction> iter2 ( iTransactionList );
+ iter2.SetToFirst();
+ if ( iter2 )
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoSendNextBufferedL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoSendNextBufferedL( CImpsFields* aFields )
+ {
+ TImpsDataAccessor myAccess( aFields );
+ TRAPD( err, DoSendSingleL( &myAccess, aFields->TidL(),
+ ( TImpsMessageType )aFields->MessageType() ) );
+ if ( err )
+ {
+ // send an error event
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendSingleL ERROR=%d csp=%d" ), err, ( TInt )this );
+#endif
+ iSnd->Reset();
+ iSnd->SetStatus( err );
+ iSnd->SetTidL( aFields->TidL() );
+ TBool someFound;
+ // This sends error event to the right client session
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ iServer.CheckRequestsL( iSnd, someFound, csp );
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsCSPSession::TransportStatus
+// ---------------------------------------------------------
+//
+void CImpsCSPSession::TransportStatus(
+ EImpsInternalStatus aConnectionState )
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: TransportStatus=%d old=%d state=%d csp=%d" ),
+ ( TInt ) aConnectionState, iIntStatus, iCSPState, ( TInt )this );
+#endif
+
+ TInt errx = KErrNone;
+ TRAP( errx, DoTransportStatusL ( aConnectionState ) );
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: TransportStatus ends" ) );
+#endif
+
+ }
+
+// ---------------------------------------------------------
+// CImpsCSPSession::DoTransportStatusL
+// ---------------------------------------------------------
+//
+void CImpsCSPSession::DoTransportStatusL(
+ EImpsInternalStatus aConnectionState )
+ {
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ EImpsInternalStatus oldStatus = iIntStatus;
+
+ // If there is pending logout request then the login is cancelled and
+ // logout performed immediately.
+ if ( iPendingLogout || iCancelLogin )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: ex3 iPendingLogout->F *****" ) );
+#endif
+ iPendingLogout = EFalse;
+ if ( iCSPState == EImpsCSPLogging )
+ {
+ // This sends first a login response
+ iServer.DiscardRequest( LogTid(), EImpsEventServerLogin, KErrCancel, csp );
+ // Special case where login is cancelled
+ if ( aConnectionState == EInternal_NO_IAP )
+ {
+ iServer.DiscardLogout( LogoutTID(), csp );
+ // below rest of activities are done
+ }
+ }
+ }
+
+ // *********************************************
+ // PDP idle situations handled first
+ if ( IsPDPIdle() )
+ {
+ if ( aConnectionState == EInternal_NO_IAP )
+ {
+ NewState( EImpsCSPOnLineIdle );
+ // In a rare situation there is pending PDP open request
+ // received when PDP is closing down.
+ if ( iPendingPDP == EImpsPDPPendOpen )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPendingLogout->F in NO_IAP ***" ) );
+#endif
+ iPendingPDP = EImpsPDPPendNone;
+ OpenPDP();
+ }
+ return;
+ }
+ else if ( aConnectionState == EInternal_IAP_OPEN )
+ {
+ // PDP re-open completes here.
+ NewState( EImpsCSPOnLine );
+ if ( iPendingPDP == EImpsPDPPendOpen )
+ {
+ iPendingPDP = EImpsPDPPendNone;
+ }
+ // pending logout if PDP-context has been opened for Logout msg
+ if ( iPendPDPLogout )
+ {
+ iPendPDPLogout = EFalse;
+ iPendingPDP = EImpsPDPPendNone;
+ TRAPD( errx, DoSendLogoutL( LogoutTID() ) );
+ if ( errx )
+ {
+ // E5: Typically Bearer Suspended error with bad luck
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: E5 ****" ) );
+#endif
+ DoLogout();
+ }
+ }
+ else
+ {
+ // Send all queued reqular requests to transport
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Normal PDP open ***" ) );
+#endif
+ iPollInResume = 1;
+ // *********************************************************
+ // Notice: we assume that GPRS is resumed in this case even
+ // if ConnManager DLL cannot provide us such an information
+ // in all cases.
+ iIntStatus = EInternal_ON_LINE;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: status ON_LINE" ) );
+#endif
+ // start ip-cir-channels if not running
+ TInt errxy = KErrNone;
+ TRAP( errxy, DoStartIpCIRL() );
+ }
+ // Send all queued requests to transport
+ SendAllQueued();
+ }
+ }
+
+ // *********************************************
+ // NO PDP IDLE STARTS HERE
+ else if ( aConnectionState == EInternal_ON_LINE && IsNegotiated() )
+ {
+ iIntStatus = EInternal_ON_LINE;
+ // we assume that old messages are in a bit heaven
+ iTr = 0;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: status ON_LINE" ) );
+#endif
+ if ( iPollState == EImpsPollPending )
+ {
+ iPollState = EImpsPollExtWait;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+#endif
+ }
+
+ // This makes poll to be sent if no other requests
+ iPollInResume = 1;
+
+ // pending logout if PDP-context has been opened for Logout msg
+ if ( iPendPDPLogout )
+ {
+ iPendPDPLogout = EFalse;
+ DoSendLogoutL( LogoutTID() );
+ }
+ else
+ {
+ SendAllQueued();
+ // start ip-cir-channels if not running
+ TInt errxy = KErrNone;
+ TRAP( errxy, DoStartIpCIRL() );
+ }
+ }
+ else if ( aConnectionState == EInternal_ON_LINE && !IsNegotiated() )
+ {
+ iIntStatus = EInternal_NOT_LOGGED;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: status NOT_LOGGED" ) );
+#endif
+ if ( IsLogged() )
+ {
+ // Rare situation where GPRS resume is taken place in negotiation phase.
+ // iAliveMgr->SendKeepAlive( EFalse );
+ SendAllQueued();
+ }
+ }
+ else if ( aConnectionState == EInternal_OFF_LINE &&
+ oldStatus == EInternal_ON_LINE )
+ {
+ iIntStatus = EInternal_OFF_LINE;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: status OFF_LINE" ) );
+#endif
+ }
+ else if ( iCSPState == EImpsCSPLogging &&
+ ( aConnectionState == EInternal_NO_IAP ||
+ aConnectionState == EInternal_NO_IAP_AUTH ) )
+ {
+ // Discard request immediately in this case
+ // This sends first a login response
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: Login cancelled" ) );
+#endif
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ iServer.DiscardRequest( LogTid(), EImpsEventServerLogin, KImpsErrorBearerSuspended, csp );
+ DoLogout();
+ }
+ else if ( aConnectionState == EInternal_NO_IAP )
+ {
+ if ( IsNegotiated() )
+ {
+ // Check if no WAP SMS CIR negotiated then do logout.
+ // Otherwise close PDP connection only
+ if ( iSettings.iSMSWAPCIR == 2 ) // WAP CIR
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: PDP LOST SMS-CIR ***" ) );
+#endif
+ NewState( EImpsCSPOnLineIdle );
+ if ( iPendingPDP == EImpsPDPPendClose )
+ {
+ iPendingPDP = EImpsPDPPendNone;
+ ClosePDP();
+ }
+ return;
+ }
+ else // no WAP CIR
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: PDP LOST NO-SMS-CIR ***" ) );
+#endif
+ DoLogout();
+ }
+ }
+ else
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: err: PDP LOST NOT-NEGOTIATED ***" ) );
+#endif
+ if ( !IsLogged() )
+ {
+ iIntStatus = EInternal_NOT_LOGGED;
+ // This causes DoLogout call from CImpsServer.
+ iServer.TransportStatus( EInternal_NO_IAP, this );
+ NewState( EImpsCSPIdle );
+ return;
+ }
+ else
+ // PDP can be lost in negotiation phase. Then we do internal
+ // logout.
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: LOGGED BUT NOT-NEGOTIATED -> Logout ***" ) );
+#endif
+ DoLogout();
+ }
+ }
+ }
+ else if ( aConnectionState == EInternal_NO_IAP_AUTH )
+ {
+ // Handle authorative bearer-lost situation here and
+ // make CSP logout
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: NO_IAP_AUTH ***" ) );
+#endif
+ iIntStatus = EInternal_NOT_LOGGED;
+ DoLogout();
+ }
+
+ // Call server's TransportStatus only if this is a state change from
+ // LOGGED->NOT_LOGGED.
+ // NOT_LOGGED event clears the client session CSP identification data and
+ // thus it must not be called in vain..
+ if ( iIntStatus == EInternal_NOT_LOGGED && oldStatus != EInternal_NOT_LOGGED )
+ {
+ iServer.TransportStatus( iIntStatus, this );
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsCSPSession::CirChOpened
+// ---------------------------------------------------------
+//
+void CImpsCSPSession::CirChOpened( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CirChOpened" ) );
+#endif
+ iTcpCIRError = EFalse;
+ }
+
+// ---------------------------------------------------------
+// CImpsCSPSession::CirChError
+// ---------------------------------------------------------
+//
+void CImpsCSPSession::CirChError( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: CirChError csp=%d" ), ( TInt )this );
+#endif
+ delete iCirManager;
+ iCirManager = NULL;
+ // start poll mode again
+ if ( IsLogged() )
+ {
+ iPollTime = iSettings.iPollTime;
+ iPollState = EImpsPollAdaptive;
+ iIdleTimer->Start( iPollTime );
+ iPDPIdleTimer->Stop();
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iPollState %d" ), iPollState );
+ CImpsClientLogger::Log( _L( "CSPSession: iPollTime %d" ), iPollTime );
+#endif
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsCSPSession::SetConnAllowed
+// ---------------------------------------------------------
+//
+void CImpsCSPSession::SetConnAllowed( TBool aParam )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: SetConnAllowed %d" ), aParam );
+#endif
+ iConAllowed = aParam;
+ // Logout CSP session on behalf of user if terminal connection is not allowed.
+ if ( !aParam )
+ {
+ // It's important that data channel is started to close first and after
+ // that internal CSP disconnect is done.
+ iReceiver2->CloseTr( );
+ DoLogout( );
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsCSPSession::DoSendSingleL
+// aAc connot be null
+// ---------------------------------------------------------
+//
+void CImpsCSPSession::DoSendSingleL(
+ MImpsDataAccessor* aAc,
+ const TDesC& aTID,
+ TImpsMessageType aMsgType,
+ TInt aExpiryTime )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendSingle messagetype = 0x%x csp=%d" ),
+ aMsgType, ( TInt )this );
+#endif
+
+ // Set the WV 1.2 version if needed, WV 1.1 is the default
+ if ( iCSPVersion == EImpsCspVersion12 )
+ {
+ CImpsFields* f = aAc->GetImpsFields();
+ f->SetCspVersion( EImpsCspVersion12 );
+ }
+
+ // Encode the message
+ iEncoder->EncodeMessageL( *aAc, *iTransportOut );
+
+ // Send to the transport module
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendSingle message encoded = 0x%x" ), aMsgType );
+#endif
+
+ // reset PDP idle timer
+ iPDPIdleTimer->Reset();
+
+ iReceiver2->SendAndWaitL( aTID, aExpiryTime );
+ iLastSent = aMsgType;
+
+ // Notice: Maintain this list of non terminal originated
+ // transactions, send by terminal to SAP.
+ if ( !( aMsgType == EImpsPolling || aMsgType == EImpsKeepAliveReq ||
+ aMsgType == EImpsStatus || aMsgType == EImpsMessageDelivered ) )
+ {
+ iTr++;
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendSingle iTr = %d" ), iTr );
+#endif
+ }
+ // Anything except Poll and KeepAlive request resets Poll Timer.
+ if ( !( aMsgType == EImpsPolling || aMsgType == EImpsKeepAliveReq ) )
+ {
+ ResetPollTime( );
+ }
+
+#ifdef _FAKE_RESPONSE
+ iTestMsgTid = aTID;
+#endif
+ }
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoSendLogoutL
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoSendLogoutL( const TDesC& aTID )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendLogoutL csp=%d" ), ( TInt )this );
+#endif
+
+ // Check if the transport is halted
+ if ( iReceiver2->NbrOfPending() >= KImpsMaxPending )
+ {
+ User::Leave( KErrInUse );
+ }
+
+ NewState( EImpsCSPDisconnecting );
+ // Set expiry time for logout.
+ // In case of Login-csncel expiry time is not overwritten, but it
+ // is the original login expiry time.
+ // Otherwise clint session would expire first and the user client would get
+ // normal time-out error, but we want that the user gets OK response.
+ if ( !iCancelLogin )
+ {
+ iNegoExpiry = iServer.ExpiryTime( EImpsEventServerLogin );
+ }
+
+ // Make a logout request (encode)
+ iSnd->Reset();
+
+ // Insert CSP Session-id
+ iSnd->SetSessionIdL( iCSPSessionId );
+ iSnd->SetTidL( aTID );
+ iSnd->SetMessageType( EImpsLogoutReq );
+
+ // Session type is inband
+ iSnd->SetSessionTypeL( EImpsInband );
+
+ TImpsDataAccessor myAc( iSnd );
+ CImpsKey* myKey = CImpsKey::NewLC(); // <<< myKey
+
+ // Add TImpsTransactionMode
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ KTransModeElements,
+ sizeof( KTransModeElements ) /
+ sizeof( KTransModeElements[0] ) );
+ myAc.StoreIntegerL( myKey, EImpsRequest );
+ myKey->Reset();
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ KTransContentElements,
+ sizeof( KTransContentElements ) /
+ sizeof( KTransContentElements[0] ) );
+ myKey->AddL( CREATEKEY( EImpsKeyLogout_Request, 0 ) );
+ myAc.StoreEmptyL( myKey );
+
+ CleanupStack::PopAndDestroy( 1 ); // >>> myKey
+
+ DoSendSingleL( &myAc, aTID, EImpsLogoutReq );
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoMakeSapResponseL
+// -----------------------------------------------------------------------------
+//
+void CImpsCSPSession::DoMakeSapResponseL( CTransaction* aTrans )
+ {
+ TPtrC tid;
+ CImpsFields* fields = aTrans->iFields;
+ tid.Set( aTrans->iTID );
+ TInt messageType = fields->MessageType();
+
+ TInt responseType = EImpsStatus;
+ // Copy values from the new message to a response
+ iSnd->Reset();
+ iSnd->SetSessionIdL( fields->SessionIdL() );
+ iSnd->SetTidL( fields->TidL() );
+ iSnd->SetSessionTypeL( EImpsInband );
+
+#ifndef _NO_IMPS_LOGGING_
+ TPtrC tid2;
+ tid2.Set( fields->TidL() );
+ CImpsClientLogger::Log( _L( "CSPSession: MakeSAPresp SAP TID=%S" ), &( tid2 ) );//lint !e525
+#endif
+
+ CImpsDataAccessor* myAccess = CImpsDataAccessor::NewL( iSnd );
+ CleanupStack::PushL( myAccess ); // << myAccess
+ CImpsKey* myKey = CImpsKey::NewLC(); // <<< myKey
+
+ CImpsDataAccessor* myAcRcv = CImpsDataAccessor::NewL( fields );
+ CleanupStack::PushL( myAcRcv ); // << myAcRcv
+
+ TPtrC myId;
+
+ switch ( messageType )
+ {
+ case EImpsNewMessage:
+ responseType = EImpsMessageDelivered;
+ iSnd->SetMessageType( responseType );
+ // Get messageId from received message
+ TImpsSDataUtils::GetNewMessageIdL( myKey, myAcRcv, myId );
+ // ... and copy data to outgoing response
+ TImpsSDataUtils::SetMessageDeliveredIdL(
+ myKey, myAccess, myId );
+ break;
+ default:
+ iSnd->SetMessageType( responseType );
+ TImpsSDataUtils::SetResultStatusL( myKey, myAccess, KImpsStatusOk );
+ break;
+ }
+
+ CleanupStack::PopAndDestroy( 1 ); // >> myAcRcv
+
+ // Add TImpsTransactionMode now
+ myKey->Reset();
+ TImpsSDataUtils::AddValuesFromArrayL(
+ myKey,
+ KTransModeElements,
+ sizeof( KTransModeElements ) /
+ sizeof( KTransModeElements[0] ) );
+ myAccess->StoreIntegerL( myKey, EImpsResponse );
+ CleanupStack::PopAndDestroy( 1 ); // >>> myKey
+
+ // -------------------------------------------
+ // Handle orphan message
+ if ( aTrans->iOrphan )
+ {
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ TRAPD( errx, iServer.HandleOrphanL( aTrans->iFields, csp ) );
+ if ( !errx )
+ {
+ // ownership of the msg is in CImpsServer now
+ aTrans->iFields = NULL;
+ }
+ }
+ // -------------------------------------------
+
+ // DoSendSingleL leaves if GPRS suspended,
+ // so don't delete entry too early
+ DoSendSingleL( myAccess, tid, ( TImpsMessageType )responseType );
+
+
+ // Save TID into tid-sap-history so that we so not send the response twicw
+ // even if SAP would send the transaction multiple times.
+ iTidSapHistory->Add( tid );
+
+ CleanupStack::PopAndDestroy( 1 ); // >> myAccess
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoStartIpCIRL
+// -----------------------------------------------------------------------------
+//
+void CImpsCSPSession::DoStartIpCIRL()
+ {
+ // Start ip-cir-watcher
+ if ( iVariant.IsFeatureSupportedL( EIpCirStandalone ) &&
+ iSettings.iTCPSCIR == 2 || iSettings.iUDPSCIR == 2 )
+ {
+ // Check which CIR bindings are negotiated for CSP session
+ TUint ipChannels = 0;
+ if ( iSettings.iTCPSCIR == 2 )
+ {
+ ipChannels = KImpsCirTcp;
+ }
+ if ( iSettings.iUDPSCIR == 2 )
+ {
+ ipChannels = ipChannels | KImpsCirUdp;
+ }
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: Starting ip-cir-watcher %d" ),
+ ipChannels );
+#endif
+ iCSPSessionId8.Copy( iCSPSessionId );
+ if ( !iCirManager )
+ {
+ iCirManager = CImpsCirManager::NewL( *this,
+ CActive::EPriorityStandard );
+ }
+ iCirManager->OpenChL( ipChannels, iReceiver2->ConnManagerHandleL(),
+ iTCPPort, *iTCPAddr, iCSPSessionId8 );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::IncreasePollTime
+// -----------------------------------------------------------------------------
+//
+void CImpsCSPSession::IncreasePollTime()
+ {
+ // Increase poll timer. Two modes; CIR Mode and other modes.
+ if ( iPollState == EImpsPollCIR )
+ {
+ ResetPollTime();
+ }
+ else if ( iPollTime < iSettings.iMaxPollTime && iIdleTimer->IsActive() )
+ {
+ iPollTime += KImpsPollIncrement;
+ iIdleTimer->Start( iPollTime );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: PollTime increased to %d" ), iPollTime );
+#endif
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::ResetPollTime
+// -----------------------------------------------------------------------------
+//
+void CImpsCSPSession::ResetPollTime()
+ {
+ // Reset poll timer. Two modes; CIR Mode and other modes.
+ if ( iPollState == EImpsPollCIR )
+ {
+ if ( iPollTime != iSettings.CIRModePollTime() )
+ {
+ iPollTime = iSettings.CIRModePollTime();
+ iIdleTimer->Start( iPollTime );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: PollTime reset %d" ), iPollTime );
+#endif
+ }
+ }
+ else if ( iPollTime > iSettings.iPollTime && iIdleTimer->IsActive() )
+ {
+ iPollTime = iSettings.iPollTime;
+ iIdleTimer->Start( iPollTime );
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: PollTime reset %d" ), iPollTime );
+#endif
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::IsLogged
+// -----------------------------------------------------------------------------
+//
+TBool CImpsCSPSession::IsLogged( )
+ {
+ return DoIsLogged();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::IsPendingLogin
+// -----------------------------------------------------------------------------
+//
+TBool CImpsCSPSession::IsPendingLogin()
+ {
+ return iCSPState == EImpsCSPLogging ? ETrue : EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::IsNegotiated
+// -----------------------------------------------------------------------------
+//
+TBool CImpsCSPSession::IsNegotiated( )
+ {
+ return DoIsNegotiated();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::Servicses
+// -----------------------------------------------------------------------------
+//
+TImpsServices* CImpsCSPSession::Services( )
+ {
+ return &iServices; //lint !e1536 this pointer must be used with care
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::IsShuttingDown
+// -----------------------------------------------------------------------------
+//
+TBool CImpsCSPSession::IsShuttingDown( )
+ {
+ return DoIsShuttingDown();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::IsLogging
+// -----------------------------------------------------------------------------
+//
+TBool CImpsCSPSession::IsLogging( )
+ {
+ return DoIsLogging();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::UserId
+// -----------------------------------------------------------------------------
+//
+TPtrC CImpsCSPSession::UserId( )
+ {
+ return DoUserId();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SAP
+// -----------------------------------------------------------------------------
+//
+TPtrC CImpsCSPSession::SAP( )
+ {
+ return DoSAP();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::SID
+// -----------------------------------------------------------------------------
+//
+TPtrC CImpsCSPSession::SID( )
+ {
+ return iCSPSessionId;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::Password
+// -----------------------------------------------------------------------------
+//
+TPtrC CImpsCSPSession::Password( )
+ {
+ return LogPwd();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::GiveNextRequestL
+// -----------------------------------------------------------------------------
+CReq* CImpsCSPSession::GiveNextRequestL()
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: GiveNextRequestL begins" ) );
+#endif
+ // If logginOff then this should be logout request
+ TDblQueIter<CReq> iter ( iRequestList );
+ iter.SetToFirst();
+
+ while ( iter )
+ {
+ CReq* request = iter;
+ // Get first and check if it is expired
+ iter++;
+
+ TTime myTime;
+ myTime.HomeTime();
+ if ( request->iExpiry < myTime )
+ {
+ // session is asked to discard request from its structures
+ // Check TID match
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Server: EXPIRED entry to be removed" ) );
+#endif
+ TImpsMessageType msgType = ( TImpsMessageType ) request->iFields->MessageType();
+ TImpsEventType myType = impsService( &iVariant, msgType );
+ // expired request is destroyed in client sessions too.
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ iServer.DiscardRequest( request->iFields->TidL(), myType, KErrTimedOut, csp );
+
+ // expired entry is deleted
+ request->Destroy();
+ TrMinus();
+
+ // We want to push new messages from queued
+ SendAllQueued();
+
+ } // expired
+ else
+ {
+ return request;
+ }
+ }
+
+ return ( CReq* )NULL;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::NewState
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::NewState( TImpsCSPState aNew )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: NewState old=%d new=%d csp=%d" ),
+ iCSPState, aNew, ( TInt )this );
+#endif
+ // In EImpsCSPDisconnecting iLogTid is still needed fore cancel-login
+ if ( iCSPState >= EImpsCSPLogging && aNew < EImpsCSPDisconnecting )
+ {
+ delete iLogTid;
+ iLogTid = NULL;
+ }
+ if ( aNew == EImpsCSPIdle )
+ {
+ iTr = 0;
+ iCookie = KNullDesC;
+ iCookie8 = KNullDesC8;
+ iCSPSessionId = KNullDesC;
+ iCSPSessionId8 = KNullDesC8;
+ iLoginPhase = 1;
+ }
+ else if ( aNew <= EImpsCSPOnLine )
+ {
+ // PDP is opened sucessfully or CSP login not done or logging out.
+ iPDPOpenTimer->Stop();
+ }
+ iCSPState = aNew;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::TrMinus
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::TrMinus()
+ {
+ if ( iTr > 0 )
+ {
+ iTr--;
+ }
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: iTr=%d csp=%d" ), iTr, ( TInt )this );
+#endif
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::ResetSession
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::ResetSession()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: ResetSession csp=%d" ), ( TInt )this );
+#endif
+ // This is not needed since CSP session entity is not re-cycled?
+ iSettings.iUDPWAPCIR = 1;
+ iSettings.iSMSWAPCIR = 1;
+ iSettings.iTCPSCIR = 1;
+ iSettings.iUDPSCIR = 1;
+ iSettings.iPollTime = KImpsPollTime;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::MaxParserSize
+// -----------------------------------------------------------------------------
+TInt CImpsCSPSession::MaxParserSize()
+ {
+ return iServer.Settings()->MaximumParserSize();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::MaxParserSize
+// -----------------------------------------------------------------------------
+TInt CImpsCSPSession::MaxMessageSize()
+ {
+ return iServer.Settings()->MaximumMessageSize();
+ }
+
+// -----------------------------------------------------------------------------
+// CTransaction::CTransaction
+// -----------------------------------------------------------------------------
+
+CTransaction::CTransaction(
+ TBool aOrphan,
+ const TDesC& aTID,
+ const TDesC& aSessionId,
+ TImpsMessageType aMessageType,
+ CImpsFields* aFields ) :
+ iMessageType( aMessageType ),
+ iFields ( aFields ),
+ iOrphan ( aOrphan )
+ {
+ iTID = aTID;
+ iSessionId = aSessionId;
+ }
+
+CTransaction::~CTransaction()
+ {
+
+ } //lint !e1540 iFields freed in Destroy
+
+void CTransaction::Destroy()
+ {
+ iLink.Deque();
+ delete iFields;
+ iFields = NULL;
+ delete this;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CReq::CReq
+// -----------------------------------------------------------------------------
+
+CReq::CReq( CImpsFields* aFields ) :
+ iFields( aFields )
+ {}
+
+CReq::~CReq()
+ {
+
+ } //lint !e1540 iFields freed in Destroy
+
+void CReq::Destroy()
+ {
+ delete iFields;
+ iFields = NULL;
+ iLink.Deque();
+ delete this;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::IsLogoutResp()
+// aFields must not be NULL
+// -----------------------------------------------------------------------------
+TImpsLogoutTrans CImpsCSPSession::IsLogoutResp( CImpsFields* aFields )
+ {
+ TImpsLogoutTrans ret = EImpsLogoutNone;
+
+ // set pointers to received TID and to current pending Logout-request TID
+ TPtrC recId;
+ TPtrC logoutTid;
+ logoutTid.Set( LogoutTID() );
+ TRAPD( errxy, recId.Set( aFields->TidL() ) );
+ if ( errxy )
+ {
+ return ret;
+ }
+
+ // Check if current logout transaction TID matches with received message.
+ if ( iCSPState == EImpsCSPDisconnecting &&
+ !logoutTid.Length() || ( logoutTid.Length() && !recId.Compare( logoutTid ) ) ) // NOTE
+ {
+ if ( aFields->MessageType() == EImpsDisconnect )
+ {
+ // WV 1.1 logout response
+ ret = EImpsLogoutTerminal;
+ }
+ else if ( aFields->MessageType() == EImpsStatus )
+ {
+ // WV 1.2 logout response
+ ret = EImpsLogoutTerminal;
+ }
+ }
+ else if ( aFields->MessageType() == EImpsDisconnect )
+ {
+ // SAP initiated CSP disconnect
+ ret = EImpsLogoutSAP;
+ }
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: IsLogoutResp returns %d csp=%d" ),
+ ret, ( TInt )this );
+#endif
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::StartLoginCancel()
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::StartLoginCancel( )
+ {
+ // Cancel login transaction, either login+logout or login+cancelLogin.
+ // DoPendingLogout() is called later to complete the client requests.
+ if ( iReceiver2->CancelLoginTrans( LogTid() ) )
+ {
+ // Generate CSP Logout transaction
+ // Clear buffers from old stuff
+ DeleteRequests();
+ DeleteTransactions();
+ // Send Logout primitive and set state to EImpsCSPDisconnecting.
+ TRAPD( errx, DoSendLogoutL( LogoutTID() ) );
+ if ( errx )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoSendLogoutL 2 error %d ***" ), errx );
+#endif
+ }
+ else
+ {
+ // If CSP Logout transaction is sent then we wait TransportResponseL or
+ // TransportErrorL callback methods to be called later.
+ return;
+ }
+ }
+ // Start to send events to clients if CSP Disconnect transaction is not sent.
+ DoPendingLogout();
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsCSPSession::DoPendingLogout()
+// -----------------------------------------------------------------------------
+void CImpsCSPSession::DoPendingLogout( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "CSPSession: DoPendingLogout ***" ) );
+#endif
+ // Send critical response events to client sessions and start to logout
+ // internally this CSP session entity.
+ TImpsSessIdent csp( iCSPSessionId, DoSAP(), DoUserId() );
+ if ( iPendingLogout )
+ {
+ // Send login response for pending request first
+ iServer.DiscardRequest( LogTid(), EImpsEventServerLogin, KErrCancel, csp );
+ // Send logout response, that is always successful
+ iServer.DiscardLogout( LogoutTID(), csp );
+ }
+
+ if ( iCancelLogin )
+ {
+ // Send cancel-login response to client
+ iServer.DiscardRequest( LogTid(), EImpsEventServerLogin, KErrNone, csp );
+ }
+
+ iPendingLogout = EFalse;
+ iCancelLogin = EFalse;
+ DoLogout();
+ }
+
+// End of File