--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IMPSengine/engsrv/src/impssession.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,1349 @@
+/*
+* Copyright (c) 2002-2005 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: Class for Imps session.
+*
+*
+*/
+
+
+// INCLUDE FILES
+#include "impsserver.h"
+#include "impsutils.h"
+#include "impssession.h"
+#include "impsfields.h"
+#include "impserrors.h"
+#include "impstimer.h"
+#include "impssubsession.h"
+#include "ImpsVariantAPI.h"
+#include "impspacked.h"
+
+// MACROS
+#ifndef _DEBUG
+#define _NO_IMPS_LOGGING_
+#endif
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+CImpsSession::CImpsSession( RMessage2& aMsg )
+ : CSession2(),
+ iCanceled( EFalse ),
+ iMessageCompleted( EFalse ),
+ iMsgR( aMsg )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: NEW session sess=%d" ), ( TInt )this );
+#endif
+ }
+
+
+// Destructor
+// RHandleBase::Close() causes this destructor to be called
+CImpsSession::~CImpsSession()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: DELETE session sess=%d" ), ( TInt )this );
+#endif
+ // Check if destructor is called by CServer2 class in failed
+ // entity creation or in other case. iContainer is the last
+ // member created is CreateL() so it can be used for this purpose.
+ TBool wasComplete = iContainer ? ETrue : EFalse;
+ // This is here to close CSP session if client is deleted
+ // without calling close method.
+ CloseSession();
+ TImpsSessIdent csp( SID(), SAP(), UserId() );
+ Server()->CloseSession( csp, wasComplete );
+ delete iApplicationId;
+ delete iSID;
+ delete iSAP;
+ delete iUserId;
+ delete iStream;
+ delete iFields;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::CreateL()
+// ---------------------------------------------------------
+// This overloads the base class implementation
+void CImpsSession::CreateL( )
+ {
+ iFields = CImpsFields::NewL();
+ // create new object index
+ iSubSessions = CObjectIx::NewL();
+ // initialize the object container using the object container index in the server.
+ iContainer = Server()->NewContainerL();
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::DispatchMessageL()
+// ---------------------------------------------------------
+void CImpsSession::DispatchMessageL( const RMessage2& aMessage )
+ {
+ TInt nbrSess = 0;
+ TUint flag = 0;
+
+ iMsgR = aMessage;
+
+ if ( iCanceled )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: already CANCELED aMsg=%d" ),
+ aMessage.Function() );
+#endif
+ CompleteMe( KErrCancel );
+ return;
+ }
+
+ // Set ETrue at the same time as Message().Complete() takes place
+ iMessageCompleted = EFalse;
+ TInt msg = aMessage.Function();
+ // stripp off bit mask in an upper word
+ msg = msg & 0x0FFFF;
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: DispatchMessageL msg=%d sess=%d" ), msg, ( TInt )this );
+#endif
+
+ // current CSP indetification
+ TImpsSessIdent csp( SID(), SAP(), UserId() );
+
+ switch ( msg )
+ {
+ case EImpsServAssign:
+ AssignIdL();
+ // Notice that in this case there is subsession specific part too.
+ // So, do not return yet.
+ break;
+
+ case EImpsAccessRegister2:
+ // NewSubSessionL will check SHUTTING_DOWN state of server and
+ // leaves when necessary
+ NewSubSessionL( EImpsEventServerLogin, aMessage );
+ return;
+
+ case EImpsImRegister:
+ NewSubSessionL( EImpsEventMessage, aMessage );
+ return;
+
+ case EImpsFundRegister:
+ NewSubSessionL( EImpsEventCommon, aMessage );
+ return;
+
+ case EImpsGroupRegister:
+ NewSubSessionL( EImpsEventGroup, aMessage );
+ return;
+
+ case EImpsServPureRegister:
+ {
+ NewSubSessionL( EImpsEventPresencePure, aMessage );
+ }
+ return;
+
+ case EImpsServIsLogged:
+ // This has to return positive value is CSP is found
+ // and it has got SID.
+ if ( IsThisLogged() )
+ {
+ CompleteMe( KErrNone );
+ }
+ else
+ {
+ CompleteMe( KImpsErrorNotLogged );
+ }
+ return;
+
+ case EImpsServNbrSessions:
+ nbrSess = NbrOfSessionsL( );
+ CompleteMe( nbrSess );
+ return;
+
+ case EImpsServServices:
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: EImpsServServices" ) );
+#endif
+ CurrentServicesL();
+ return;
+
+ case EImpsServPush:
+ // multi-csp supported, i.e. CIR given for every CSP session
+ // until sessoin cookie matches
+ if ( Server()->IsShuttingDown() )
+ {
+ User::Leave( KImpsErrorShuttingDown );
+ }
+ PushMessageL();
+ iCIRSess = ETrue;
+ return;
+
+ case EImpsServBuffSizeReq:
+ CompleteMe( IsThisLogged() ? Server()->BufferSize() : 0 );
+ return;
+
+ case EImpsServCloseAll: // close all sessions
+ Server()->LogoutAll();
+ CompleteMe( KErrNone );
+ return;
+ }
+
+ // subsession specific requests
+ TInt myHandle = aMessage.Int3( );
+ CImpsSubSession* sub = ConnectionFromHandle( myHandle );
+ if ( !sub )
+ {
+ PanicClient( EImpsBadRequest );
+ return;
+ }
+
+ TBool reactive( EFalse );
+
+ switch ( msg )
+ {
+
+ case EImpsServAssign:
+ sub->AssignIdL( csp );
+ return;
+
+ // completion of request made in ServiceL
+ case EImpsServReactiveLogin:
+ reactive = ETrue;
+ case EImpsServWVLogin:
+ if ( Server()->IsShuttingDown() )
+ {
+ User::Leave( KImpsErrorShuttingDown );
+ }
+ if ( !Server()->IsConAllowed() )
+ {
+ User::Leave( KImpsErrorTerminalOffLine );
+ }
+ // multi: check if this session is already logged in.
+ if ( IsThisLogged() )
+ {
+ User::Leave( KImpsErrorAlreadyLogged );
+ }
+ iLogoutTID = KNullDesC;
+ sub->LoginL( reactive );
+ return;
+
+ // case EImpsServWVLogoutOne:
+ case EImpsServWVLogout:
+ if ( Server()->IsShuttingDown() )
+ {
+ User::Leave( KImpsErrorShuttingDown );
+ }
+ if ( !IsThisActive() )
+ {
+ User::Leave( KImpsErrorNotLogged );
+ }
+ iLogoutTID = KNullDesC;
+ iLogoutTID = sub->LogoutL( csp, EFalse );
+ // The following is needed if no force logout
+ // and a shared CSP exists.
+ CompleteMe( KErrNone );
+ return;
+
+ case EImpsServWVSendOnly:
+ case EImpsServBlock:
+ case EImpsServGroup:
+ case EImpsServPres:
+ case EImpsServFundSearch:
+ case EImpsServFundInvite:
+ if ( Server()->IsShuttingDown() )
+ {
+ User::Leave( KImpsErrorShuttingDown );
+ }
+ // multi: check if this handle is logged
+ if ( !IsThisLogged() )
+ {
+ User::Leave( KImpsErrorNotLogged );
+ }
+ else if ( !Server()->IsConAllowed() )
+ {
+ User::Leave( KImpsErrorTerminalOffLine );
+ }
+ sub->SendPrimitiveL( aMessage.Function(), csp );
+ return;
+
+ case EImpsServNextEvent:
+ sub->NextEventL( aMessage );
+ // This is completed later
+ iMessageCompleted = ETrue;
+ return;
+
+ case EImpsServEventBody:
+ sub->SendEventBodyL( aMessage );
+ // This is completed later
+ iMessageCompleted = ETrue;
+ return;
+
+ case EImpsServCloseSub:
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: EImpsServCloseSub" ) );
+#endif
+ sub->Unregister();
+ // remove subsession type
+ flag = sub->Type();
+ iTypes = ( iTypes & ~flag );
+ CompleteMe( KErrNone );
+ return;
+
+ case EImpsServDeleteSub:
+ // remove subsession entity
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: EImpsServDeleteSub" ) );
+#endif
+ sub->DeleteSub();
+ CompleteMe( KErrNone );
+ return;
+
+ case EImpsServGetBlocked:
+ if ( Server()->IsShuttingDown() )
+ {
+ User::Leave( KImpsErrorShuttingDown );
+ }
+ // multi: check if this handle is logged in
+ if ( !IsThisLogged() )
+ {
+ User::Leave( KImpsErrorNotLogged );
+ }
+ else if ( !Server()->IsConAllowed() )
+ {
+ User::Leave( KImpsErrorTerminalOffLine );
+ }
+ sub->SendGetBlockedL( csp );
+ return;
+
+ case EImpsServStatusReg:
+ sub->SetStatusObserver( ETrue );
+ CompleteMe( KErrNone );
+ return;
+
+ case EImpsServStatusUnreg:
+ sub->SetStatusObserver( EFalse );
+ CompleteMe( KErrNone );
+ return;
+
+ case EImpsServDetailedReg:
+ sub->SetDetailedError( ETrue );
+ CompleteMe( KErrNone );
+ return;
+
+ case EImpsServDetailedUnreg:
+ sub->SetDetailedError( EFalse );
+ CompleteMe( KErrNone );
+ return;
+
+ case EImpsServCspVersion:
+ CompleteMe( Server()->CspVersion() );
+ return;
+
+ case EImpsServCancelLogin: // cancel ongoing login
+ if ( Server()->IsShuttingDown() )
+ {
+ User::Leave( KImpsErrorShuttingDown );
+ }
+ // Call logout with cancel parameter.
+ ( void )sub->LogoutL( csp, ETrue );
+ return;
+
+ case EImpsServCancelTrans: // cancel transaction
+ // If the specified request is not found then just complete the current request.
+ if ( !sub->CancelTrans( aMessage, csp ) )
+ {
+ CompleteMe( KErrNone );
+ }
+ else
+ {
+ // Complete with cancel if operation is cancelled
+ CompleteMe( KErrCancel );
+ }
+ return;
+
+ case EImpsServSetExpiry:
+ sub->SetExpiryTime( aMessage );
+ CompleteMe( KErrNone );
+ return;
+
+ default:
+ PanicClient( EImpsBadRequest );
+ return;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CImpsSession::NewSubSessionL
+// ---------------------------------------------------------
+// Create a new connection; pass back its handle via the message
+// Ensures the object is cleaned up on failure
+void CImpsSession::NewSubSessionL(
+ TImpsEventType aType,
+ const RMessage2& aMessage )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: NewSubSessionL sess=%d" ), TInt( this ) );
+#endif
+ // Reject request if server is SHUTTING_DOWN
+ if ( Server()->IsShuttingDown() )
+ {
+ User::Leave( KImpsErrorShuttingDown );
+ }
+ CImpsSubSession* sub = CImpsSubSession::NewL( this, aType, aMessage );
+ CleanupClosePushL( *sub );
+ iContainer->AddL( sub );
+ // Add subsession to object index, this returns unique handle
+ TInt handle = iSubSessions->AddL( sub );
+ // write the handle to client
+ TPckg<TInt> handlePckg( handle );
+ TRAPD( res, aMessage.WriteL( 3, handlePckg ) );
+ if ( res != KErrNone )
+ {
+ // Removing sub from object index will
+ // cause Close() to be called on sub, and that calls destructor
+ CleanupStack::Pop();
+ iSubSessions->Remove( handle );
+ PanicClient( EImpsCorrupted );
+ User::Leave( res );
+ }
+ sub->SetHandle( handle );
+ // notch up another resource
+ iResourceCount++;
+ // update iTypes bit Mask
+ iTypes = iTypes | aType;
+ CleanupStack::Pop( );
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::ConnectionFromHandle()
+// ---------------------------------------------------------
+CImpsSubSession* CImpsSession::ConnectionFromHandle( TUint aHandle )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )iSubSessions->At( aHandle );
+ return sub;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::DeleteSubSession
+// ---------------------------------------------------------
+void CImpsSession::DeleteSubSession( TUint aHandle )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: DeleteSubSession sess=%d" ), ( TInt )this );
+#endif
+ // panic if bad handle
+ CImpsSubSession* sub = ConnectionFromHandle( aHandle );
+ if ( sub == NULL )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: PANIC" ) );
+#endif
+ PanicClient( EImpsCorrupted );
+ }
+
+ // remove subsession
+ iSubSessions->Remove( aHandle );
+ // decrement resource count
+ iResourceCount--;
+
+#ifndef _NO_IMPS_LOGGING_
+ TInt count = iSubSessions->ActiveCount();
+ CImpsClientLogger::Log( _L( "Session: DeleteSubSession nbrsub=%d %d subses=%d" ),
+ count, iResourceCount, ( TInt )sub );
+#endif
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::MatchSession
+// ---------------------------------------------------------
+TBool CImpsSession::MatchSession( TImpsSessIdent aCSP )
+ {
+ // -----------------------------------
+ // Notice: comment
+ // extra stuff for debugging
+ /*
+ TPtrC pp1 = aCSP.SAP();
+ TPtrC pp2 = aCSP.UserId();
+ TPtrC pp3 = aCSP.SID();
+ TPtrC ppa = SAP();
+ TPtrC ppb = UserId();
+ TPtrC ppc = SID();
+ CImpsClientLogger::Log(_L("Session: MatchSession aCSP sap=%S user=%S sid=%S"), &pp1, &pp2, &pp3);
+ CImpsClientLogger::Log(_L("Session: MatchSession this sap=%S user=%S sid=%S"), &ppa, &ppb, &ppc);
+ */
+ // -----------------------------------
+
+ // The current session-id must match if it is non-zero
+ if ( aCSP.SID().Length() > 0 &&
+ SID().Length() > 0 &&
+ aCSP.SID().CompareF( SID() ) )
+ {
+ return EFalse;
+ }
+ // Also user-id and SAP address must match
+ else if ( !( SAP().CompareF( aCSP.SAP() ) ) &&
+ !( UserId().CompareF( aCSP.UserId() ) ) )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ TPtrC p1 = SAP();
+ TPtrC p2 = UserId();
+ TPtrC p3 = aCSP.SID();
+ CImpsClientLogger::Log( _L( "Session: MatchSession MATCH sess=%d sap=%S user=%S sid=%S" ),
+ ( TInt )this, &p1, &p2, &p3 );
+#endif
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CImpsSession::SendEvent()
+// ---------------------------------------------------------
+void CImpsSession::SendEvent(
+ CImpsFields *aFields,
+ TInt aOpId,
+ TImpsServRequest aRequestType,
+ TImpsMessageType aReqMsgType,
+ TUint aHandle )
+ {
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ if ( iCanceled )
+ {
+ return;
+ }
+
+ TInt errx = KErrNone;
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: SendEvent begins" ) );
+#endif
+
+ // specified subsession
+ if ( aHandle )
+ {
+ CImpsSubSession* sub = ConnectionFromHandle( aHandle );
+ if ( sub )
+ {
+ sub->SendEvent(
+ aFields,
+ aOpId,
+ aRequestType,
+ aReqMsgType );
+ }
+ }
+ // scan subsessions
+ else
+ {
+ // This is safe even if client would close session or subsession
+ // Scheduler does not allocate time for it until this loop ends.
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ TRAP( errx, sub->SendEvent(
+ aFields,
+ aOpId,
+ aRequestType,
+ aReqMsgType ) );
+ }
+ }
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: SendEvent ends" ) );
+#endif
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::SendEvent()
+// Lighter version for engine status event
+// ---------------------------------------------------------
+void CImpsSession::SendEvent(
+ EImpsInternalStatus aStatus )
+ {
+
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ if ( iCanceled )
+ {
+ return;
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: SendEvent begins aStatus=%d" ), aStatus );
+#endif
+
+ if ( aStatus == EInternal_NOT_LOGGED || aStatus == EInternal_SHUTTING_DOWN )
+ {
+ // NOT_LOGGED event is sent after LogoutResponse and it cleans
+ // the WV CSP TID, so that it will not receive any further
+ // messages from transport.
+ CleanSID();
+ SetThisInactive();
+ }
+
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ sub->SendEvent( aStatus );
+ }
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: SendEvent ends" ) );
+#endif
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::SendLogoutEvent
+// ---------------------------------------------------------
+void CImpsSession::SendLogoutEvent(
+ TInt aRespStatus, TInt aOpId, CImpsSubSession* aSub,
+ TUint aHandle )
+ {
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ if ( iCanceled )
+ {
+ return;
+ }
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: SendLogoutEventL" ) );
+#endif
+
+ // specified subsession only
+ if ( aHandle )
+ {
+ CImpsSubSession* sub = ConnectionFromHandle( aHandle );
+ if ( sub )
+ {
+ sub->SendLogoutEvent( aRespStatus, aOpId );
+ return;
+ }
+ }
+
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ // Igone a specific subsession
+ if ( sub && sub != aSub )
+ {
+ sub->SendLogoutEvent( aRespStatus, aOpId );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::CheckNotification()
+// ---------------------------------------------------------
+TBool CImpsSession::CheckNotifications(
+ CImpsFields* aFields, TImpsSessIdent aCSP )
+ {
+ TBool retVal( EFalse );
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ // Multi: Validate the CSP connection id and check that
+ // client has not completed logout request.
+ if ( iCanceled || !MatchSession( aCSP ) || !IsThisActive() )
+ {
+ return retVal;
+ }
+
+ TInt myType = 0;
+ TInt myOpId = 0;
+ // Notice: client thread use this information
+ if ( aFields->MessageType() == EImpsDisconnect )
+ {
+ myType = EImpsServWVLogout;
+ }
+
+
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub && sub->CheckNotification( aFields ) )
+ {
+ retVal = ETrue;
+ sub->SendEvent(
+ aFields, myOpId, ( TImpsServRequest )myType, EImpsMessageNone );
+ }
+ }
+ return retVal;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::HandleAllOrphans()
+// ---------------------------------------------------------
+void CImpsSession::HandleAllOrphans()
+ {
+ // current CSP indetification
+ TImpsSessIdent csp( SID(), SAP(), UserId() );
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ sub->HandleAllOrphans( csp );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsSession::CloseSession()
+// -----------------------------------------------------------------------------
+void CImpsSession::CloseSession()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: CloseSession" ) );
+#endif
+
+ iCanceled = ETrue;
+ DeleteAllRequests();
+ void DeleteAllEvents();
+ // Delete the object index (this stores the objects for this session)
+ delete iSubSessions;
+ iSubSessions = NULL;
+ Server()->RemoveContainer( iContainer );
+ iContainer = NULL;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::CheckRequests()
+// ---------------------------------------------------------
+TUint CImpsSession::CheckRequests(
+ const TDesC& aTid,
+ TInt& aOpId,
+ TImpsServRequest& aRequestType,
+ TImpsMessageType& aReqMsgType,
+ TImpsSessIdent aCSP )
+ {
+
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ if ( iCanceled )
+ {
+ return 0;
+ }
+
+ // Check also that the CSP session matches
+ if ( !MatchSession( aCSP ) )
+ {
+ return 0;
+ }
+
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub && sub->CheckRequests(
+ aTid,
+ aOpId,
+ aRequestType,
+ aReqMsgType ) )
+ {
+ // Check if a successful response for login
+ if ( SID().Length() == 0 &&
+ aCSP.SID().Length() > 0 &&
+ aRequestType == EImpsServWVLogin )
+ {
+ // If OOM here then this returns 0 and expiry routines
+ // handles the request later on. This is extremely
+ // rare situation anyway.
+ TRAPD( errx, ModifySIDL( aCSP.SID() ) );
+ if ( errx )
+ {
+ return 0;
+ }
+ }
+ return sub->Handle();
+ }
+ }
+
+ return 0;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::DiscardRequests()
+// ---------------------------------------------------------
+void CImpsSession::DiscardRequests(
+ TTime aExpiryTime,
+ TImpsEventType aServiceType,
+ TImpsSessIdent aCSP,
+ MImpsCSPSession* aSess )
+ {
+
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ // Multi: Validate the CSP connection too.
+ if ( iCanceled || !MatchSession( aCSP ) )
+ {
+ return;
+ }
+
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ sub->DiscardRequests( aExpiryTime, aServiceType, aSess );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::DiscardRequests()
+// ---------------------------------------------------------
+void CImpsSession::DiscardRequests(
+ TInt aError,
+ TImpsEventType aServiceType,
+ TImpsSessIdent aCSP,
+ MImpsCSPSession* aSess )
+ {
+
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ // Multi: Validate the CSP connection too.
+ if ( iCanceled || !MatchSession( aCSP ) )
+ {
+ return;
+ }
+
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ sub->DiscardRequests( aError, aServiceType, aSess );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::DiscardRequest()
+// ---------------------------------------------------------
+TBool CImpsSession::DiscardRequest(
+ const TDesC& aTid,
+ TImpsEventType aServiceType,
+ TInt aCode,
+ TImpsSessIdent aCSP )
+ {
+
+ TBool ret( EFalse );
+
+ // It is possible that the cancel request from client is not
+ // complete and this session entity is still waiting deletion.
+ // Multi: Validate the CSP connection too.
+ if ( iCanceled || !MatchSession( aCSP ) )
+ {
+ return EFalse;
+ }
+
+ // Scan subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ ret = sub->DiscardRequest( aTid, aServiceType, aCode );
+ if ( ret )
+ {
+ return ETrue;
+ }
+ }
+ }
+
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsSession::DeleteAllRequests()
+// -----------------------------------------------------------------------------
+void CImpsSession::DeleteAllRequests( )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: DeleteAllRequests" ) );
+#endif
+ if ( iCanceled )
+ {
+ return;
+ }
+
+ // Delete all buffered requests from this client.
+ // Delete from subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ sub->DeleteAllRequests();
+ }
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsSession::DeleteAllRequests()
+// -----------------------------------------------------------------------------
+void CImpsSession::DeleteAllRequests( TImpsSessIdent* aCSP )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: DeleteAllRequests aCSP" ) );
+#endif
+ if ( iCanceled )
+ {
+ return;
+ }
+
+ if ( !MatchSession( *aCSP ) )
+ {
+ return;
+ }
+
+ // Delete all buffered requests from this client.
+ // Delete from subsessions
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ sub->DeleteAllRequests();
+ }
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsSession::DeleteRequest
+// -----------------------------------------------------------------------------
+void CImpsSession::DeleteRequest( TInt aOpId, TUint aSubHandle )
+ {
+
+ if ( aSubHandle )
+ {
+ CImpsSubSession* sub = ConnectionFromHandle( aSubHandle );
+ if ( sub )
+ {
+ sub->DeleteRequest( aOpId );
+ }
+ return;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CImpsSession::ExpiryTime
+// -----------------------------------------------------------------------------
+TInt CImpsSession::ExpiryTime( )
+ {
+ if ( iCanceled )
+ {
+ return 0;
+ }
+
+ // Search the minimum subsession expiry time.
+ TInt sesexp = 0;
+ TInt exp = 0;
+ TInt count = iSubSessions->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ CImpsSubSession* sub = ( CImpsSubSession* )( ( *iSubSessions )[i] );
+ if ( sub )
+ {
+ exp = sub->ExpiryTime();
+ if ( ( exp && exp < sesexp ) || !sesexp )
+ {
+ sesexp = exp;
+ }
+ }
+ }
+ return sesexp;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::CompleteMe()
+// ---------------------------------------------------------
+void CImpsSession::CompleteMe( TInt aStatus )
+ {
+ iMsgR.Complete( aStatus );
+ iMessageCompleted = ETrue;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::PushMessageL()
+// ---------------------------------------------------------
+void CImpsSession::PushMessageL()
+ {
+ // read cookie
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: PushMessageL" ) );
+#endif
+ if ( !iStream )
+ {
+ iStream = HBufC8::NewL( KImpsMaxCookie );
+ }
+
+ // server instance saves these after successful login
+ ( void ) ReadBuffer8L( 1, iStream );
+ Server()->CirMessageL( iStream->Des() );
+ }
+
+
+// ---------------------------------------------------------
+// CImpsSession::ServiceL()
+// ---------------------------------------------------------
+
+void CImpsSession::ServiceL( const RMessage2& aMessage )
+ {
+ TRAPD( err, DispatchMessageL( aMessage ) );
+ if ( !iMessageCompleted )
+ {
+ CompleteMe( err );
+ }
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::PanicClient()
+// ---------------------------------------------------------
+void CImpsSession::PanicClient( TImpsPanic aPanic ) const
+ {
+ iMsgR.Panic( KImpsPanicCategory, aPanic );
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::CurrentServicesL()
+// ---------------------------------------------------------
+void CImpsSession::CurrentServicesL()
+ {
+
+ TImpsSessIdent csp( SID(), SAP(), UserId() );
+ if ( !Server()->IsNegotiated( csp ) )
+ {
+ User::Leave( KImpsErrorServices );
+ }
+
+ // Buffer for response
+ TBuf < sizeof( TImpsServices ) + 4 >
+ myBuf( sizeof( TImpsServices ) + 4 );
+ TImpsServices myServices;
+ myServices.Reset();
+
+ TImpsServices* activeServices = Server()->Services( csp );
+ if ( !activeServices )
+ {
+ User::Leave( KImpsErrorServices );
+ }
+ myServices.Copy( *activeServices );
+
+ // Copy service tree to the local descriptor buffer
+ const TUint8* aPtrStart = ( const TUint8* )myBuf.Ptr();
+ TInt32 tempSize = 0;
+ tempSize = sizeof( TImpsServices );
+ Mem::Copy( ( void* )aPtrStart, &tempSize, sizeof( tempSize ) );
+ aPtrStart = aPtrStart + sizeof( tempSize );
+ if ( tempSize )
+ {
+ Mem::Copy( ( void* )aPtrStart, ( void* )&myServices, tempSize );
+ }
+ TInt ret = iMsgR.Write( 0, myBuf );
+ // complete the request
+ CompleteMe( ret );
+
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::ReadBuffer8L()
+// aBuffer must be a member if there is a risk that
+// more memory must be allocated, because of cleanupstack is
+// inconsistent otherwise.
+// ---------------------------------------------------------
+TBool CImpsSession::ReadBuffer8L(
+ TInt aIndex,
+ HBufC8*& aBuffer )
+//
+// Copies a buffer from the client
+// Only fails if there is not enough memory to increase the buffer size
+//
+ {
+ TBool alloced = EFalse;
+ TInt desLen = iMsgR.GetDesLength( aIndex );
+
+ if ( desLen < 0 )
+ {
+ User::Leave( desLen );
+ }
+
+ HBufC8* newBuffer = NULL;
+
+ if ( aBuffer == NULL )
+ {
+ newBuffer = HBufC8::NewLC( desLen );
+ alloced = ETrue;
+ }
+ else if ( desLen > aBuffer->Des().MaxLength() )
+ {
+ alloced = ETrue;
+ // we have to increase the size of buffer
+ aBuffer->Des().SetLength( 0 ); // to avoid copying the contents
+ newBuffer = aBuffer->ReAllocL( desLen );
+ CleanupStack::PushL( newBuffer );
+ }
+
+ TPtr8 desPtr = alloced ? newBuffer->Des() : aBuffer->Des(); //lint !e613 !e661
+ // newBuffer is allocated, aBuffer must not be zero
+ iMsgR.ReadL( aIndex, desPtr );
+
+ if ( alloced )
+ {
+ aBuffer = newBuffer;
+ CleanupStack::Pop();
+ }
+
+ return alloced;
+
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::ApplicationId()
+// ---------------------------------------------------------
+TPtrC CImpsSession::ApplicationId()
+ {
+ return iApplicationId ? TPtrC( *iApplicationId ) : TPtrC();
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::SetUserIdL()
+// ---------------------------------------------------------
+void CImpsSession::SetUserIdL( const TDesC& aId )
+ {
+ delete iUserId;
+ iUserId = NULL;
+ iUserId = aId.AllocL();
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::SetSAPL()
+// ---------------------------------------------------------
+void CImpsSession::SetSAPL( const TDesC& aId )
+ {
+ delete iSAP;
+ iSAP = NULL;
+ iSAP = aId.AllocL();
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::SetThisInactive()
+// Use iUserId to check whether client session is logged in
+// ---------------------------------------------------------
+void CImpsSession::SetThisInactive()
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: SetThisInactive sess=%d" ), ( TInt )this );
+#endif
+ delete iUserId;
+ iUserId = NULL;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::NewFieldsL()
+// Old iFields must not be deleted because of CImpsServer
+// still uses that.
+// ---------------------------------------------------------
+void CImpsSession::NewFieldsL()
+ {
+ CImpsFields* newF = CImpsFields::NewL();
+ iFields = newF;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::AssignIdL()
+// ---------------------------------------------------------
+void CImpsSession::AssignIdL()
+ {
+
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: AssignIdL begins" ) );
+#endif
+ // Generate session's application id and client id
+ RMessage2 myMsg( iMsgR );
+ // verify that length is valid
+ TInt desLen = myMsg.GetDesLength( 0 );
+ if ( desLen > KImpsMaxClientId )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ CImpsClientLogger::Log( _L( "Session: Error: too long client-id" ) );
+#endif
+ User::Leave( KImpsErrorValidate );
+ }
+ // allocate memory dynamically
+ delete iApplicationId;
+ iApplicationId = NULL;
+ iApplicationId = HBufC::NewL( desLen );
+ TPtr desPtr = iApplicationId->Des();
+ myMsg.ReadL( 0, desPtr );
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::CleanSID()
+// ---------------------------------------------------------
+void CImpsSession::CleanSID()
+ {
+ if ( !iSID )
+ {
+ return;
+ }
+#ifndef _NO_IMPS_LOGGING_
+ TPtr p = iSID->Des();
+ CImpsClientLogger::Log( _L( "Session: CleanSID sess=%d sid=%S" ), ( TInt )this, &p );
+#endif
+ delete iSID;
+ iSID = NULL;
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::ModifySIDL()
+// ---------------------------------------------------------
+void CImpsSession::ModifySIDL( const TDesC& aSID )
+ {
+#ifndef _NO_IMPS_LOGGING_
+ TPtrC p = aSID;
+ CImpsClientLogger::Log( _L( "Session: ModifySIDL sess=%d sid=%S" ), ( TInt )this, &p );
+#endif
+ delete iSID;
+ iSID = NULL;
+ iSID = aSID.AllocL();
+ }
+
+// ---------------------------------------------------------
+// CImpsSession::NbrSessionsL( )
+// ---------------------------------------------------------
+TInt CImpsSession::NbrOfSessionsL()
+ {
+ RMessage2 myMsg( Message() );
+
+ // Read PACKED ARRAY
+ CDesCArrayFlat* tempArr = new ( ELeave )CDesCArrayFlat( 2 );
+ CleanupStack::PushL( tempArr ); // << tempArr
+
+ HBufC8* stream = *StreamBufAddr();
+ if ( ReadBuffer8L( 0, stream ) )
+ {
+ HBufC8** stream2 = StreamBufAddr();
+ *stream2 = stream;
+ }
+ TImpsPackedEntity packedMessage( stream );
+ const TUint8* pS = stream->Ptr();
+ packedMessage.DoUnpackArrayL( pS, tempArr );
+
+ __ASSERT_DEBUG(
+ tempArr->MdcaCount() == 2,
+ User::Panic( KImpsPanicCategory,
+ EImpsCorrupted ) );
+
+ TPtrC tempUser = tempArr->MdcaPoint( 1 );
+ TPtrC tempSAP = tempArr->MdcaPoint( 0 );
+ TImpsSessIdent csp( KNullDesC, tempSAP, tempUser );
+
+ // ask number of clint sessions
+ TInt ret = Server()->NbrSessions( EFalse, csp );
+
+ tempArr->Reset();
+ CleanupStack::PopAndDestroy( 1 ); // >> tempArr
+
+ return ret;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CWvEvent::CWvEvent
+// -----------------------------------------------------------------------------
+
+CWvEvent::CWvEvent( TImpsEventType aType ) :
+ iType( aType ),
+ iMessageType( EImpsStatus ), // just default
+ iSent( EFalse ),
+ iPackedMessage ( NULL )
+ {}
+
+CWvEvent::~CWvEvent()
+ {
+ if ( iPackedMessage )
+ {
+ delete iPackedMessage;
+ }
+ iPackedMessage = NULL;
+ }
+
+void CWvEvent::Destroy()
+ {
+ iLink.Deque();
+ delete this;
+ }
+
+// -----------------------------------------------------------------------------
+// CRequest::CRequest
+// -----------------------------------------------------------------------------
+CRequest::CRequest(
+ const TDesC& aTID,
+ TInt aOpId,
+ TImpsServRequest aRequestType,
+ TTime aExpiry,
+ TImpsMessageType aMessageType )
+ : iOpId( aOpId ),
+ iRequestType ( aRequestType ),
+ iMessageType ( aMessageType ),
+ iExpiry( aExpiry )
+ {
+ iTID = aTID;
+ }
+
+CRequest::~CRequest()
+ {
+
+ }
+
+void CRequest::Destroy()
+ {
+ iLink.Deque();
+ delete this;
+ }
+
+// End of File