IMPSengine/engsrv/src/impssubsession.cpp
changeset 0 094583676ce7
equal deleted inserted replaced
-1:000000000000 0:094583676ce7
       
     1 /*
       
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Class for imps sub session.
       
    15 *
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include    "impsserver.h"
       
    22 #include    "impsutils.h"
       
    23 #include    "impssession.h"
       
    24 #include    "impsfields.h"
       
    25 #include    "impserrors.h"
       
    26 #include    "impstimer.h"
       
    27 #include    "impssdatautils.h"
       
    28 #include    "impspacked.h"
       
    29 #include    "impssubsession.h"
       
    30 #include    "impstdataaccessor.h"
       
    31 #include    "impsmessageinterpreterapi.h"
       
    32 #include    "impsliterals.h"
       
    33 #include    "ImpsVariantAPI.h"
       
    34 
       
    35 #ifdef _FAKE_RESPONSE
       
    36 #include   "impssrvtestutils.h"
       
    37 #endif
       
    38 
       
    39 // MACROS
       
    40 #ifndef _DEBUG
       
    41 #define _NO_IMPS_LOGGING_
       
    42 #endif
       
    43 
       
    44 
       
    45 
       
    46 
       
    47 // ================= MEMBER FUNCTIONS =======================
       
    48 
       
    49 // C++ default constructor can NOT contain any code, that
       
    50 // might leave.
       
    51 //
       
    52 CImpsSubSession::CImpsSubSession(  )
       
    53         :   iEventList( _FOFF( CWvEvent, iLink ) ),  //lint !e413
       
    54         iRequestList( _FOFF( CRequest, iLink ) ), //lint !e413
       
    55         iStatusObserver( EFalse ),
       
    56         iDetailedError( EFalse ),
       
    57         iLastEvent( EImpsMessageNone ),
       
    58         iExpiryTime( 0 )
       
    59     {
       
    60 #ifndef _NO_IMPS_LOGGING_
       
    61     CImpsClientLogger::Log( _L( "SubSession: CREATE subses=%d" ), ( TInt )this );
       
    62 #endif
       
    63     }
       
    64 
       
    65 // Destructor
       
    66 // Session destructor calls this
       
    67 CImpsSubSession::~CImpsSubSession()
       
    68     {
       
    69     DeleteAllRequests();
       
    70     DeleteAllEvents();
       
    71     delete iVariant;
       
    72 
       
    73     // complete event msg
       
    74     CompleteEventMsg( KErrCancel );
       
    75 
       
    76 #ifndef _NO_IMPS_LOGGING_
       
    77     CImpsClientLogger::Log( _L( "SubSession: DELETE subses=%d" ), ( TInt )this );
       
    78 #endif
       
    79     }
       
    80 
       
    81 // ---------------------------------------------------------
       
    82 // CImpsSubSession::NewL()
       
    83 // ---------------------------------------------------------
       
    84 CImpsSubSession* CImpsSubSession::NewL(
       
    85     CImpsSession* aSession,
       
    86     TImpsEventType aType,
       
    87     const RMessage2 aMessage )
       
    88     {
       
    89     CImpsSubSession*  self = new ( ELeave ) CImpsSubSession();
       
    90     // CleanupStack::PushL( self );
       
    91     // Close method has to be called since this is derived from CObject.
       
    92     CleanupClosePushL( *self );
       
    93     self->ConstructL( aSession, aType, aMessage );
       
    94     CleanupStack::Pop();
       
    95     return self;
       
    96     }
       
    97 
       
    98 // ---------------------------------------------------------
       
    99 // CImpsSubSession::ConstructL()
       
   100 // ---------------------------------------------------------
       
   101 void CImpsSubSession::ConstructL(
       
   102     CImpsSession* aSession,
       
   103     TImpsEventType aType,
       
   104     const RMessage2 aMessage )
       
   105     {
       
   106     iServiceType = aType;
       
   107     iSession = aSession;
       
   108     TInt msg = aMessage.Function();
       
   109 
       
   110     // get bit mask in an upper byte
       
   111     TInt flags = ( msg >> 16 );
       
   112 
       
   113     iOOMErr.Reset();
       
   114 
       
   115 #ifdef _FAKE_RESPONSE
       
   116     // **********************************
       
   117     // MODULE TEST for auxiliary classes
       
   118 
       
   119     TImpsSrvTestUtils::TestOOMList();
       
   120 
       
   121     // **********************************
       
   122 #endif
       
   123 
       
   124     iHandleNew = ( flags & KImpsReqHandleNew ) ? ETrue : EFalse;
       
   125     iVariant = CImpsVariant::NewLC( );
       
   126     CleanupStack::Pop( ); // >> iVariant
       
   127     // default value used ubtil client request to change it.
       
   128     iExpiryTime = Server()->ExpirySeconds( iServiceType );
       
   129     }
       
   130 
       
   131 // -----------------------------------------------------------------------------
       
   132 // CImpsSubSession::Unregister()
       
   133 // -----------------------------------------------------------------------------
       
   134 void CImpsSubSession::Unregister()
       
   135     {
       
   136 #ifndef _NO_IMPS_LOGGING_
       
   137     CImpsClientLogger::Log( _L( "SubSession: Unregister subses=%d h=%d type=%d" ),
       
   138                             ( TInt )this, Handle(), ( TInt )iServiceType );
       
   139 #endif
       
   140     iCanceled = ETrue;
       
   141     DeleteAllRequests();
       
   142 
       
   143     // Complete new message observer
       
   144     CompleteEventMsg( KErrCancel );
       
   145 
       
   146     ( void ) DeleteAllEvents();
       
   147     }
       
   148 
       
   149 // -----------------------------------------------------------------------------
       
   150 // CImpsSubSession::DeleteSub()
       
   151 // -----------------------------------------------------------------------------
       
   152 void CImpsSubSession::DeleteSub()
       
   153     {
       
   154 #ifndef _NO_IMPS_LOGGING_
       
   155     CImpsClientLogger::Log( _L( "SubSession: DeleteSub subses=%d type=%d" ), ( TInt )this, ( TInt )iServiceType );
       
   156 #endif
       
   157     // Calculate new expiry timer value
       
   158     Server()->ResetExpiryTimer( iExpiryTime );
       
   159     // Delete this entity
       
   160     RMessage2 myMsg( Message() );
       
   161     iSession->DeleteSubSession( myMsg.Int3() );
       
   162     }
       
   163 
       
   164 // ---------------------------------------------------------
       
   165 // CImpsSubSession::AssignIdL()
       
   166 // ---------------------------------------------------------
       
   167 void CImpsSubSession::AssignIdL( TImpsSessIdent aCSP )
       
   168     {
       
   169 #ifndef _NO_IMPS_LOGGING_
       
   170     CImpsClientLogger::Log( _L( "SubSession: AssignIdL subses=%d" ), ( TInt )this );
       
   171 #endif
       
   172     // create an event for each orphan message
       
   173     CImpsFields* msg = NULL;
       
   174     msg = Server()->NextOrphanLC( iSession->ApplicationId(), iServiceType, aCSP );
       
   175     while ( msg )
       
   176         {
       
   177         SendEvent( msg, 0, EImpsServNone, EImpsMessageNone );
       
   178         CleanupStack::PopAndDestroy();
       
   179         msg = Server()->NextOrphanLC( iSession->ApplicationId(), iServiceType, aCSP );
       
   180         }
       
   181     }
       
   182 
       
   183 // ---------------------------------------------------------
       
   184 // CImpsSubSession::HandleAllOrphans()
       
   185 // ---------------------------------------------------------
       
   186 void CImpsSubSession::HandleAllOrphans( TImpsSessIdent aCSP )
       
   187     {
       
   188 #ifndef _NO_IMPS_LOGGING_
       
   189     CImpsClientLogger::Log( _L( "SubSession: HandleAllOrphans subses=%d" ), ( TInt )this );
       
   190 #endif
       
   191     TInt err = KErrNone;
       
   192     TRAP( err, AssignIdL( aCSP ) );
       
   193     }
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // CImpsSubSession::DeleteAllEvents()
       
   197 // -----------------------------------------------------------------------------
       
   198 TInt CImpsSubSession::DeleteAllEvents(  )
       
   199     {
       
   200 #ifndef _NO_IMPS_LOGGING_
       
   201     CImpsClientLogger::Log( _L( "SubSession: DeleteAllEvents subses=%d" ), ( TInt )this );
       
   202 #endif
       
   203 
       
   204     TInt ret = 0;
       
   205 
       
   206     // Reset OOM_LIST too
       
   207     iOOMErr.Reset();
       
   208 
       
   209     // Delete all buffered events from this client,
       
   210 
       
   211     TDblQueIter<CWvEvent> rIter( iEventList );
       
   212 
       
   213     rIter.SetToFirst();
       
   214 
       
   215     while ( rIter )
       
   216         {
       
   217         CWvEvent* event = rIter;
       
   218         rIter++;
       
   219         if ( event->iSent )
       
   220             {
       
   221             ret++;
       
   222             }
       
   223         event->Destroy();
       
   224         }
       
   225 
       
   226     return ret;
       
   227     }
       
   228 
       
   229 // -----------------------------------------------------------------------------
       
   230 // CImpsSubSession::DeleteAllRequests()
       
   231 // -----------------------------------------------------------------------------
       
   232 void CImpsSubSession::DeleteAllRequests(  )
       
   233     {
       
   234 #ifndef _NO_IMPS_LOGGING_
       
   235     CImpsClientLogger::Log( _L( "SubSession: DeleteAllRequests" ) );
       
   236 #endif
       
   237     // Delete all buffered requests from this client.
       
   238 
       
   239     TDblQueIter<CRequest> rIter( iRequestList );
       
   240 
       
   241     rIter.SetToFirst();
       
   242 
       
   243     while ( rIter )
       
   244         {
       
   245         CRequest* requ = rIter;
       
   246         rIter++;
       
   247 #ifndef _NO_IMPS_LOGGING_
       
   248         CImpsClientLogger::Log( _L( "SubSession: DeleteAllRequests TID=%S" ), &( requ->iTID ) );
       
   249 #endif
       
   250         requ->Destroy();
       
   251         }
       
   252     }
       
   253 
       
   254 // ---------------------------------------------------------
       
   255 // CImpsSubSession::LoginL()
       
   256 // ---------------------------------------------------------
       
   257 void CImpsSubSession::LoginL( TBool aReactive )
       
   258     {
       
   259 #ifndef _NO_IMPS_LOGGING_
       
   260     CImpsClientLogger::Log( _L( "SubSession: LoginL begins reactive=%d subses=%d" ),
       
   261                             aReactive, ( TInt )this );
       
   262 #endif
       
   263 
       
   264     // OPID
       
   265     RMessage2 myMsg( Message() );
       
   266     TInt opId = myMsg.Int1();
       
   267 #ifndef _NO_IMPS_LOGGING_
       
   268     CImpsClientLogger::Log( _L( "SubSession: Login opid=%d" ), opId );
       
   269 #endif
       
   270 
       
   271     // Read PACKED ARRAY
       
   272     CDesCArrayFlat* tempArr = new ( ELeave )CDesCArrayFlat( 7 );
       
   273     CleanupStack::PushL( tempArr );   // << tempArr
       
   274 
       
   275     HBufC8* stream = *StreamBufAddr();
       
   276     if ( iSession->ReadBuffer8L( 0, stream ) )
       
   277         {
       
   278         HBufC8** stream2 = StreamBufAddr();
       
   279         *stream2 = stream;
       
   280         }
       
   281     TImpsPackedEntity packedMessage( stream );
       
   282     const TUint8* pS = stream->Ptr();
       
   283     packedMessage.DoUnpackArrayL( pS, tempArr );
       
   284 
       
   285     __ASSERT_DEBUG(
       
   286         tempArr->MdcaCount() == 7,
       
   287         User::Panic( KImpsPanicCategory,
       
   288                      EImpsCorrupted ) );
       
   289     TPtrC tid;
       
   290     TPtrC tempUser = tempArr->MdcaPoint( 0 );
       
   291     TPtrC tempPassword = tempArr->MdcaPoint( 1 );
       
   292     TPtrC tempCliId = tempArr->MdcaPoint( 2 );
       
   293     TPtrC tempSAP = tempArr->MdcaPoint( 3 );
       
   294     TPtrC key1 = tempArr->MdcaPoint( 4 );
       
   295     TPtrC key2 = tempArr->MdcaPoint( 5 );
       
   296     TPtrC ap = tempArr->MdcaPoint( 6 );
       
   297 
       
   298     // convert AP back
       
   299     TLex lex;
       
   300     TUint32 myAp;
       
   301     lex.Assign( ap );
       
   302     lex.Val( myAp, EDecimal );
       
   303 
       
   304     // Multi: update session's user-id and SAP.
       
   305     iSession->SetUserIdL( tempUser );
       
   306     iSession->SetSAPL( tempSAP );
       
   307 
       
   308     TImpsSessIdent csp( KNullDesC, tempSAP, tempUser );
       
   309     TPtrC p;
       
   310     if ( Server()->IsLogged( csp, &p ) )
       
   311         {
       
   312 #ifndef _NO_IMPS_LOGGING_
       
   313         CImpsClientLogger::Log( _L( "SubSession: CSP already logged ín subses=%d" ), ( TInt )this );
       
   314 #endif
       
   315         // check password: if it does not match then return an error.
       
   316         if ( p.CompareF( tempPassword ) )
       
   317             {
       
   318             User::Leave( KImpsErrorUnauthorized );
       
   319             }
       
   320 
       
   321         // Update session SID and other CSP identification data.
       
   322         iSession->ModifySIDL( Server()->SID( csp ) );
       
   323         iSession->SetSAPL( tempSAP );
       
   324         iSession->SetUserIdL( tempUser );
       
   325 
       
   326         // multi: Share existing CSP session
       
   327         // Send callback reponse to a client
       
   328         // Complete the open asyncronous request first and
       
   329         // after that send login event (callback).
       
   330         iSession->CompleteMe( KErrNone );
       
   331         SendLoginEvent( KErrNone, opId );
       
   332         if ( Server()->IsNegotiated( csp ) )
       
   333             {
       
   334             // On-line event too if CSP is negotiated.
       
   335             // Must sent via Session to all subsessions
       
   336             iSession->SendEvent( EInternal_ON_LINE );
       
   337             // Check orphan messages because of IM subsessions
       
   338             // may be registered before login request,
       
   339             // Create an event for each orphan message
       
   340             Server()->HandleAllOrphans();
       
   341             }
       
   342         tempArr->Reset();
       
   343         CleanupStack::PopAndDestroy( 1 );   // >> tempArr
       
   344         return;
       
   345         }
       
   346 
       
   347 
       
   348     // Save login expiry time and give it to CSP session too.
       
   349     TTime loginExpiry = Server()->ExpiryTime( iExpiryTime );
       
   350 
       
   351     tid.Set( Server()->LoginL( tempUser, tempPassword, tempCliId,
       
   352                                tempSAP, myAp, key1, key2, this, loginExpiry, aReactive ) );
       
   353 
       
   354     tempArr->Reset();
       
   355     CleanupStack::PopAndDestroy( 1 );   // >> tempArr
       
   356 
       
   357     // Update request queue
       
   358     // Add request into queue
       
   359     CRequest* request = new ( ELeave ) CRequest(
       
   360         tid,    // tid
       
   361         opId,   // op-id
       
   362         EImpsServWVLogin,
       
   363         loginExpiry,
       
   364         EImpsLoginReq
       
   365     );
       
   366 
       
   367     iRequestList.AddLast( *request );
       
   368 
       
   369 #ifndef _NO_IMPS_LOGGING_
       
   370     CImpsClientLogger::Log( _L( "SubSession: LoginL ends TID=%S" ), &tid );
       
   371 #endif
       
   372 
       
   373     }
       
   374 
       
   375 // ---------------------------------------------------------
       
   376 // CImpsSubSession::LogoutL()
       
   377 // ---------------------------------------------------------
       
   378 TPtrC CImpsSubSession::LogoutL( TImpsSessIdent aCSP, TBool aCancel )
       
   379     {
       
   380 #ifndef _NO_IMPS_LOGGING_
       
   381     CImpsClientLogger::Log( _L( "SubSession: LogoutL begins subses=%d" ), ( TInt )this );
       
   382 #endif
       
   383 
       
   384     RMessage2 myMsg( Message() );
       
   385     TInt opId = myMsg.Int0();
       
   386 #ifndef _NO_IMPS_LOGGING_
       
   387     CImpsClientLogger::Log( _L( "SubSession: Logout opid=%d" ), opId );
       
   388 #endif
       
   389 
       
   390     TPtrC tid;
       
   391 
       
   392     // Login-cancel.
       
   393     if ( aCancel )
       
   394         {
       
   395         // Check that request still exists, if not then leave KErrNotFound
       
   396         TBool found( EFalse );
       
   397         TDblQueIter<CRequest> requestIter( iRequestList );
       
   398         requestIter.SetToFirst();
       
   399         while ( requestIter )
       
   400             {
       
   401             CRequest* request = requestIter;
       
   402             requestIter++;
       
   403             if ( request->iOpId == opId )
       
   404                 {
       
   405                 found = ETrue;
       
   406                 break;
       
   407                 }
       
   408             }
       
   409         if ( !found )
       
   410             {
       
   411             User::Leave( KErrNotFound );
       
   412             }
       
   413         }
       
   414 
       
   415     // Send logout request forward to CSP session entity
       
   416     TRAPD( errL, tid.Set( iSession->Server()->LogoutL( aCancel, aCSP ) ) );
       
   417 
       
   418     // If canceling login operation then client needs to get only one callback method call,
       
   419     // so do not save new CRequest entity then. The CSP session entity will call later
       
   420     // SendEvent to respond to the cancelled login operation if there is something
       
   421     // to cancel.
       
   422     if ( aCancel )
       
   423         {
       
   424         if ( errL )
       
   425             {
       
   426             // If the previous request leaves then there is nothing to cancel.
       
   427             // Therefore delete the login request entity now and verify that CSP entity
       
   428             // clear the particular transaction data,
       
   429             CancelTrans( myMsg, aCSP );
       
   430             User::Leave( errL );
       
   431             }
       
   432         // CSPSession will call back later and delete the request and send a response
       
   433         // event to cancel request when everyting is clear regarding cancel of login
       
   434         // transaction..
       
   435         return TPtrC();
       
   436         }
       
   437     if ( errL == KImpsErrorTerminalOffLine )
       
   438         {
       
   439         // Logout requested in such a situation where Logout request is
       
   440         // not needed nor not possible to be sent to SAP server.
       
   441         // We have to generate a response here
       
   442         // because of Logout must not fail in client API.
       
   443         SendLogoutEvent( KErrNone, opId );
       
   444         // Send NOT_LOGGED events to subhandles
       
   445         iSession->SendEvent( EInternal_NOT_LOGGED );
       
   446         return TPtrC();
       
   447         }
       
   448     else if ( errL )
       
   449         {
       
   450         // Unexpeted error situation
       
   451         User::Leave( errL );
       
   452         }
       
   453 
       
   454     // Add request into request queue
       
   455     CRequest* request = new ( ELeave ) CRequest(
       
   456         tid,
       
   457         opId,
       
   458         EImpsServWVLogout,
       
   459         Server()->ExpiryTime( iExpiryTime ),
       
   460         EImpsLogoutReq
       
   461     );
       
   462     iRequestList.AddLast( *request );
       
   463 
       
   464 #ifndef _NO_IMPS_LOGGING_
       
   465     CImpsClientLogger::Log( _L( "SubSession: LogoutL ends with tid=%S" ), &tid );
       
   466 #endif
       
   467     return tid;
       
   468     }
       
   469 
       
   470 // ---------------------------------------------------------
       
   471 // CImpsSubSession::Message()
       
   472 // ---------------------------------------------------------
       
   473 // return message - get it from session
       
   474 const RMessagePtr2 CImpsSubSession::Message() const
       
   475     {
       
   476     return iSession->Message();
       
   477     }
       
   478 
       
   479 // ---------------------------------------------------------
       
   480 // CImpsSubSession::Server()
       
   481 // ---------------------------------------------------------
       
   482 // return message - get it from session
       
   483 CImpsServer* CImpsSubSession::Server()
       
   484     {
       
   485     return iSession->Server();
       
   486     }
       
   487 
       
   488 // ---------------------------------------------------------
       
   489 // CImpsSubSession::DoSendStatusEvent()
       
   490 // ---------------------------------------------------------
       
   491 void CImpsSubSession::DoSendStatusEvent( CWvEvent& aEvent )
       
   492     {
       
   493 
       
   494     // Status event is lighter than a regular event in a sense that
       
   495     // it does not write data to client thread, but updates iStatus
       
   496     // of the handler active object in a client thread only.
       
   497     if ( iEventMsg.IsNull() )
       
   498         {
       
   499 #ifndef _NO_IMPS_LOGGING_
       
   500         CImpsClientLogger::Log( _L( "SubSession: DoSendStatusEvent NULL MSG subses=%d" ),
       
   501                                 ( TInt )this );
       
   502 #endif
       
   503         return;
       
   504         }
       
   505 
       
   506     TInt newStatus = ConvertStatusCode( ( EImpsInternalStatus )aEvent.iAux );
       
   507 
       
   508 #ifndef _NO_IMPS_LOGGING_
       
   509     CImpsClientLogger::Log( _L( "SubSession: DoSendStatusEvent stat=%d subses=%d" ),
       
   510                             newStatus, ( TInt )this );
       
   511 #endif
       
   512     CompleteEventMsg( newStatus );
       
   513 
       
   514     aEvent.iSent = ETrue;
       
   515     }
       
   516 
       
   517 // ---------------------------------------------------------
       
   518 // CImpsSubSession::SendEvent()
       
   519 // ---------------------------------------------------------
       
   520 void CImpsSubSession::SendEvent(
       
   521     CImpsFields *aFields,
       
   522     TInt aOpId,
       
   523     TImpsServRequest aRequestType,
       
   524     TImpsMessageType aReqMsgType )
       
   525     {
       
   526 
       
   527     TInt memErr = KErrNone;
       
   528     // It is possible that the cancel request from client is not
       
   529     // complete and this session entity is still waiting deletion.
       
   530     if ( iCanceled  )
       
   531         {
       
   532 #ifndef _NO_IMPS_LOGGING_
       
   533         CImpsClientLogger::Log(
       
   534             _L( "SubSession: SendEvent cancelled subses=%d ****" ), ( TInt )this );
       
   535 #endif
       
   536         return;
       
   537         }
       
   538 
       
   539 #ifndef _NO_IMPS_LOGGING_
       
   540     CImpsClientLogger::Log( _L( "SubSession: SendEvent begins" ) );
       
   541 #endif
       
   542 
       
   543 
       
   544     TDblQueIter<CWvEvent> eventIter( iEventList );
       
   545 
       
   546     // Check if too many events waiting
       
   547     CWvEvent* event = NULL;
       
   548 
       
   549     // check if there is unhandled events for this session
       
   550     TBool thisFirst = ( NbrEvents() > 0 || iOOMErr.Exists() ) ? EFalse : ETrue;
       
   551 
       
   552     // Split GroupChangeNotice up to three parts for
       
   553     // HandleNewUsersL, HandleLeftUsersL and HandleGroupProperties
       
   554     if ( aFields->MessageType() == EImpsGroupChangeNotice )
       
   555         {
       
   556         TRAP( memErr, DoSplitGroupChangeL( aOpId, aRequestType, aFields ) );
       
   557         }
       
   558     else
       
   559         {
       
   560         TRAP( memErr, DoCreateEventL( aOpId, aRequestType, aReqMsgType, aFields ) );
       
   561         }
       
   562 
       
   563     // Now the event is ready to be sent.
       
   564     // Send the event to client thread if this is first one
       
   565     if ( thisFirst && !memErr )
       
   566         {
       
   567         // This should be a new event just created
       
   568         eventIter.SetToFirst();
       
   569         event = eventIter;
       
   570         __ASSERT_DEBUG(
       
   571             !event->iSent,
       
   572             User::Panic( KImpsPanicCategory,
       
   573                          EImpsCorrupted ) );
       
   574         // Select between base event and EventBody
       
   575         DoSendBaseEvent( *event );
       
   576         }
       
   577     // Notice: CSP negotiation requests (client capabilities and service
       
   578     // negotiaion) are internal for CSP class entity and they are not
       
   579     // originated from client. Thus corresponding negotiation phase
       
   580     // errors are not guaranted to be sent to a client in OOM situation.
       
   581     // In those cases the aOpId is NULL.
       
   582     //
       
   583     else if ( memErr && aOpId )
       
   584         {
       
   585         // send/store OOM error message ( KErrNoMemory, aOpId )
       
   586         iOOMErr.StoreOOM( aOpId );
       
   587         if ( thisFirst )
       
   588             {
       
   589             ( void )SendOOMError();
       
   590             }
       
   591         }
       
   592 
       
   593 #ifndef _NO_IMPS_LOGGING_
       
   594     CImpsClientLogger::Log( _L( "SubSession: SendEvent ends" ) );
       
   595 #endif
       
   596     }
       
   597 
       
   598 // ---------------------------------------------------------
       
   599 // CImpsSubSession::SendEvent()
       
   600 // Lighter version for engine status event
       
   601 //     Notice: CSP status changes are guaranted to
       
   602 //     to be sent to a client in OOM situation too.
       
   603 // ---------------------------------------------------------
       
   604 void CImpsSubSession::SendEvent(
       
   605     EImpsInternalStatus aStatus )
       
   606     {
       
   607 
       
   608     // It is possible that the cancel request from client is not
       
   609     // complete and this session entity is still waiting deletion.
       
   610     if ( iCanceled || !iStatusObserver  )
       
   611         {
       
   612         return;
       
   613         }
       
   614 
       
   615 #ifndef _NO_IMPS_LOGGING_
       
   616     CImpsClientLogger::Log( _L( "SubSession: SendEvent (status) subses=%d" ), ( TInt )this );
       
   617 #endif
       
   618 
       
   619     // check if there is unhandled events for this session
       
   620     TBool thisFirst = ( NbrEvents() > 0 || iOOMErr.Exists() ) ? EFalse : ETrue;
       
   621 
       
   622     // Prefer reqular event queue then OOM error queue in order
       
   623     // to save the logical order of events.
       
   624     TRAPD( memErr, DoCreateEventL( aStatus ) );
       
   625 
       
   626     if ( thisFirst && !memErr )
       
   627         {
       
   628         TDblQueIter<CWvEvent> eventIter( iEventList );
       
   629         CWvEvent* event = NULL;
       
   630         // This should be a new event just created
       
   631         eventIter.SetToFirst();
       
   632         event = eventIter;
       
   633         __ASSERT_DEBUG(
       
   634             !event->iSent,
       
   635             User::Panic( KImpsPanicCategory,
       
   636                          EImpsCorrupted ) );
       
   637         // Send the event immediately
       
   638         DoSendStatusEvent( *event );
       
   639         }
       
   640 
       
   641     else if ( memErr )
       
   642         {
       
   643         // send/store OOM error message ( status, aOpId )
       
   644         TInt retCode = ConvertStatusCode( aStatus );
       
   645         iOOMErr.StoreOOM( retCode );
       
   646         if ( thisFirst )
       
   647             {
       
   648             ( void )SendOOMError();
       
   649             }
       
   650         }
       
   651 
       
   652 #ifndef _NO_IMPS_LOGGING_
       
   653     CImpsClientLogger::Log( _L( "SubSession: SendEvent ends" ) );
       
   654 #endif
       
   655     }
       
   656 
       
   657 // ---------------------------------------------------------
       
   658 // CImpsSubSession::DoSendBaseEvent()
       
   659 // ---------------------------------------------------------
       
   660 void CImpsSubSession::DoSendBaseEvent( CWvEvent& aEvent )
       
   661     {
       
   662     TInt bufSize = EventMsgBufSize();
       
   663     TInt messageLength = aEvent.iPackedMessage ?
       
   664                          aEvent.iPackedMessage->Length() : 0;
       
   665     if ( bufSize > 0 && bufSize >= messageLength )
       
   666         {
       
   667         // Message body can be sent immediately.
       
   668         // This sends message headers too.
       
   669         DoSendEventBody( aEvent );
       
   670         }
       
   671     else
       
   672         {
       
   673         // No message body or client is asked to increase the buffer
       
   674         DoSendEventHeader( aEvent );
       
   675         }
       
   676     }
       
   677 
       
   678 // ---------------------------------------------------------
       
   679 // CImpsSubSession::DoSendEventHeader()
       
   680 // ---------------------------------------------------------
       
   681 void CImpsSubSession::DoSendEventHeader( CWvEvent& aEvent )
       
   682     {
       
   683 #ifndef _NO_IMPS_LOGGING_
       
   684     CImpsClientLogger::Log( _L( "SubSession: DoSendEventHeader type=%d subses=%d" ),
       
   685                             aEvent.iType, ( TInt )this );
       
   686 #endif
       
   687     RMessagePtr2 ptrMsg = EventMsg();
       
   688     if ( ptrMsg.IsNull() )
       
   689         {
       
   690 #ifndef _NO_IMPS_LOGGING_
       
   691         CImpsClientLogger::Log( _L( "SubSession: DoSendEventHeader NULL MSG subses=%d" ),
       
   692                                 ( TInt )this );
       
   693 #endif
       
   694         return;
       
   695         }
       
   696     // Create the header information
       
   697 
       
   698     TBuf < sizeof( SImpsEventData ) >
       
   699     eventBuf( sizeof( SImpsEventData ) );
       
   700 
       
   701     SImpsEventData* eventData =
       
   702         ( SImpsEventData* )eventBuf.Ptr();
       
   703 
       
   704     DoCreateEventIPC( aEvent, eventData );
       
   705 
       
   706     // Write the message header to client thread via a message.
       
   707     TInt err = KErrNone;
       
   708 
       
   709 
       
   710     err = DoWriteEventHeaders( ptrMsg, eventBuf );
       
   711 
       
   712     // We use NotifyHandler status parameter to pass the size of the
       
   713     // packed message!
       
   714     TInt messageLength = aEvent.iPackedMessage ?
       
   715                          aEvent.iPackedMessage->Length() : 0;
       
   716     if ( err == KErrNone )
       
   717         {
       
   718         err = messageLength;
       
   719         }
       
   720 
       
   721     // Signal event handler in a client thread
       
   722     CompleteEventMsg( err );
       
   723 
       
   724     aEvent.iSent = ETrue;
       
   725     }
       
   726 
       
   727 // ---------------------------------------------------------
       
   728 // CImpsSubSession::DoSendEventBody()
       
   729 // ---------------------------------------------------------
       
   730 void CImpsSubSession::DoSendEventBody( CWvEvent& aEvent )
       
   731     {
       
   732 #ifndef _NO_IMPS_LOGGING_
       
   733     CImpsClientLogger::Log( _L( "SubSession: DoSendEventBody type=%d subses=%d" ),
       
   734                             aEvent.iType, ( TInt )this );
       
   735 #endif
       
   736 
       
   737     RMessagePtr2 ptrMsg = EventMsg();
       
   738     if ( ptrMsg.IsNull() )
       
   739         {
       
   740 #ifndef _NO_IMPS_LOGGING_
       
   741         CImpsClientLogger::Log( _L( "SubSession: DoSendEventBody NULL MSG subses=%d" ),
       
   742                                 ( TInt )this );
       
   743 #endif
       
   744         return;
       
   745         }
       
   746 
       
   747     // This writes both headers and body.
       
   748     // This increases the robustenss and thre client thread do not need
       
   749     // to store data between these transactions, because of it receives
       
   750     // all the necessary data at once.
       
   751 
       
   752     TBuf < sizeof( SImpsEventData ) >
       
   753     eventBuf( sizeof( SImpsEventData ) );
       
   754 
       
   755     SImpsEventData* eventData =
       
   756         ( SImpsEventData* )eventBuf.Ptr();
       
   757 
       
   758     DoCreateEventIPC( aEvent, eventData );
       
   759     eventData->iMessageBody = ( aEvent.iPackedMessage ? ETrue : EFalse );
       
   760 
       
   761     // Write the message header to client thread via a message.
       
   762     TInt err = KErrNone;
       
   763     err = DoWriteEventHeaders( ptrMsg, eventBuf );
       
   764 
       
   765     if ( !err )
       
   766         {
       
   767         // Write the message body
       
   768         err = DoWriteEventBody( ptrMsg, aEvent );
       
   769         // We use NotifyHandler status parameter to pass the size of the
       
   770         // packed message!
       
   771         TInt messageLength = aEvent.iPackedMessage ?
       
   772                              aEvent.iPackedMessage->Length() : 0;
       
   773         if ( err == KErrNone )
       
   774             {
       
   775             err = messageLength;
       
   776             }
       
   777         }
       
   778 
       
   779     // Signal event handler in a client thread
       
   780     CompleteEventMsg( err );
       
   781 
       
   782     aEvent.iSent = ETrue;
       
   783     }
       
   784 
       
   785 // ---------------------------------------------------------
       
   786 // CImpsSubSession::SendLogoutEvent
       
   787 // ---------------------------------------------------------
       
   788 void CImpsSubSession::SendLogoutEvent( TInt aRespStatus, TInt aOpId )
       
   789     {
       
   790     // transfer CSP error code if any
       
   791     if ( aRespStatus > 0 )
       
   792         {
       
   793         aRespStatus = ErrorCode( aRespStatus );
       
   794         }
       
   795 
       
   796     // check session type first and filter sending
       
   797     // of the same logout twice
       
   798     if ( iServiceType != EImpsEventServerLogin ||
       
   799          ( iLastEvent == EImpsDisconnect && aOpId == 0 ) )
       
   800         {
       
   801         return;
       
   802         }
       
   803 
       
   804 #ifndef _NO_IMPS_LOGGING_
       
   805     CImpsClientLogger::Log( _L( "SubSession: SendLogoutEvent in action subses=%d" ),
       
   806                             ( TInt )this );
       
   807 #endif
       
   808 
       
   809     TDblQueIter<CWvEvent> eventIter( iEventList );
       
   810     CWvEvent* event = NULL;
       
   811 
       
   812     // check if there is unhandled events for this session
       
   813     TBool thisFirst = ( NbrEvents() > 0 || iOOMErr.Exists() ) ? EFalse : ETrue;
       
   814 
       
   815     // Let this behave like real SAP initiated Disconnect primitive
       
   816     TRAPD( memErr, DoCreateEventL( aOpId, aRespStatus,
       
   817                                    EImpsMessageNone, EImpsDisconnect, EImpsServWVLogout ) );
       
   818     // Since WV 1,2 logout messages may be either disconnect or Status,
       
   819     // harmomize them here in order to avoid sending logout message
       
   820     // with opid=actual_id and opid=0.
       
   821     iLastEvent = EImpsDisconnect;
       
   822 
       
   823     // Now the event is ready to be sent.
       
   824     // Send the event to client thread if this is first one
       
   825     if ( thisFirst && !memErr )
       
   826         {
       
   827         // This should be a new event just created
       
   828         eventIter.SetToFirst();
       
   829         event = eventIter;
       
   830         __ASSERT_DEBUG(
       
   831             !event->iSent,
       
   832             User::Panic( KImpsPanicCategory,
       
   833                          EImpsCorrupted ) );
       
   834         // Logout event does not contain body in this case
       
   835         DoSendEventHeader( *event );
       
   836         }
       
   837     else if ( memErr && aOpId )
       
   838         {
       
   839         // send/store OOM error message ( KErrNoMemory, aOpId )
       
   840         iOOMErr.StoreOOM( aOpId );
       
   841         if ( thisFirst )
       
   842             {
       
   843             ( void )SendOOMError();
       
   844             }
       
   845         }
       
   846     }
       
   847 
       
   848 // ---------------------------------------------------------
       
   849 // CImpsSubSession::SendLoginEvent
       
   850 // Multi: new method to generate events when CSP session
       
   851 // already exists
       
   852 // ---------------------------------------------------------
       
   853 void CImpsSubSession::SendLoginEvent( TInt aRespStatus, TInt aOpId )
       
   854     {
       
   855     // transfer CSP error code if any
       
   856     if ( aRespStatus > 0 )
       
   857         {
       
   858         aRespStatus = ErrorCode( aRespStatus );
       
   859         }
       
   860 
       
   861     // check session type first and filter sending
       
   862     // of the same logout twice
       
   863     if ( iServiceType != EImpsEventServerLogin )
       
   864         {
       
   865         return;
       
   866         }
       
   867 
       
   868 #ifndef _NO_IMPS_LOGGING_
       
   869     CImpsClientLogger::Log( _L( "SubSession: SendLoginEvent in action subses=%d" ),
       
   870                             ( TInt )this );
       
   871 #endif
       
   872 
       
   873     TDblQueIter<CWvEvent> eventIter( iEventList );
       
   874     CWvEvent* event = NULL;
       
   875 
       
   876     // check if there is unhandled events for this session
       
   877     TBool thisFirst = ( NbrEvents() > 0 || iOOMErr.Exists() ) ? EFalse : ETrue;
       
   878 
       
   879     // Let this behave like real SAP initiated Disconnect primitive
       
   880     TRAPD( memErr, DoCreateEventL( aOpId, aRespStatus,
       
   881                                    EImpsMessageNone, EImpsLoginRes, EImpsServWVLogin ) );
       
   882 
       
   883     // Now the event is ready to be sent.
       
   884     // Send the event to client thread if this is first one
       
   885     if ( thisFirst && !memErr )
       
   886         {
       
   887         // This should be a new event just created
       
   888         eventIter.SetToFirst();
       
   889         event = eventIter;
       
   890         __ASSERT_DEBUG(
       
   891             !event->iSent,
       
   892             User::Panic( KImpsPanicCategory,
       
   893                          EImpsCorrupted ) );
       
   894         // Logout event does not contain body in this case
       
   895         DoSendEventHeader( *event );
       
   896         }
       
   897     else if ( memErr && aOpId )
       
   898         {
       
   899         // send/store OOM error message ( KErrNoMemory, aOpId )
       
   900         iOOMErr.StoreOOM( aOpId );
       
   901         if ( thisFirst )
       
   902             {
       
   903             ( void )SendOOMError();
       
   904             }
       
   905         }
       
   906     }
       
   907 
       
   908 // ---------------------------------------------------------
       
   909 // CImpsSubSession::SendOOMError
       
   910 // ---------------------------------------------------------
       
   911 TBool CImpsSubSession::SendOOMError( )
       
   912     {
       
   913 
       
   914     if ( iEventMsg.IsNull() )
       
   915         {
       
   916 #ifndef _NO_IMPS_LOGGING_
       
   917         CImpsClientLogger::Log(
       
   918             _L( "SubSession: SendOOMError NULL MSG subses=%d" ), ( TInt )this );
       
   919 #endif
       
   920         return EFalse;
       
   921         }
       
   922 
       
   923     TInt opId = iOOMErr.GetOOM();
       
   924     if ( opId != 0 )
       
   925         {
       
   926         if ( opId > 0 )
       
   927             {
       
   928             CompleteEventMsg( KImpsOOMReply | opId );
       
   929 #ifndef _NO_IMPS_LOGGING_
       
   930             CImpsClientLogger::Log(
       
   931                 _L( "SubSession: SendOOMError completes opid=%d ****" ), opId );
       
   932 #endif
       
   933             }
       
   934         else
       
   935             {
       
   936             // Status change special error code etc
       
   937             CompleteEventMsg( opId );
       
   938 #ifndef _NO_IMPS_LOGGING_
       
   939             CImpsClientLogger::Log(
       
   940                 _L( "SubSession: SendOOMError completes status=%d ****" ), opId );
       
   941 #endif
       
   942             }
       
   943         return ETrue;
       
   944         }
       
   945     else
       
   946         {
       
   947         return EFalse;
       
   948         }
       
   949     }
       
   950 
       
   951 // ---------------------------------------------------------
       
   952 // CImpsSubSession::SendPrimitiveL()
       
   953 // ---------------------------------------------------------
       
   954 void CImpsSubSession::SendPrimitiveL( TInt aFunction, TImpsSessIdent aCSP )
       
   955     {
       
   956     RMessage2 myMsg( Message() );
       
   957     TInt opId = myMsg.Int1();
       
   958 #ifndef _NO_IMPS_LOGGING_
       
   959     CImpsClientLogger::Log( _L( "SubSession: SendPrimitiveL begins %d opid=%d" ),
       
   960                             aFunction, opId );
       
   961 #endif
       
   962 
       
   963     switch ( aFunction )
       
   964         {
       
   965         case EImpsServWVSendOnly:
       
   966         case EImpsServBlock:
       
   967             // Check availability of the service in general
       
   968             TImpsSrvUtils::CheckServiceL( EIMFeat,
       
   969                                           Server()->Services( aCSP ) );
       
   970             break;
       
   971         case EImpsServGroup:
       
   972             TImpsSrvUtils::CheckServiceL( EGroupFeat,
       
   973                                           Server()->Services( aCSP ) );
       
   974             break;
       
   975         case EImpsServPres:
       
   976             TImpsSrvUtils::CheckServiceL( EPresenceFeat,
       
   977                                           Server()->Services( aCSP ) );
       
   978             break;
       
   979         case EImpsServFundSearch:
       
   980         case EImpsServFundInvite:
       
   981             TImpsSrvUtils::CheckServiceL( EFundamentalFeat,
       
   982                                           Server()->Services( aCSP ) );
       
   983             break;
       
   984         default:
       
   985             break;
       
   986         }
       
   987     // Get data to iFields
       
   988     GetWVDataL();
       
   989 
       
   990     TImpsMessageType myMesType = ( TImpsMessageType ) ImpsFields()->MessageType();
       
   991 
       
   992     // Check primitive if this is pure subsession
       
   993     // Discard anything that does not belong to presence service
       
   994     if ( iServiceType == EImpsEventPresencePure &&
       
   995          impsService( iVariant, TImpsMessageType( myMesType ) ) != EImpsEventPresence )
       
   996         {
       
   997         User::Leave( KImpsErrorUnknownMessageType );
       
   998         }
       
   999 
       
  1000     // Add sender if it is empty in new IM message
       
  1001     if ( aFunction == EImpsServWVSendOnly )
       
  1002         {
       
  1003         TPtrC sender;
       
  1004         TPtrC group;
       
  1005         CImpsKey* myKey = CImpsKey::NewLC();      // <<< myKey
       
  1006         TImpsSDataUtils::AddValuesFromArrayL(
       
  1007             myKey,
       
  1008             KSendMessageElements,
       
  1009             sizeof( KSendMessageElements ) /
       
  1010             sizeof( KSendMessageElements[0] ) );
       
  1011         myKey->AddL( CREATEKEY( EImpsKeyMessageInfo, 0 ) );
       
  1012         TImpsDataAccessor myAc( ImpsFields() );
       
  1013         TImpsSDataUtils::GetSenderL( myKey, &myAc, sender, group );
       
  1014         if ( sender.Length() == 0 )
       
  1015             {
       
  1016             TPtrC userId = iSession->UserId();
       
  1017             // Set Sender( User( UserID )) if sender not specified
       
  1018             // in client API
       
  1019             // Notice: Here we could add assigned clientID if wanted so.
       
  1020             TImpsSDataUtils::SetSenderL(
       
  1021                 myKey,
       
  1022                 &myAc,
       
  1023                 &userId,
       
  1024                 NULL );
       
  1025             }
       
  1026 
       
  1027         TPtrC applicationID( iSession->ApplicationId() );
       
  1028         if ( applicationID.Length() != 0 )
       
  1029             {
       
  1030             // insert the ExtBlock
       
  1031             myKey->PopL( 3 );
       
  1032             myKey->AddL( CREATEKEY( EImpsKeyExtBlock, 0 ) );
       
  1033             myKey->AddL( CREATEKEY( EImpsKeyAPIClient, 0 ) );
       
  1034             myAc.StoreDescL( myKey, applicationID );
       
  1035             }
       
  1036 
       
  1037 
       
  1038         CleanupStack::PopAndDestroy( 1 );   // >>> myKey
       
  1039 
       
  1040         }
       
  1041 
       
  1042     TPtrC tid;
       
  1043 
       
  1044     // Send data may in certain situation change iFields,
       
  1045     // so copy data address to safe.
       
  1046     tid.Set( Server()->SendDataL( this, aCSP ) );
       
  1047 
       
  1048     // Add request into queue
       
  1049     CRequest* request = new ( ELeave ) CRequest(
       
  1050         tid,    // tid
       
  1051         opId,   // op-id
       
  1052         ( TImpsServRequest )aFunction,
       
  1053         Server()->ExpiryTime( iExpiryTime ),
       
  1054         myMesType );
       
  1055     iRequestList.AddLast( *request );
       
  1056 
       
  1057     }
       
  1058 
       
  1059 // ---------------------------------------------------------
       
  1060 // CImpsSubSession::SendGetBlockedL()
       
  1061 // This is for IM GetBlocked, only ID received from client
       
  1062 // ---------------------------------------------------------
       
  1063 void CImpsSubSession::SendGetBlockedL( TImpsSessIdent aCSP )
       
  1064     {
       
  1065 
       
  1066     RMessage2 myMsg( Message() );
       
  1067     TInt opId = myMsg.Int1();
       
  1068 
       
  1069 #ifndef _NO_IMPS_LOGGING_
       
  1070     CImpsClientLogger::Log( _L( "SubSession: SendGetBlockedL  opid=%d" ), opId );
       
  1071 #endif
       
  1072 
       
  1073     // Check availability of the service in general
       
  1074     TImpsSrvUtils::CheckServiceL( EIMFeat, Server()->Services( aCSP ) );
       
  1075 
       
  1076     // Generate the stuff. Server thread finalizes the message adding
       
  1077     // session-id etc
       
  1078 
       
  1079     ImpsFields()->Reset();
       
  1080     ImpsFields()->SetMessageType( EImpsGetBlockedListReq );
       
  1081 
       
  1082     CImpsDataAccessor* myAc = CImpsDataAccessor::NewL( ImpsFields() );
       
  1083     CleanupStack::PushL( myAc );        // <<< myAc
       
  1084     CImpsKey* myKey = CImpsKey::NewLC();    // <<< myKey
       
  1085 
       
  1086     TImpsSDataUtils::AddValuesFromArrayL(
       
  1087         myKey,
       
  1088         KTransContentElements,
       
  1089         sizeof( KTransContentElements ) /
       
  1090         sizeof( KTransContentElements[0] ) );
       
  1091     myKey->AddL( CREATEKEY( EImpsKeyGetBlockedList_Request, 0 ) );
       
  1092     myAc->StoreEmptyL( myKey );
       
  1093 
       
  1094     TPtrC tid;
       
  1095 
       
  1096     // Send data may in certain situation change iFields,
       
  1097     // so copy data to safe.
       
  1098     tid.Set( Server()->SendDataL( this, aCSP ) );
       
  1099 
       
  1100     // Update request queue
       
  1101     // Add request into queue
       
  1102     CRequest* request = new ( ELeave ) CRequest(
       
  1103         tid,            // tid
       
  1104         opId,           // op-id
       
  1105         EImpsServGetBlocked,
       
  1106         Server()->ExpiryTime( iExpiryTime ),
       
  1107         EImpsGetBlockedListReq );
       
  1108     iRequestList.AddLast( *request );
       
  1109 
       
  1110     CleanupStack::PopAndDestroy( 2 );   // >>> myAc, myKey
       
  1111     }
       
  1112 
       
  1113 // ---------------------------------------------------------
       
  1114 // CImpsSubSession::DoNextEvent()
       
  1115 // ---------------------------------------------------------
       
  1116 void CImpsSubSession::DoNextEvent()
       
  1117     {
       
  1118 
       
  1119     // check OOM_LIST first
       
  1120     iOOMErr.RemoveOOM();
       
  1121     TInt errId = SendOOMError();
       
  1122     if ( errId )
       
  1123         {
       
  1124         return;
       
  1125         }
       
  1126 
       
  1127     // Delete the event that was sent and send next
       
  1128     TDblQueIter<CWvEvent> eventIter( iEventList );
       
  1129     eventIter.SetToFirst();
       
  1130 
       
  1131     while ( eventIter )
       
  1132         {
       
  1133         CWvEvent* event = eventIter;
       
  1134         eventIter++;
       
  1135 
       
  1136         if ( event->iSent )
       
  1137             {
       
  1138             event->Destroy();
       
  1139             }
       
  1140         else
       
  1141             {
       
  1142             if ( event->iRequestType != EImpsServStatusReg )
       
  1143                 {
       
  1144                 DoSendBaseEvent( *event );
       
  1145                 }
       
  1146             else
       
  1147                 {
       
  1148                 DoSendStatusEvent( *event );
       
  1149                 }
       
  1150             // Only one event at a time is possible
       
  1151             break;
       
  1152             }
       
  1153         }
       
  1154     }
       
  1155 
       
  1156 // ---------------------------------------------------------
       
  1157 // CImpsSubSession::DoEventBodyL()
       
  1158 // ---------------------------------------------------------
       
  1159 void CImpsSubSession::DoEventBodyL()
       
  1160     {
       
  1161     // Check that the first event (headers) in the queue
       
  1162     // is sent
       
  1163     TDblQueIter<CWvEvent> eventIter( iEventList );
       
  1164     eventIter.SetToFirst();
       
  1165     CWvEvent* event = eventIter;
       
  1166     if ( !event || !event->iSent )
       
  1167         {
       
  1168         // This ensures that if the synchronization between client-server
       
  1169         // is lost the next messages are handled because of the
       
  1170         // client asks next event after this error.
       
  1171         User::Leave( KImpsGeneralError );
       
  1172         }
       
  1173 
       
  1174     // Write the body to the client thread
       
  1175     DoSendEventBody( *event );
       
  1176     }
       
  1177 
       
  1178 // ---------------------------------------------------------
       
  1179 // CImpsSubSession::DiscardRequests()
       
  1180 // Expiry detection
       
  1181 // ---------------------------------------------------------
       
  1182 void CImpsSubSession::DiscardRequests(
       
  1183     TTime aExpiryTime,
       
  1184     TImpsEventType aServiceType,
       
  1185     MImpsCSPSession* aSess )
       
  1186     {
       
  1187 
       
  1188     // It is possible that the cancel request from client is not
       
  1189     // complete and this session entity is still waiting deletion.
       
  1190     if ( iCanceled )
       
  1191         {
       
  1192         return;
       
  1193         }
       
  1194 
       
  1195     if ( !( aServiceType & iServiceType ) )
       
  1196         {
       
  1197         return;
       
  1198         }
       
  1199 
       
  1200     // check if there is unhandled events for this session
       
  1201     TBool thisFirst = ( NbrEvents() > 0 || iOOMErr.Exists() ) ? EFalse : ETrue;
       
  1202 
       
  1203     TDblQueIter<CRequest> requestIter( iRequestList );
       
  1204     requestIter.SetToFirst();
       
  1205     while ( requestIter )
       
  1206         {
       
  1207         CRequest* request = requestIter;
       
  1208         requestIter++;
       
  1209         if ( request->iExpiry < aExpiryTime )
       
  1210             {
       
  1211             // expired entry found
       
  1212             // Create error event for UI API
       
  1213 #ifndef _NO_IMPS_LOGGING_
       
  1214             CImpsClientLogger::Log(
       
  1215                 _L( "SubSession: Entry EXPIRED type=%d subses=%d" ),
       
  1216                 request->iRequestType, ( TInt )this );
       
  1217 #endif
       
  1218             // Delete the message from server queues if not send
       
  1219             Server()->CancelTrans( request->iTID, aSess );
       
  1220             // Create event for client
       
  1221             TRAPD( memErr, DoCreateEventL(
       
  1222                        request->iOpId,
       
  1223                        KErrTimedOut,
       
  1224                        request->iMessageType ) );
       
  1225 
       
  1226             // store OOM error message if necessary ( KErrNoMemory, aOpId )
       
  1227             if ( memErr )
       
  1228                 {
       
  1229                 iOOMErr.StoreOOM( request->iOpId );
       
  1230                 }
       
  1231 
       
  1232             // Send an event if this is first
       
  1233             if ( thisFirst )
       
  1234                 {
       
  1235                 DoNextEvent();
       
  1236                 thisFirst = EFalse;
       
  1237                 }
       
  1238             // delete request from queue
       
  1239 #ifndef _NO_IMPS_LOGGING_
       
  1240             CImpsClientLogger::Log(
       
  1241                 _L( "SubSession: DiscardRequests TID=%S" ), &( request->iTID ) );  //lint !e525
       
  1242 #endif
       
  1243             request->Destroy();
       
  1244             }
       
  1245         }
       
  1246     }
       
  1247 
       
  1248 // ---------------------------------------------------------
       
  1249 // CImpsSubSession::DiscardRequests()
       
  1250 // Discrad all requests
       
  1251 // ---------------------------------------------------------
       
  1252 void CImpsSubSession::DiscardRequests(
       
  1253     TInt aError,
       
  1254     TImpsEventType aServiceType,
       
  1255     MImpsCSPSession* aSess )
       
  1256     {
       
  1257 
       
  1258     // It is possible that the cancel request from client is not
       
  1259     // complete and this session entity is still waiting deletion.
       
  1260     if ( iCanceled )
       
  1261         {
       
  1262         return;
       
  1263         }
       
  1264 
       
  1265     if ( !( aServiceType & iServiceType ) )
       
  1266         {
       
  1267         return;
       
  1268         }
       
  1269 
       
  1270     // check if there is unhandled events for this session
       
  1271     TBool thisFirst = ( NbrEvents() > 0 || iOOMErr.Exists() ) ? EFalse : ETrue;
       
  1272 
       
  1273     TDblQueIter<CRequest> requestIter( iRequestList );
       
  1274     requestIter.SetToFirst();
       
  1275     while ( requestIter )
       
  1276         {
       
  1277         CRequest* request = requestIter;
       
  1278         requestIter++;
       
  1279 
       
  1280 #ifndef _NO_IMPS_LOGGING_
       
  1281         CImpsClientLogger::Log(
       
  1282             _L( "SubSession: Entry DISCARDED type=%d subses=%d" ),
       
  1283             request->iRequestType, ( TInt )this );
       
  1284 #endif
       
  1285         // Delete the message from server queues if not send
       
  1286         Server()->CancelTrans( request->iTID, aSess );
       
  1287         // Create event for client
       
  1288         TRAPD( memErr, DoCreateEventL(
       
  1289                    request->iOpId,
       
  1290                    aError,
       
  1291                    request->iMessageType ) );
       
  1292 
       
  1293         if ( memErr )
       
  1294             {
       
  1295             iOOMErr.StoreOOM( request->iOpId );
       
  1296             }
       
  1297 
       
  1298         // Try to send event if this is first
       
  1299         if ( thisFirst )
       
  1300             {
       
  1301             DoNextEvent();
       
  1302             thisFirst = EFalse;
       
  1303             }
       
  1304         // delete request from queue
       
  1305 #ifndef _NO_IMPS_LOGGING_
       
  1306         CImpsClientLogger::Log(
       
  1307             _L( "SubSession: DiscardRequests TID=%S" ), &( request->iTID ) ); //lint !e525
       
  1308 #endif
       
  1309         request->Destroy();
       
  1310 
       
  1311         }
       
  1312     }
       
  1313 
       
  1314 // ---------------------------------------------------------
       
  1315 // CImpsSubSession::DiscardRequest()
       
  1316 // Discard a single request
       
  1317 // ---------------------------------------------------------
       
  1318 TBool CImpsSubSession::DiscardRequest(
       
  1319     const TDesC& aTid,
       
  1320     TImpsEventType aServiceType,
       
  1321     TInt aCode )
       
  1322     {
       
  1323 
       
  1324     // It is possible that the cancel request from client is not
       
  1325     // complete and this session entity is still waiting deletion.
       
  1326     if ( iCanceled )
       
  1327         {
       
  1328         return EFalse;
       
  1329         }
       
  1330 
       
  1331     TBool ret( EFalse );
       
  1332     if ( aServiceType != iServiceType )
       
  1333         {
       
  1334         return ret;
       
  1335         }
       
  1336 
       
  1337     // check if there is unhandled events for this session
       
  1338     TBool thisFirst = ( NbrEvents() > 0 || iOOMErr.Exists() ) ? EFalse : ETrue;
       
  1339 
       
  1340 #ifndef _NO_IMPS_LOGGING_
       
  1341     CImpsClientLogger::Log( _L( "SubSession: DiscardRequest subses=%d" ), ( TInt )this );
       
  1342 #endif
       
  1343 
       
  1344     TDblQueIter<CRequest> requestIter( iRequestList );
       
  1345     requestIter.SetToFirst();
       
  1346     while ( requestIter )
       
  1347         {
       
  1348         CRequest* request = requestIter;
       
  1349         requestIter++;
       
  1350         if ( !request->iTID.Compare( aTid ) )
       
  1351             {
       
  1352             // entry found
       
  1353             // Create error event for UI API
       
  1354 #ifndef _NO_IMPS_LOGGING_
       
  1355             CImpsClientLogger::Log( _L( "SubSession: entry DISCARDED" ) );
       
  1356 #endif
       
  1357             TRAPD( memErr, DoCreateEventL( request->iOpId,
       
  1358                                            aCode,
       
  1359                                            request->iMessageType ) );
       
  1360 
       
  1361             if ( memErr )
       
  1362                 {
       
  1363                 // store OOM error message ( KErrNoMemory, aOpId )
       
  1364                 iOOMErr.StoreOOM( request->iOpId );
       
  1365                 }
       
  1366 
       
  1367             // The following is NOT called because of server has called this.
       
  1368             // Server()->CancelTrans( request->iTID );
       
  1369             // delete request from queue
       
  1370             request->Destroy();
       
  1371             ret = ETrue;
       
  1372             break;
       
  1373             }
       
  1374         }
       
  1375 
       
  1376     // Send the new event only if no old events in queue
       
  1377     if ( ret && thisFirst )
       
  1378         {
       
  1379         DoNextEvent();
       
  1380         }
       
  1381 
       
  1382     return ret;
       
  1383     }
       
  1384 
       
  1385 // ---------------------------------------------------------
       
  1386 // CImpsSubSession::CheckNotification()
       
  1387 // ---------------------------------------------------------
       
  1388 TBool CImpsSubSession::CheckNotification( CImpsFields* aFields )
       
  1389     {
       
  1390 
       
  1391     TBool ret ( EFalse );
       
  1392     TRAPD( errx, ( ret = DoCheckNotificationL( aFields ) ) );
       
  1393     if ( ret && !errx )
       
  1394         {
       
  1395         return ETrue;
       
  1396         }
       
  1397     else
       
  1398         {
       
  1399         return EFalse;
       
  1400         }
       
  1401     }
       
  1402 
       
  1403 // ---------------------------------------------------------
       
  1404 // CImpsSubSession::DoCheckNotificationL()
       
  1405 // Notice: MessageNotifiction not supported.
       
  1406 // ---------------------------------------------------------
       
  1407 TBool CImpsSubSession::DoCheckNotificationL( CImpsFields* aFields )
       
  1408     {
       
  1409 
       
  1410     // It is possible that the cancel request from client is not
       
  1411     // complete and this session entity is still waiting deletion.
       
  1412     if ( iCanceled )
       
  1413         {
       
  1414         return EFalse;
       
  1415         }
       
  1416 
       
  1417     // Filter new messages out if necessary
       
  1418     if ( !iHandleNew )
       
  1419         {
       
  1420 #ifndef _NO_IMPS_LOGGING_
       
  1421         CImpsClientLogger::Log( _L( "SubSession: new msg FILTERED OUT" ) );
       
  1422 #endif
       
  1423         return EFalse;
       
  1424         }
       
  1425 
       
  1426     TImpsDataAccessor myAc( aFields );
       
  1427     TPtrC msgContentType;
       
  1428     TBool retVal = EFalse;
       
  1429     TInt messageType = aFields->MessageType();
       
  1430 
       
  1431     // Handle SAP initiated transactions here.
       
  1432     //
       
  1433     switch ( this->iServiceType )
       
  1434         {
       
  1435         case EImpsEventMessage:
       
  1436             if ( messageType == EImpsNewMessage )
       
  1437                 {
       
  1438                 retVal = ETrue;
       
  1439                 // Checking the ApplicationID
       
  1440                 // Consider client-id routing if media type is ok
       
  1441                 /*
       
  1442                  * 1) Get the ApplicationID from the message
       
  1443                  * 2) Get the ApplicationID from the corresponding session
       
  1444                  *    ownClientId = iSession->ApplicationID();
       
  1445                  * 3) if ownClientId == messageClientId -> retVal = ETrue,
       
  1446                  *    this includes the case when both are empty
       
  1447                  * 4) otherwise retVal = EFalse
       
  1448                 */
       
  1449                 TPtrC messageAppID; // The recipient's ApplicationID
       
  1450 
       
  1451                 TImpsSDataUtils::GetApplicationIDL( &myAc, messageAppID );
       
  1452 
       
  1453                 if ( !messageAppID.Compare( iSession->ApplicationId() ) )
       
  1454                     {
       
  1455                     // The ClientIDs are matching
       
  1456                     retVal = ETrue;
       
  1457                     }
       
  1458                 else
       
  1459                     {
       
  1460                     retVal = EFalse;
       
  1461                     }
       
  1462                 }
       
  1463             else if ( messageType == EImpsDeliveryReportReq )
       
  1464                 {
       
  1465                 retVal = ETrue;
       
  1466                 }
       
  1467             break;
       
  1468         case EImpsEventServerLogin:
       
  1469             if ( messageType == EImpsDisconnect )
       
  1470                 {
       
  1471                 retVal = ETrue;
       
  1472                 }
       
  1473             break;
       
  1474         case EImpsEventGroup:
       
  1475             if ( messageType == EImpsLeaveGroupRes ||
       
  1476                  messageType == EImpsGroupChangeNotice )
       
  1477                 {
       
  1478                 retVal = ETrue;
       
  1479                 }
       
  1480             break;
       
  1481         case EImpsEventCommon:
       
  1482             if ( messageType == EImpsInviteUserReq ||
       
  1483                  messageType == EImpsInviteRes ||
       
  1484                  messageType == EImpsCancelInviteUserReq )
       
  1485                 {
       
  1486                 retVal = ETrue;
       
  1487                 }
       
  1488             break;
       
  1489         case EImpsEventPresence:
       
  1490         case EImpsEventPresencePure:
       
  1491             if ( messageType == EImpsPresenceNotification ||
       
  1492                  messageType == EImpsPresenceAuthReq ||
       
  1493                  messageType == EImpsPureData )
       
  1494                 {
       
  1495                 retVal = ETrue;
       
  1496                 }
       
  1497             break;
       
  1498         default:
       
  1499             retVal = EFalse;
       
  1500             break;
       
  1501         }
       
  1502 
       
  1503     return retVal;
       
  1504     }
       
  1505 
       
  1506 // ---------------------------------------------------------
       
  1507 // CImpsSubSession::CheckRequests()
       
  1508 // ---------------------------------------------------------
       
  1509 TBool CImpsSubSession::CheckRequests(
       
  1510     const TDesC& aTid,
       
  1511     TInt& aOpId,
       
  1512     TImpsServRequest& aRequestType,
       
  1513     TImpsMessageType& aReqMsgType )
       
  1514     {
       
  1515     // It is possible that the cancel request from client is not
       
  1516     // complete and this session entity is still waiting deletion.
       
  1517     if ( iCanceled )
       
  1518         {
       
  1519         return EFalse;
       
  1520         }
       
  1521 
       
  1522     aRequestType = EImpsServNone;
       
  1523     aReqMsgType = EImpsMessageNone;
       
  1524 
       
  1525     TDblQueIter<CRequest> requestIter( iRequestList );
       
  1526 
       
  1527     requestIter.SetToFirst();
       
  1528 
       
  1529     while ( requestIter )
       
  1530         {
       
  1531         CRequest* request = requestIter;
       
  1532         requestIter++;
       
  1533 
       
  1534 #ifndef _NO_IMPS_LOGGING_
       
  1535         CImpsClientLogger::Log( _L( "SubSession: CheckRequests subses=%d aTID=%S reg.TID=%S" ),
       
  1536                                 ( TInt )this, &aTid, &request->iTID );
       
  1537 #endif
       
  1538 
       
  1539         if ( !request->iTID.Compare( aTid ) )
       
  1540             {
       
  1541             aOpId = request->iOpId;
       
  1542             aRequestType = request->iRequestType;
       
  1543             aReqMsgType = request->iMessageType;
       
  1544             return ETrue;
       
  1545             }
       
  1546         }
       
  1547 
       
  1548     return EFalse;
       
  1549     }
       
  1550 
       
  1551 // -----------------------------------------------------------------------------
       
  1552 // CImpsSubSession::DeleteRequest
       
  1553 // -----------------------------------------------------------------------------
       
  1554 TBool CImpsSubSession::DeleteRequest( TInt aOpId )
       
  1555     {
       
  1556 #ifndef _NO_IMPS_LOGGING_
       
  1557     CImpsClientLogger::Log( _L( "SubSession: DeleteRequest opid=%d, subses=%d" ), aOpId, ( TInt )this );
       
  1558 #endif
       
  1559     // Delete one buffered requests from this client,
       
  1560     TDblQueIter<CRequest> rIter( iRequestList );
       
  1561 
       
  1562     rIter.SetToFirst();
       
  1563 
       
  1564     while ( rIter )
       
  1565         {
       
  1566         CRequest* requ = rIter;
       
  1567         rIter++;
       
  1568         if ( requ->iOpId == aOpId )
       
  1569             {
       
  1570 #ifndef _NO_IMPS_LOGGING_
       
  1571             CImpsClientLogger::Log( _L( "SubSession: DeleteRequest TID=%S" ), &( requ->iTID ) ); //lint !e525
       
  1572 #endif
       
  1573             requ->Destroy();
       
  1574             return ETrue;
       
  1575             }
       
  1576         }
       
  1577 #ifndef _NO_IMPS_LOGGING_
       
  1578     CImpsClientLogger::Log( _L( "SubSession: DeleteRequest failed" ) );
       
  1579 #endif
       
  1580     return EFalse;
       
  1581     }
       
  1582 
       
  1583 // ---------------------------------------------------------
       
  1584 // CImpsSubSession::NextEventL()
       
  1585 // ---------------------------------------------------------
       
  1586 void CImpsSubSession::NextEventL( const RMessage2& aMsg )
       
  1587     {
       
  1588 #ifndef _NO_IMPS_LOGGING_
       
  1589     CImpsClientLogger::Log( _L( "SubSession: NextEventL begins subses=%d" ), ( TInt )this );
       
  1590 #endif
       
  1591     if ( iCanceled )
       
  1592         {
       
  1593         User::Leave( KErrCancel );
       
  1594         }
       
  1595     StoreEventMsg( aMsg );
       
  1596     DoNextEvent();
       
  1597     }
       
  1598 
       
  1599 // ---------------------------------------------------------
       
  1600 // CImpsSubSession::SendEventBodyL()
       
  1601 // ---------------------------------------------------------
       
  1602 void CImpsSubSession::SendEventBodyL( const RMessage2& aMsg )
       
  1603     {
       
  1604 #ifndef _NO_IMPS_LOGGING_
       
  1605     CImpsClientLogger::Log( _L( "SubSession: SendEventBodyL subses=%d" ), ( TInt )this );
       
  1606 #endif
       
  1607     if ( iCanceled )
       
  1608         {
       
  1609         User::Leave( KErrCancel );
       
  1610         }
       
  1611 
       
  1612     StoreEventMsg( aMsg );
       
  1613     DoEventBodyL();
       
  1614     }
       
  1615 
       
  1616 // ---------------------------------------------------------
       
  1617 // CImpsSubSession::DoCreateEventL
       
  1618 // ---------------------------------------------------------
       
  1619 void CImpsSubSession::DoCreateEventL(
       
  1620     TInt aOpId,
       
  1621     TImpsServRequest aRequestType,
       
  1622     TImpsMessageType aReqMesType,
       
  1623     CImpsFields* aFields )
       
  1624     {
       
  1625 
       
  1626 #ifdef _DEBUG
       
  1627     TInt rate = 0;
       
  1628     if ( !rate )
       
  1629         {
       
  1630         __UHEAP_RESET;
       
  1631         }
       
  1632     else
       
  1633         {
       
  1634         __UHEAP_FAILNEXT( rate );
       
  1635         }
       
  1636 #endif
       
  1637 
       
  1638     // Create an event
       
  1639     CWvEvent* myEvent = new ( ELeave ) CWvEvent( iServiceType );
       
  1640     CleanupStack::PushL( myEvent );     // <<< myEvent
       
  1641     myEvent->iOpCode = aOpId;
       
  1642     myEvent->iStatus = aFields->Status();
       
  1643     myEvent->iRequestType = aRequestType;
       
  1644     myEvent->iMessageType = ( TImpsMessageType )aFields->MessageType();
       
  1645     myEvent->iReqMesType = aReqMesType;
       
  1646 
       
  1647     // convert CSP error code if any
       
  1648     TInt32 resstatus = aFields->ResponseStatusL();
       
  1649     if ( resstatus != KImpsStatusOk &&
       
  1650          resstatus != KErrNone )
       
  1651         {
       
  1652         myEvent->iStatus = ErrorCode( resstatus );
       
  1653         }
       
  1654 
       
  1655     TImpsMessageType msgType = ( TImpsMessageType )myEvent->iMessageType;
       
  1656 
       
  1657     // *********************************************************
       
  1658     // Handle pure client responses in different way
       
  1659     // In that case XML-formatted response needed in a client
       
  1660     if ( iServiceType == EImpsEventPresencePure )
       
  1661         {
       
  1662         if ( msgType == EImpsStatus ||
       
  1663              impsService( iVariant, TImpsMessageType( msgType ) ) == EImpsEventPresence )
       
  1664             {
       
  1665             myEvent->iMessageType = EImpsPureData;
       
  1666             msgType = EImpsPureData;
       
  1667             }
       
  1668         }
       
  1669     //*********************************************************/
       
  1670 
       
  1671     // List of responses having serialized CImpsFields
       
  1672     // Notice: Check this list if new methods in API presented
       
  1673     if ( // im client
       
  1674         msgType == EImpsNewMessage ||
       
  1675         msgType == EImpsGetBlockedListRes ||
       
  1676         msgType == EImpsSendMessageRes ||
       
  1677         msgType == EImpsDeliveryReportReq ||
       
  1678         // group client
       
  1679         msgType == EImpsJoinGroupRes ||
       
  1680         msgType == EImpsLeaveGroupRes ||
       
  1681         msgType == EImpsGroupMembersRes ||
       
  1682         msgType == EImpsGroupPropertiesRes ||
       
  1683         msgType == EImpsGroupRejectListRes ||
       
  1684         msgType == EImpsNewUsers ||
       
  1685         msgType == EImpsLeftUsers ||
       
  1686         msgType == EImpsGroupChangeNotice ||
       
  1687         // Pure data
       
  1688         msgType == EImpsPureData ||
       
  1689         // fundamental
       
  1690         impsService( iVariant, TImpsMessageType( msgType ) ) == EImpsEventCommon ||
       
  1691         // presence
       
  1692         impsService( iVariant, TImpsMessageType( msgType ) ) == EImpsEventPresence )
       
  1693         // access service has nothing to pack in responses
       
  1694         {
       
  1695         HBufC8* dataBuffer = NULL;
       
  1696         TRAPD( errx, ( dataBuffer = HBufC8::NewL( aFields->Size() ) ) );
       
  1697         if ( errx )
       
  1698             {
       
  1699             myEvent->iStatus = errx;
       
  1700             myEvent->iPackedMessage = NULL;
       
  1701             }
       
  1702         else
       
  1703             {
       
  1704             TImpsPackedEntity packed( dataBuffer );
       
  1705             // Check data length if enough
       
  1706             User::LeaveIfError ( packed.PackEntity( *aFields ) );
       
  1707             myEvent->iPackedMessage = dataBuffer;
       
  1708             }
       
  1709         }
       
  1710 
       
  1711     // detailed error data code in special format
       
  1712     // notice: avoid to pack in vain
       
  1713     if ( msgType == EImpsStatus && iDetailedError )
       
  1714         {
       
  1715         HBufC8* dataBuffer = HBufC8::NewLC( aFields->Size() );
       
  1716         TImpsPackedEntity packed( dataBuffer );
       
  1717         // Check data length if enough
       
  1718         User::LeaveIfError ( packed.PackEntity( *aFields ) );
       
  1719         myEvent->iPackedMessage = dataBuffer;
       
  1720         CleanupStack::Pop();    // dataBuffer
       
  1721         }
       
  1722 
       
  1723     // list of responses having one byte response
       
  1724     if ( aFields->MessageType() == EImpsSubsGroupNoticeRes )
       
  1725         {
       
  1726         CImpsKey* myKey = CImpsKey::NewLC();    // <<< myKey
       
  1727         CImpsDataAccessor* myAc = CImpsDataAccessor::NewL( aFields );
       
  1728         CleanupStack::PushL( myAc );            // <<< myAc
       
  1729         TBool groupNotice = TImpsSDataUtils::SubGroupNoticeResponseL(
       
  1730                                 myKey,
       
  1731                                 myAc );
       
  1732         myEvent->iAux = groupNotice;
       
  1733         CleanupStack::PopAndDestroy( 2 );   // >>> myKey, myAc
       
  1734         }
       
  1735 
       
  1736     // New event created succesfully
       
  1737     CleanupStack::Pop( 1 ); // >>> myEvent
       
  1738     // Since WV 1,2 logout messages may be either disconnect or Status,
       
  1739     // harmomize them here in order to avoid sending logout message
       
  1740     // with opid=actual_id and opid=0.
       
  1741     if ( aRequestType == EImpsServWVLogout )
       
  1742         {
       
  1743         iLastEvent = EImpsDisconnect;
       
  1744         }
       
  1745     else
       
  1746         {
       
  1747         iLastEvent = myEvent->iMessageType;
       
  1748         }
       
  1749     iEventList.AddLast( *myEvent );
       
  1750     }
       
  1751 
       
  1752 // ---------------------------------------------------------
       
  1753 // CImpsSubSession::DoCreateEventL
       
  1754 // This creates wv engine online status event
       
  1755 // ---------------------------------------------------------
       
  1756 void CImpsSubSession::DoCreateEventL(
       
  1757     EImpsInternalStatus aStatus )
       
  1758     {
       
  1759 #ifdef _DEBUG
       
  1760     TInt rate = 0;
       
  1761     if ( !rate )
       
  1762         {
       
  1763         __UHEAP_RESET;
       
  1764         }
       
  1765     else
       
  1766         {
       
  1767         __UHEAP_FAILNEXT( rate );
       
  1768         }
       
  1769 #endif
       
  1770     // Create an event
       
  1771     CWvEvent* myEvent = new ( ELeave ) CWvEvent( iServiceType );
       
  1772     // No need for CleanupStack, no leave before inserted to queue
       
  1773     myEvent->iOpCode = 0;
       
  1774     myEvent->iStatus = KErrNone;
       
  1775     myEvent->iRequestType = EImpsServStatusReg;
       
  1776     myEvent->iMessageType = EImpsMessageNone;
       
  1777     myEvent->iReqMesType = 0;
       
  1778     myEvent->iAux = aStatus;
       
  1779 
       
  1780     // New event created succesfully
       
  1781     iEventList.AddLast( *myEvent );
       
  1782 
       
  1783     // Notice: this does not update iLastEvent
       
  1784     }
       
  1785 
       
  1786 // ---------------------------------------------------------
       
  1787 // CImpSsubSession::DoCreateEventL
       
  1788 // This creates wv engine expiry events and other internal messages
       
  1789 // ---------------------------------------------------------
       
  1790 void CImpsSubSession::DoCreateEventL(
       
  1791     TInt aOpCode,
       
  1792     TInt aStatus,
       
  1793     TImpsMessageType aReqMesType,
       
  1794     TImpsMessageType aRcvMesType,
       
  1795     TImpsServRequest aReqType )
       
  1796     {
       
  1797 #ifdef _DEBUG
       
  1798     TInt rate = 0;
       
  1799     if ( !rate )
       
  1800         {
       
  1801         __UHEAP_RESET;
       
  1802         }
       
  1803     else
       
  1804         {
       
  1805         __UHEAP_FAILNEXT( rate );
       
  1806         }
       
  1807 #endif
       
  1808     // Create an event
       
  1809     CWvEvent* myEvent = new ( ELeave ) CWvEvent( iServiceType );
       
  1810     // No need for CleanupStack, no leave before inserted to queue
       
  1811     myEvent->iOpCode = aOpCode;
       
  1812     myEvent->iStatus = aStatus;
       
  1813     myEvent->iMessageType = aRcvMesType;
       
  1814     myEvent->iReqMesType = aReqMesType;
       
  1815     myEvent->iRequestType = aReqType;
       
  1816 
       
  1817     // New event created succesfully
       
  1818     iLastEvent = myEvent->iMessageType;
       
  1819     iEventList.AddLast( *myEvent );
       
  1820     }
       
  1821 
       
  1822 // ---------------------------------------------------------
       
  1823 // CImpsSubSession::DoSplitGroupChangeL
       
  1824 // ---------------------------------------------------------
       
  1825 void CImpsSubSession::DoSplitGroupChangeL(
       
  1826     TInt aOpId,
       
  1827     TImpsServRequest aRequestType,
       
  1828     CImpsFields* aFields )
       
  1829     {
       
  1830 
       
  1831     CImpsKey* myKey = CImpsKey::NewLC();    // <<< myKey
       
  1832     CImpsDataAccessor* myAc = CImpsDataAccessor::NewL( aFields );
       
  1833     CleanupStack::PushL( myAc );        // myAc
       
  1834 
       
  1835     TImpsSDataUtils::AddValuesFromArrayL(
       
  1836         myKey,
       
  1837         KTransContentElements,
       
  1838         sizeof( KTransContentElements ) /
       
  1839         sizeof( KTransContentElements[0] ) );
       
  1840     myKey->AddL( CREATEKEY( EImpsKeyGroupChangeNotice, 0 ) );
       
  1841 
       
  1842     // First get GroupId
       
  1843     TDesC* pId;  // for GroupID
       
  1844     myKey->AddL( CREATEKEY( EImpsKeyGroupID, 0 ) );
       
  1845     if ( myAc->RestoreDescL( myKey, pId ) )
       
  1846         {
       
  1847         myKey->PopL();
       
  1848         }
       
  1849     else
       
  1850         {
       
  1851         // This means illegal data from transport.
       
  1852         User::Leave( EImpsCorrupted );
       
  1853         }
       
  1854 
       
  1855     // Search if new users
       
  1856     myKey->AddL( CREATEKEY( EImpsKeyJoined, 0 ) );
       
  1857     if ( myAc->CheckBranchExistenceL( myKey ) )
       
  1858         {
       
  1859         CImpsFields* newFields = CImpsFields::NewL();
       
  1860         CleanupStack::PushL( newFields );   // <<< newFields
       
  1861 
       
  1862         // Copy message type etc important
       
  1863         newFields->SetStatus( aFields->Status( ) );
       
  1864 
       
  1865         // set special internal message type
       
  1866         newFields->SetMessageType( EImpsNewUsers );
       
  1867 
       
  1868         // Copy data, only Joined users list
       
  1869         CImpsDataAccessor* myAc2 = CImpsDataAccessor::NewLC( newFields );
       
  1870         TImpsDataUtils::CopyNewUsersL( *myAc, *myAc2 );
       
  1871 
       
  1872         // Add Group Id
       
  1873         myKey->ReplaceLastL( CREATEKEY( EImpsKeyGroupID, 0 ) );
       
  1874         myAc2->StoreDescL( myKey, *pId );
       
  1875         // Make a request entity into queue
       
  1876         DoCreateEventL( aOpId, aRequestType, EImpsMessageNone, newFields );
       
  1877 
       
  1878         CleanupStack::PopAndDestroy( 2 );   // >>> myAc2, newFields
       
  1879         }
       
  1880 
       
  1881     // Search if LeftUsers
       
  1882     myKey->ReplaceLastL( CREATEKEY( EImpsKeyLeft, 0 ) );
       
  1883     if ( myAc->CheckBranchExistenceL( myKey ) )
       
  1884         {
       
  1885         CImpsFields* newFields = CImpsFields::NewL();
       
  1886         CleanupStack::PushL( newFields );   // <<< newFields
       
  1887 
       
  1888         // Copy message type etc important
       
  1889         newFields->SetStatus( aFields->Status( ) );
       
  1890 
       
  1891         // set special internal message type
       
  1892         newFields->SetMessageType( EImpsLeftUsers );
       
  1893 
       
  1894         // Copy data, only Left users list
       
  1895         CImpsDataAccessor* myAc2 = CImpsDataAccessor::NewLC( newFields );
       
  1896         TImpsDataUtils::CopyLeftUsersL( *myAc, *myAc2 );
       
  1897 
       
  1898         // Add Group Id
       
  1899         myKey->ReplaceLastL( CREATEKEY( EImpsKeyGroupID, 0 ) );
       
  1900         myAc2->StoreDescL( myKey, *pId );
       
  1901 
       
  1902         // Make a request entity into queue
       
  1903         DoCreateEventL( aOpId, aRequestType, EImpsMessageNone, newFields );
       
  1904 
       
  1905         CleanupStack::PopAndDestroy( 2 );   // >>> myAc2, newFields
       
  1906         }
       
  1907 
       
  1908     CImpsFields* newFields = CImpsFields::NewL();
       
  1909     CleanupStack::PushL( newFields );   // <<< newFields
       
  1910 
       
  1911     // Copy message type etc important
       
  1912     newFields->SetStatus( aFields->Status( ) );
       
  1913 
       
  1914     // set special internal message type
       
  1915     newFields->SetMessageType( EImpsGroupChangeNotice );
       
  1916 
       
  1917     // Search if GroupProperties
       
  1918     CImpsDataAccessor* myAc2 = CImpsDataAccessor::NewLC( newFields );
       
  1919     myKey->ReplaceLastL( CREATEKEY( EImpsKeyGroupProperties, 0 ) );
       
  1920     if ( myAc->CheckBranchExistenceL( myKey ) )
       
  1921         {
       
  1922         TImpsDataUtils::CopyGroupPropertiesL( *myAc, *myAc2 );
       
  1923         }
       
  1924     // Search if ownproperties
       
  1925     myKey->ReplaceLastL( CREATEKEY( EImpsKeyOwnProperties, 0 ) );
       
  1926     if ( myAc->CheckBranchExistenceL( myKey ) )
       
  1927         {
       
  1928         TImpsDataUtils::CopyOwnPropertiesL( *myAc, *myAc2 );
       
  1929         }
       
  1930 
       
  1931     // Add Group Id
       
  1932     myKey->ReplaceLastL( CREATEKEY( EImpsKeyGroupID, 0 ) );
       
  1933     myAc2->StoreDescL( myKey, *pId );
       
  1934 
       
  1935     // Make a request entity into queue
       
  1936     DoCreateEventL( aOpId, aRequestType, EImpsMessageNone, newFields );
       
  1937 
       
  1938     CleanupStack::PopAndDestroy( 4 );     // >>> myAc2, newFields
       
  1939     // myKey, myAc
       
  1940     }
       
  1941 
       
  1942 // ---------------------------------------------------------
       
  1943 // CImpsSubSession::NbrEvents
       
  1944 // ---------------------------------------------------------
       
  1945 TInt CImpsSubSession::NbrEvents()
       
  1946     {
       
  1947     TDblQueIter<CWvEvent> eventIter( iEventList );
       
  1948     CWvEvent* event = NULL;
       
  1949     TInt counter = 0;
       
  1950 
       
  1951     eventIter.SetToFirst();
       
  1952     event = eventIter;
       
  1953     while ( event )
       
  1954         {
       
  1955         counter++;
       
  1956         eventIter++;
       
  1957         event = eventIter;
       
  1958         }
       
  1959 
       
  1960     return counter;
       
  1961     }
       
  1962 
       
  1963 // ---------------------------------------------------------
       
  1964 // CImpsSubSession::GetWVDataL()
       
  1965 // Generic data converter from packed data to internal data structure.
       
  1966 // ---------------------------------------------------------
       
  1967 void CImpsSubSession::GetWVDataL()
       
  1968     {
       
  1969 #ifndef _NO_IMPS_LOGGING_
       
  1970     CImpsClientLogger::Log( _L( "SubSession: GetWVDataL begins" ) );
       
  1971 #endif
       
  1972 
       
  1973     // serialized message is always in ptr0
       
  1974     HBufC8* stream = *StreamBufAddr();
       
  1975     if ( iSession->ReadBuffer8L( 0, stream ) )
       
  1976         {
       
  1977         HBufC8** stream2 = StreamBufAddr();
       
  1978         *stream2 = stream;
       
  1979         }
       
  1980     ImpsFields()->Reset();
       
  1981     TImpsPackedEntity packedMessage( *StreamBufAddr() );
       
  1982     packedMessage.UnpackEntityL( *ImpsFields() );
       
  1983 #ifndef _NO_IMPS_LOGGING_
       
  1984     CImpsClientLogger::Log( _L( "Session: GetWVDataL ends" ) );
       
  1985 #endif
       
  1986     }
       
  1987 
       
  1988 // ---------------------------------------------------------
       
  1989 // CImpsSubSession::ErrorCode
       
  1990 // ---------------------------------------------------------
       
  1991 TInt CImpsSubSession::ErrorCode( TInt aCSPError )
       
  1992     {
       
  1993 
       
  1994     if ( aCSPError >= 100 && aCSPError <= 999 )
       
  1995         {
       
  1996         // Convert the error code if valid input value
       
  1997         return KImpsGeneralError - aCSPError;
       
  1998         }
       
  1999     // This means illagel data from transport.
       
  2000     return KImpsErrorValidate;
       
  2001 
       
  2002     }
       
  2003 
       
  2004 // ---------------------------------------------------------
       
  2005 // CImpsSubSession::DoCreateEventIPC
       
  2006 // ---------------------------------------------------------
       
  2007 void CImpsSubSession::DoCreateEventIPC(
       
  2008     CWvEvent& aEvent, SImpsEventData* aData )
       
  2009     {
       
  2010     // Set pointers to the data
       
  2011     aData->iOpCode = aEvent.iOpCode;
       
  2012     aData->iMessageType = aEvent.iMessageType;
       
  2013     aData->iRequestType = ( TInt ) aEvent.iRequestType;
       
  2014     aData->iStatus = aEvent.iStatus;
       
  2015     aData->iMessageBody = EFalse;
       
  2016     aData->iReqMesType = aEvent.iReqMesType;
       
  2017     // this is not used in all cases but let's write it every time
       
  2018     aData->iAux = aEvent.iAux;
       
  2019 
       
  2020     // Make a special change for Logout SAP errors to hide the error code
       
  2021     if ( iServiceType == EImpsEventServerLogin &&
       
  2022          aEvent.iRequestType == EImpsServWVLogout &&
       
  2023          aEvent.iStatus < ( Imps_ERROR_BASE - 200 ) )
       
  2024         {
       
  2025         aData->iStatus = KErrNone;
       
  2026 #ifndef _NO_IMPS_LOGGING_
       
  2027         CImpsClientLogger::Log( _L
       
  2028                                 ( "SubSession: DoCreateEventIPC converts LOGOUT code" ) );
       
  2029 #endif
       
  2030         }
       
  2031     }
       
  2032 
       
  2033 // ---------------------------------------------------------
       
  2034 // CImpsSubSession::DoWriteEventHeaders
       
  2035 // ---------------------------------------------------------
       
  2036 TInt CImpsSubSession::DoWriteEventHeaders(
       
  2037     RMessagePtr2 aMsg, const TDes& aData )
       
  2038     {
       
  2039 
       
  2040     TInt err = KErrNone;
       
  2041 
       
  2042     TPtrC ptr( aData );
       
  2043 
       
  2044     err = aMsg.Write( 0, ptr );
       
  2045 
       
  2046     __ASSERT_DEBUG( err != KErrBadDescriptor,
       
  2047                     aMsg.Panic( KImpsPanicCategory, EImpsCorrupted ) );
       
  2048 
       
  2049 #ifndef _NO_IMPS_LOGGING_
       
  2050     SImpsEventData* eventData = ( SImpsEventData* )aData.Ptr();
       
  2051     CImpsClientLogger::Log( _L(
       
  2052                                 "SubSession: DoWriteEventHeaders opid=%d msg=0x%x status=%d err=%d subses=%d" ),
       
  2053                             eventData->iOpCode, eventData->iMessageType, eventData->iStatus, err, ( TInt )this );
       
  2054 #endif
       
  2055 
       
  2056     return err;
       
  2057     }
       
  2058 
       
  2059 // ---------------------------------------------------------
       
  2060 // CImpsSubSession::DoWriteEventBody
       
  2061 // ---------------------------------------------------------
       
  2062 TInt CImpsSubSession::DoWriteEventBody(
       
  2063     RMessagePtr2 aMsg, CWvEvent& aEvent )
       
  2064     {
       
  2065     // Write message body
       
  2066     TPtrC8 ptr8( KNullDesC8 );
       
  2067     if ( aEvent.iPackedMessage )
       
  2068         {
       
  2069         ptr8.Set( aEvent.iPackedMessage->Des() );
       
  2070         }
       
  2071     TInt mLen = aMsg.GetDesMaxLength( 1 );
       
  2072     __ASSERT_DEBUG( mLen != KErrBadDescriptor,
       
  2073                     aMsg.Panic( KImpsPanicCategory, EImpsCorrupted ) );
       
  2074     __ASSERT_DEBUG( mLen >= ptr8.Length(),
       
  2075                     aMsg.Panic( KImpsPanicCategory, EImpsCorrupted ) );
       
  2076     if ( mLen < ptr8.Length() )
       
  2077         {
       
  2078         // This is an error situation in a client side
       
  2079         return KErrBadHandle;
       
  2080         }
       
  2081 
       
  2082 #ifndef _NO_IMPS_LOGGING_
       
  2083     CImpsClientLogger::Log( _L( "SubSession: EventMsg.Write2 subses=%d" ), ( TInt )this );
       
  2084     TTime testTime1;
       
  2085     testTime1.HomeTime();
       
  2086 #endif
       
  2087 
       
  2088     TInt err = aMsg.Write( 1, ptr8 );
       
  2089     __ASSERT_DEBUG( err != KErrBadDescriptor,
       
  2090                     aMsg.Panic( KImpsPanicCategory, EImpsCorrupted ) );
       
  2091 
       
  2092 #ifndef _NO_IMPS_LOGGING_
       
  2093     CImpsClientLogger::Log( _L(
       
  2094                                 "SubSession: DoWriteEventBody opid=%d msg=0x%x status=%d err=%d" ),
       
  2095                             aEvent.iOpCode, aEvent.iMessageType, aEvent.iStatus, err );
       
  2096 #endif
       
  2097 
       
  2098     return KErrNone;
       
  2099     }
       
  2100 
       
  2101 // ---------------------------------------------------------
       
  2102 // CImpsSubSession::StoreEventMsg
       
  2103 // ---------------------------------------------------------
       
  2104 void CImpsSubSession::StoreEventMsg( RMessagePtr2 aMsg )
       
  2105     {
       
  2106 #ifndef _NO_IMPS_LOGGING_
       
  2107     RMessage2 myMsg( aMsg );
       
  2108     CImpsClientLogger::Log( _L( "SubSession: StoreEventMsg subses=%d bufSize=%d" ), ( TInt )this, myMsg.Int2() );
       
  2109 #endif
       
  2110     iEventMsg = aMsg;
       
  2111     }
       
  2112 
       
  2113 // ---------------------------------------------------------
       
  2114 // CImpsSubSession::CompleteEventMsg
       
  2115 // ---------------------------------------------------------
       
  2116 void CImpsSubSession::CompleteEventMsg( TInt aStatus )
       
  2117     {
       
  2118 #ifndef _NO_IMPS_LOGGING_
       
  2119     CImpsClientLogger::Log( _L( "SubSession: CompleteEventMsg size=%d subses=%d" ), aStatus, ( TInt )this );
       
  2120 #endif
       
  2121     if ( iEventMsg.IsNull() )
       
  2122         {
       
  2123 #ifndef _NO_IMPS_LOGGING_
       
  2124         CImpsClientLogger::Log( _L( "SubSession: CompleteEventMsg NULL MSG subses=%d" ), ( TInt )this );
       
  2125 #endif
       
  2126         return;
       
  2127         }
       
  2128     iEventMsg.Complete( aStatus );
       
  2129     }
       
  2130 
       
  2131 // ---------------------------------------------------------
       
  2132 // CImpsSubSession::EventMsgBufSize
       
  2133 // ---------------------------------------------------------
       
  2134 TInt CImpsSubSession::EventMsgBufSize( ) const
       
  2135     {
       
  2136     if ( iEventMsg.IsNull() )
       
  2137         {
       
  2138 #ifndef _NO_IMPS_LOGGING_
       
  2139         CImpsClientLogger::Log( _L( "SubSession: EventMsgBufSize NULL MSG subses=%d" ), ( TInt )this );
       
  2140 #endif
       
  2141         return 0;
       
  2142         }
       
  2143     RMessage2 myMsg( iEventMsg );
       
  2144     return myMsg.Int2();
       
  2145     }
       
  2146 
       
  2147 // ---------------------------------------------------------
       
  2148 // CImpsSubSession::ConvertStatusCode
       
  2149 // ---------------------------------------------------------
       
  2150 TInt CImpsSubSession::ConvertStatusCode( EImpsInternalStatus aStatus ) const
       
  2151     {
       
  2152     TInt newStatus = KImpsOnlineStatus;
       
  2153     if ( aStatus == EInternal_OFF_LINE )
       
  2154         {
       
  2155         // This is not supported in client API anymore, so this is an error code.
       
  2156         newStatus = KImpsOfflineStatus;
       
  2157         }
       
  2158     else if ( aStatus == EInternal_NOT_LOGGED )
       
  2159         {
       
  2160         newStatus = KImpsNotLoggedStatus;
       
  2161         }
       
  2162     else if ( aStatus == EInternal_NO_IAP )
       
  2163         {
       
  2164         newStatus = KImpsNoIapStatus;
       
  2165         }
       
  2166     else if ( aStatus == EInternal_SHUTTING_DOWN )
       
  2167         {
       
  2168         newStatus = KImpsErrorShuttingDown;
       
  2169         }
       
  2170     return newStatus;
       
  2171     }
       
  2172 
       
  2173 // ---------------------------------------------------------
       
  2174 // CImpsSubSession::CancelTrans
       
  2175 // ---------------------------------------------------------
       
  2176 TBool CImpsSubSession::CancelTrans(
       
  2177     RMessagePtr2 aMsg, TImpsSessIdent aCSP )
       
  2178     {
       
  2179     // Get operation id from client request messages
       
  2180     RMessage2 myMsg( aMsg );
       
  2181     TInt opid = myMsg.Int0();
       
  2182 #ifndef _NO_IMPS_LOGGING_
       
  2183     CImpsClientLogger::Log( _L( "SubSession: CancelTransL opid=%d subses=%d" ), opid, ( TInt )this );
       
  2184 #endif
       
  2185 
       
  2186     TBuf<KImpsMaxTID> myTid;
       
  2187 
       
  2188     // delete the request
       
  2189     // If there is no such opid then return an error code
       
  2190     TBool found( EFalse );
       
  2191     TDblQueIter<CRequest> requestIter( iRequestList );
       
  2192     requestIter.SetToFirst();
       
  2193     while ( requestIter )
       
  2194         {
       
  2195         CRequest* request = requestIter;
       
  2196         requestIter++;
       
  2197         if ( request->iOpId == opid )
       
  2198             {
       
  2199             myTid = request->iTID;
       
  2200             // entry found and deleted
       
  2201             request->Destroy();
       
  2202             found = ETrue;
       
  2203             break;
       
  2204             }
       
  2205         }
       
  2206 #ifndef _NO_IMPS_LOGGING_
       
  2207     CImpsClientLogger::Log( _L( "SubSession: CancelTransL returns %d" ), found );
       
  2208 #endif
       
  2209     if ( found )
       
  2210         {
       
  2211         // ok, the session cancels the transport and completes the request
       
  2212         Server()->CancelTrans( myTid, aCSP );
       
  2213         }
       
  2214     return found;
       
  2215     }
       
  2216 
       
  2217 // ---------------------------------------------------------
       
  2218 // CImpsSubSession::SetExpiryTime
       
  2219 // ---------------------------------------------------------
       
  2220 void CImpsSubSession::SetExpiryTime( RMessagePtr2 aMsg )
       
  2221     {
       
  2222     RMessage2 myMsg( aMsg );
       
  2223     TInt time = myMsg.Int0();
       
  2224     SetExpiryTime( time );
       
  2225     }
       
  2226 
       
  2227 // ---------------------------------------------------------
       
  2228 // CImpsSubSession::SetExpiryTime
       
  2229 // ---------------------------------------------------------
       
  2230 void CImpsSubSession::SetExpiryTime( TInt aVal )
       
  2231     {
       
  2232     if ( aVal > 0 )
       
  2233         {
       
  2234 #ifndef _NO_IMPS_LOGGING_
       
  2235         CImpsClientLogger::Log( _L( "SubSession: SetExpiryTime %d" ), aVal );
       
  2236 #endif
       
  2237         iExpiryTime = aVal;
       
  2238         Server()->SetExpiryTimer( aVal, EFalse );
       
  2239         }
       
  2240     }
       
  2241 
       
  2242 // ---------------------------------------------------------
       
  2243 // CImpsSubSession::ExpiryTime
       
  2244 // ---------------------------------------------------------
       
  2245 TInt CImpsSubSession::ExpiryTime( )
       
  2246     {
       
  2247     return iExpiryTime;
       
  2248     }
       
  2249 
       
  2250 // ---------------------------------------------------------
       
  2251 // TImpsOOMErrors::StoreOOM
       
  2252 // ---------------------------------------------------------
       
  2253 void TImpsOOMErrors::StoreOOM( TInt aOpCode )
       
  2254     {
       
  2255     // FIFO, a ring buffer
       
  2256     iOOMList[iW].SetOpId( aOpCode );
       
  2257     TInt newW = ( iW + 1 ) % KImpsMaxBuffered;
       
  2258     if ( newW != iR )
       
  2259         {
       
  2260         // overflow, don't increase the index.
       
  2261         // the last free write cell is re-used as needed
       
  2262         iW = newW;
       
  2263         }
       
  2264     }
       
  2265 
       
  2266 // ---------------------------------------------------------
       
  2267 // ImpsOOMErrors::GetOOM
       
  2268 // ---------------------------------------------------------
       
  2269 TInt TImpsOOMErrors::GetOOM()
       
  2270     {
       
  2271     if ( iR != iW )
       
  2272         {
       
  2273         iOOMList[iR].SetAsSent();
       
  2274         return iOOMList[iR].OpId();
       
  2275         }
       
  2276     else
       
  2277         {
       
  2278         return 0;
       
  2279         }
       
  2280     }
       
  2281 
       
  2282 // ---------------------------------------------------------
       
  2283 // ImpsOOMErrors::RemoveOOM
       
  2284 // ---------------------------------------------------------
       
  2285 TInt TImpsOOMErrors::RemoveOOM()
       
  2286     {
       
  2287     if ( iR != iW && iOOMList[iR].IsSent() )
       
  2288         {
       
  2289         TInt ret = iOOMList[iR].OpId();
       
  2290         iR = ( ++iR ) % KImpsMaxBuffered;
       
  2291         return ret;
       
  2292         }
       
  2293     else
       
  2294         {
       
  2295         return 0;
       
  2296         }
       
  2297     }
       
  2298 
       
  2299 // ---------------------------------------------------------
       
  2300 // ImpsOOMErrors::Exists
       
  2301 // ---------------------------------------------------------
       
  2302 TBool TImpsOOMErrors::Exists()
       
  2303     {
       
  2304     if ( iR != iW /*&& !iOOMList[iR].IsSent()*/ )
       
  2305         {
       
  2306         return ETrue;
       
  2307         }
       
  2308     else
       
  2309         {
       
  2310         return EFalse;
       
  2311         }
       
  2312     }
       
  2313 
       
  2314 // ---------------------------------------------------------
       
  2315 // TImpsOOMErrors::Reset
       
  2316 // ---------------------------------------------------------
       
  2317 void TImpsOOMErrors::Reset()
       
  2318     {
       
  2319     iR = 0;
       
  2320     iW = 0;
       
  2321     }
       
  2322 
       
  2323 // ---------------------------------------------------------
       
  2324 // TImpsOOMError::TImpsOOMError
       
  2325 // ---------------------------------------------------------
       
  2326 TImpsOOMError::TImpsOOMError()
       
  2327     {
       
  2328     iOpId = 0;
       
  2329     iSent = EFalse;
       
  2330     }
       
  2331 
       
  2332 // ---------------------------------------------------------
       
  2333 // TImpsOOMError::SetOpId
       
  2334 // ---------------------------------------------------------
       
  2335 void TImpsOOMError::SetOpId( TInt aOpId )
       
  2336     {
       
  2337     iOpId = aOpId;
       
  2338     iSent = EFalse;
       
  2339     }
       
  2340 
       
  2341 // ---------------------------------------------------------
       
  2342 // TImpsOOMError::OpId
       
  2343 // ---------------------------------------------------------
       
  2344 TInt TImpsOOMError::OpId()
       
  2345     {
       
  2346     return iOpId;
       
  2347     }
       
  2348 
       
  2349 // ---------------------------------------------------------
       
  2350 // TImpsOOMError::SetAsSent
       
  2351 // ---------------------------------------------------------
       
  2352 void TImpsOOMError::SetAsSent( )
       
  2353     {
       
  2354     iSent = ETrue;
       
  2355     }
       
  2356 
       
  2357 // ---------------------------------------------------------
       
  2358 // TImpsOOMError::IsSent
       
  2359 // ---------------------------------------------------------
       
  2360 TBool TImpsOOMError::IsSent( )
       
  2361     {
       
  2362     return iSent;
       
  2363     }
       
  2364 
       
  2365 
       
  2366 //  End of File