simpleengine/siputils/src/simplesipconnection.cpp
changeset 0 c8caa15ef882
child 12 e6a66db4e9d0
child 14 de84881f4ac3
equal deleted inserted replaced
-1:000000000000 0:c8caa15ef882
       
     1 /*
       
     2 * Copyright (c) 2006-2009 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:    sip connection
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 
       
    23 #ifdef _DEBUG
       
    24 #include <f32file.h>
       
    25 #endif
       
    26 
       
    27 #include <badesca.h>
       
    28 
       
    29 // sip api
       
    30 #include <sip.h>
       
    31 #include <sipconnection.h>
       
    32 #include <sipconnectionobserver.h>
       
    33 #include <sipresponseelements.h>
       
    34 #include <siprequestelements.h>
       
    35 #include <sipclienttransaction.h>
       
    36 #include <siprefresh.h>
       
    37 #include <sipmessageelements.h>
       
    38 #include <sipsubscribedialogassoc.h>
       
    39 #include <sipregistrationcontext.h>
       
    40 
       
    41 // sip codec api
       
    42 #include <sipfromheader.h>
       
    43 #include <siptoheader.h>
       
    44 #include <sipexpiresheader.h>
       
    45 #include <sipeventheader.h>
       
    46 #include <sipcontenttypeheader.h>
       
    47 #include <sipaddress.h>
       
    48 #include <sipstrings.h>
       
    49 #include <sipstrconsts.h>
       
    50 #include <sipextensionheader.h>
       
    51 #include <sipsubscriptionstateheader.h>
       
    52 #include <sipsupportedheader.h>
       
    53 #include <sipacceptheader.h>
       
    54 
       
    55 #include <cvimpstsettingsstore.h>
       
    56 
       
    57 // own simple
       
    58 #include "simplesipconnection.h"
       
    59 #include "simplesipconnectionobserver.h"
       
    60 #include "simplesipprofileobserver.h"
       
    61 #include "simplerefreshtimer.h"
       
    62 #include "msimpleenginerequest.h"
       
    63 #include "simpleerrors.h"
       
    64 
       
    65 #ifdef _DEBUG
       
    66 #include "simpledebugutils.h"
       
    67 #ifdef __LOCAL_MODE
       
    68 // INTERNAL TEST SUITE
       
    69 #include "simplelocalmodeutils.h"
       
    70 #endif
       
    71 #endif
       
    72 
       
    73 _LIT8 ( KSimpleWINFO, "winfo");
       
    74 _LIT8 ( KSimplePRESENCE_LOW, "presence");
       
    75 _LIT8 ( KSimpleEventlist, "eventlist");
       
    76 _LIT8 ( KSimpleId, "id");
       
    77 _LIT8 ( KSimpleAnonymous, "\"Anonymous\" <sip:anonymous@anonymous.invalid>");
       
    78 _LIT8 ( KSimpleDeactivated, "deactivated" );
       
    79 _LIT8 ( KSimpleProbation, "probation" );
       
    80 _LIT8 ( KSimpleRejected, "rejected" );
       
    81 _LIT8 ( KSimpleTimeout, "timeout" );
       
    82 _LIT8 ( KSimpleGiveup, "giveup" );
       
    83 _LIT8 ( KSimpleNoresource, "Noresource" );
       
    84 _LIT8 ( KSipPrefix, "sip:" );
       
    85 
       
    86 // ================= MEMBER FUNCTIONS =======================
       
    87 //
       
    88 
       
    89 // ----------------------------------------------------------
       
    90 // CSimpleSipConnection::CSimpleSipConnection
       
    91 // ----------------------------------------------------------
       
    92 //
       
    93 CSimpleSipConnection::CSimpleSipConnection()
       
    94 : iSip(NULL), iSipConnection(NULL), iConnectionObserver(NULL),
       
    95   iSipState( ESimpleSipInactive ),
       
    96   iRequestList(CSimpleRequest::LinkOffset()),
       
    97   iCurrentNbrSubs( 0 )
       
    98     {
       
    99     }
       
   100 
       
   101 // ----------------------------------------------------------
       
   102 // CSimpleSipConnection::~CSimpleSipConnection
       
   103 // ----------------------------------------------------------
       
   104 //
       
   105 EXPORT_C CSimpleSipConnection::~CSimpleSipConnection()
       
   106     {
       
   107 #ifdef _DEBUG
       
   108     TSimpleLogger::Log(_L("SipConnection: DESTRUCTOR this=%d" ), (TInt)this );
       
   109     iFs.Close();
       
   110 #endif
       
   111     delete iSipConnection;
       
   112     delete iProfileObserver;
       
   113     delete iConnectionObserver;
       
   114     delete iSip;
       
   115     DeleteRequests();
       
   116     DeleteRequests( CSimpleRequest::EReqReceiveIM );
       
   117     SIPStrings::Close();
       
   118     }
       
   119 
       
   120 // ----------------------------------------------------------
       
   121 // CSimpleSipConnection::NewL
       
   122 // ----------------------------------------------------------
       
   123 //
       
   124 EXPORT_C CSimpleSipConnection* CSimpleSipConnection::NewL()
       
   125     {
       
   126     CSimpleSipConnection* self = new (ELeave) CSimpleSipConnection;
       
   127     CleanupStack::PushL( self );
       
   128     self->ConstructL();
       
   129     CleanupStack::Pop( self );
       
   130     return self;
       
   131     }
       
   132 
       
   133 // ----------------------------------------------------------
       
   134 // CSimpleSipConnection::ConstructL
       
   135 // ----------------------------------------------------------
       
   136 //
       
   137 void CSimpleSipConnection::ConstructL()
       
   138     {
       
   139 #ifdef _DEBUG
       
   140     TSimpleLogger::Log(
       
   141         _L("SipConnection: ConstructL 20-01-07 this=%d" ), (TInt)this );
       
   142 #endif
       
   143     
       
   144     iConnectionObserver = CSimpleSipConnectionObserver::NewL( *this);
       
   145     SIPStrings::OpenL();
       
   146     // read static cenrep settings
       
   147     iSettings.ReadCentRepSettings();
       
   148 
       
   149 #ifdef _DEBUG
       
   150     // read ini file for debug version settings
       
   151     (void)iFs.Connect();
       
   152     TRAP_IGNORE(iSettings.ReadIniFileL( iFs ));
       
   153 #endif
       
   154     }
       
   155 
       
   156 // ----------------------------------------------------------
       
   157 // CSimpleSipConnection::DispatchReqL
       
   158 // ----------------------------------------------------------
       
   159 //
       
   160 EXPORT_C void CSimpleSipConnection::DispatchReqL( MSimpleEngineRequest& aReq )
       
   161     {
       
   162     MSimpleEngineRequest::TSimpleRequest type = aReq.RequestType();
       
   163 
       
   164 #ifdef _DEBUG
       
   165     TSimpleLogger::Log(_L("SipConnection: DispatchReqL type=%d this=%d" ),
       
   166         type, (TInt)this );
       
   167 #endif
       
   168 
       
   169     switch ( type )
       
   170         {
       
   171         case MSimpleEngineRequest::ERegister:
       
   172             aReq.SetRefreshTime( 0 );
       
   173             RegisterL( aReq );
       
   174             break;
       
   175         case MSimpleEngineRequest::ESendIM:
       
   176             aReq.SetRefreshTime( 0 );
       
   177             SendInstantMessageL( aReq );
       
   178             break;
       
   179         case MSimpleEngineRequest::EReceiveIM:
       
   180             aReq.SetRefreshTime( 0 );
       
   181             RequestInstantMessageReceivingL( aReq );
       
   182             break;
       
   183         case MSimpleEngineRequest::EStartPublish:
       
   184             aReq.SetRefreshTime( iSettings.ExpiryPuhlish() );
       
   185             StartPublishL( aReq );
       
   186             break;
       
   187         case MSimpleEngineRequest::EPublishModify:
       
   188             ModifyPublishL( aReq );
       
   189             break;
       
   190         case MSimpleEngineRequest::ESubscribe:
       
   191             aReq.SetRefreshTime( iSettings.ExpiryWatcher() );
       
   192             SubscribeL( aReq);
       
   193             break;
       
   194         case MSimpleEngineRequest::ESubscribeStop:
       
   195             aReq.SetRefreshTime( 0 );
       
   196             StopSubscribeL( aReq );
       
   197             break;
       
   198         case MSimpleEngineRequest::ESubscribeGet:
       
   199             aReq.SetRefreshTime( 0 );
       
   200             SubscribeL( aReq );
       
   201             break;
       
   202         case MSimpleEngineRequest::ESubscribeWinfo:
       
   203             aReq.SetRefreshTime( iSettings.ExpiryWinfo() );
       
   204             SubscribeWinfoL( aReq );
       
   205             break;
       
   206         case MSimpleEngineRequest::ESubscribeLista:
       
   207             aReq.SetRefreshTime( iSettings.ExpiryWatcher() );
       
   208             SubscribeListL( aReq );
       
   209             break;
       
   210         case MSimpleEngineRequest::EStopPublish:
       
   211             aReq.SetRefreshTime( 0 );
       
   212             StopPublishL( aReq );
       
   213             break;
       
   214         case MSimpleEngineRequest::EListenEvents:
       
   215             aReq.SetRefreshTime( 0 );
       
   216             ListenStatusL( aReq );
       
   217             break;
       
   218         case MSimpleEngineRequest::EDestroy:
       
   219             DeleteRequest( aReq );
       
   220             break;
       
   221         case MSimpleEngineRequest::EDestroyStart:
       
   222             DeleteRequestStart( aReq );
       
   223             break;
       
   224         default:
       
   225             User::Leave( KErrNotSupported );
       
   226             break;
       
   227         }
       
   228     }
       
   229 
       
   230 // ----------------------------------------------------------
       
   231 // CSimpleSipConnection::SIPStatus
       
   232 // ----------------------------------------------------------
       
   233 //
       
   234 EXPORT_C TUint CSimpleSipConnection::SIPStatus( 
       
   235     TInt aOpId, TInt& aRetryAfter )
       
   236     {
       
   237 #ifdef _DEBUG
       
   238     TSimpleLogger::Log(_L("SipConnection: SIPStatus this=%d" ), (TInt)this);
       
   239 #endif
       
   240     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
   241     rIter.SetToFirst();
       
   242     
       
   243     aRetryAfter = 0;
       
   244 
       
   245     while ( rIter )
       
   246         {
       
   247         CSimpleRequest* req = rIter;
       
   248         rIter++; //lint !e1757
       
   249         MSimpleEngineRequest& mr = req->Request();
       
   250         if ( mr.OpId( ) == aOpId )
       
   251             {
       
   252             aRetryAfter = req->RetryAfter();
       
   253             return req->Status();
       
   254             }
       
   255         }
       
   256     return 0;
       
   257     }
       
   258 
       
   259 // ----------------------------------------------------------
       
   260 // CSimpleSipConnection::SIPState
       
   261 // ----------------------------------------------------------
       
   262 //
       
   263 EXPORT_C TSimpleSipState CSimpleSipConnection::SIPState( )
       
   264     {
       
   265 #ifdef _DEBUG
       
   266     TSimpleLogger::Log(_L("SipConnection: SIPState returns %d this=%d" ),
       
   267         iSipState, (TInt)this );
       
   268 #endif
       
   269     return iSipState;
       
   270     }
       
   271     
       
   272 // ----------------------------------------------------------
       
   273 // CSimpleSipConnection::CurrentSIPIdentityL
       
   274 // ----------------------------------------------------------
       
   275 //
       
   276 EXPORT_C TPtrC8 CSimpleSipConnection::CurrentSIPIdentityL()
       
   277     {
       
   278     return iProfileObserver->GiveUserAorL();
       
   279     }  
       
   280     
       
   281 // ----------------------------------------------------------
       
   282 // CSimpleSipConnection::SipSubscriptionState
       
   283 // ----------------------------------------------------------
       
   284 //
       
   285 EXPORT_C MSimpleEngineRequest::TSimpleSipSubscriptionState CSimpleSipConnection::SipSubscriptionState( 
       
   286     MSimpleEngineRequest& aReq )
       
   287     {
       
   288     MSimpleEngineRequest::TSimpleSipSubscriptionState retVal = MSimpleEngineRequest::ESimpleStateNone;
       
   289     
       
   290     CSimpleRequest* r = GetCliRequest( aReq );             
       
   291     if ( r )
       
   292         {
       
   293         retVal = r->SipSubscriptionState();
       
   294         }
       
   295     else
       
   296         {        
       
   297         }
       
   298 
       
   299     return retVal;        
       
   300     }      
       
   301 
       
   302 // ----------------------------------------------------------
       
   303 // CSimpleSipConnection::RegisterL
       
   304 // ----------------------------------------------------------
       
   305 //
       
   306 void CSimpleSipConnection::RegisterL( MSimpleEngineRequest& aReq )
       
   307     {
       
   308 #ifdef _DEBUG
       
   309     TSimpleLogger::Log(_L("SipConnection: RegisterL" ));
       
   310 #endif
       
   311     // Check if already registered
       
   312     switch ( iSipState )
       
   313         {
       
   314         case ESimpleSipInactive:
       
   315             {
       
   316             if ( !aReq.Aux() )
       
   317                 {
       
   318                 // Default profile used
       
   319                 RegisterDefaultL( aReq );
       
   320                 }
       
   321             else
       
   322                 {
       
   323                 RegisterAnyL( aReq );
       
   324                 }
       
   325             }
       
   326             break;
       
   327         case ESimpleSipActive:
       
   328         case ESimpleSipSuspend:
       
   329             // The sip connection is already registered,
       
   330             // return the callback.
       
   331             aReq.Complete( KErrNone );
       
   332             break;
       
   333         case ESimpleSipIdle:
       
   334             {
       
   335             // already initiated, just wait
       
   336             // Save the request to wait a response
       
   337             CSimpleRequest* simpleR = CSimpleRequest::NewL(
       
   338                 *this, aReq, CSimpleRequest::EReqRegister, aReq.RefreshTime());
       
   339             iRequestList.AddLast( *simpleR );
       
   340             }
       
   341             break;
       
   342         case ESimpleSipUnavailable:
       
   343         default:
       
   344             User::Leave( KErrNotFound );
       
   345             break;
       
   346         }; //lint !e960
       
   347     }
       
   348 
       
   349 // ----------------------------------------------------------
       
   350 // CSimpleSipConnection::ListenStatusL
       
   351 // ----------------------------------------------------------
       
   352 //
       
   353 void CSimpleSipConnection::ListenStatusL( MSimpleEngineRequest& aReq )
       
   354     {
       
   355 #ifdef _DEBUG
       
   356     TSimpleLogger::Log(_L("SipConnection: ListenStatusL" ));
       
   357 #endif
       
   358     // Save the request to wait a response
       
   359     CSimpleRequest* simpleR = CSimpleRequest::NewL(
       
   360         *this, aReq, CSimpleRequest::EReqListenEvents, aReq.RefreshTime() );
       
   361     iRequestList.AddLast( *simpleR );
       
   362     }
       
   363 
       
   364 // ----------------------------------------------------------
       
   365 // CSimpleSipConnection::RequestInstantMessageReceivingL
       
   366 // ----------------------------------------------------------
       
   367 //
       
   368 void CSimpleSipConnection::RequestInstantMessageReceivingL(
       
   369     MSimpleEngineRequest& aReq )
       
   370     {
       
   371 #ifdef _DEBUG
       
   372     TSimpleLogger::Log( _L(
       
   373         "CSimpleSipConnection::RequestInstantMessageReceivingL - Start" ) );
       
   374 #endif
       
   375     
       
   376     // Create the request
       
   377     CSimpleRequest* request = CSimpleRequest::NewL( *this,
       
   378         aReq, CSimpleRequest::EReqReceiveIM, aReq.RefreshTime() );
       
   379     
       
   380     // Save the request into queue
       
   381     iRequestList.AddLast( *request );
       
   382     
       
   383 #ifdef _DEBUG
       
   384     TSimpleLogger::Log( _L(
       
   385         "CSimpleSipConnection::RequestInstantMessageReceivingL - End" ) );
       
   386 #endif
       
   387     }
       
   388 
       
   389 // ----------------------------------------------------------
       
   390 // CSimpleSipConnection::SendInstantMessageL
       
   391 // ----------------------------------------------------------
       
   392 //
       
   393 void CSimpleSipConnection::SendInstantMessageL( MSimpleEngineRequest& aReq )
       
   394     {
       
   395 #ifdef _DEBUG
       
   396     TSimpleLogger::Log(
       
   397         _L( "CSimpleSipConnection::SendInstantMessageL - Start" ) );
       
   398 #endif
       
   399 
       
   400     // Create the request
       
   401     CSimpleRequest* request = CSimpleRequest::NewL( *this, aReq,
       
   402         CSimpleRequest::EReqSendIM, aReq.RefreshTime() );
       
   403     CleanupStack::PushL( request );  // CS: 1
       
   404     
       
   405     request->SetDataL( aReq.RequestData() );
       
   406     request->SetRequestContentTypeL( aReq.RequestContentType() );
       
   407     request->SetRefreshTime( aReq.RefreshTime() );
       
   408     
       
   409     if ( ESimpleSipActive == iSipState )
       
   410         {
       
   411         // Set request state
       
   412         request->SetReqState( CSimpleRequest::ESimpleRunningInit );
       
   413         const TDesC8& aContent = request->Data();
       
   414         
       
   415         if ( !iSipConnection || ESimpleSipActive != iSipState ||
       
   416             !iProfileObserver )
       
   417             {
       
   418             User::Leave( KErrNotReady );
       
   419             }
       
   420         
       
   421         MSIPRegistrationContext* regContext = iProfileObserver->
       
   422             ProfileContext();
       
   423         
       
   424         if ( !regContext )
       
   425             {
       
   426             User::Leave( KErrNotReady );
       
   427             }
       
   428         
       
   429         // Check CLIENT-OBJ-DATA-LIMIT
       
   430         TUint myLimit = iSettings.ObjLimit();
       
   431 
       
   432         if ( myLimit && ( TUint )aContent.Size() > myLimit )
       
   433            {
       
   434            // This is too big mesasge, an error is returned
       
   435            User::Leave( KSimpleErrSettingsLimit );
       
   436            }
       
   437         
       
   438         // Get request URI from a request
       
   439         TUriParser8 parser;
       
   440         HBufC8* temp = HBufC8::NewLC( KSipPrefix().Length() +
       
   441             aReq.Recipient().Length() ); // CS: 2
       
   442         temp->Des().Copy( KSipPrefix() );
       
   443         temp->Des().Append( aReq.Recipient() );
       
   444         User::LeaveIfError( parser.Parse( *temp ));
       
   445         CUri8* uri = CUri8::NewL( parser );
       
   446         
       
   447         // Start to fill header, Remote URI
       
   448         CSIPRequestElements* elems = CSIPRequestElements::NewL( uri );
       
   449         CleanupStack::PushL( elems );  // CS: 3
       
   450         
       
   451         TUriParser8 parser3;
       
   452         User::LeaveIfError( parser3.Parse( iProfileObserver->
       
   453             GiveUserAorL() ));
       
   454         uri = CUri8::NewL( parser3 );
       
   455         CSIPAddress* sipAddress = CSIPAddress::NewL( uri );
       
   456         
       
   457         // From Header
       
   458         CSIPFromHeader* fromH = CSIPFromHeader::NewL( sipAddress );
       
   459         elems->SetFromHeaderL( fromH ); // fromH, ownership given to elems
       
   460         
       
   461         uri = CUri8::NewL( parser );
       
   462         CSIPAddress* addr = CSIPAddress::NewL( uri );
       
   463         // To Header
       
   464         CSIPToHeader* toHeader = CSIPToHeader::NewL( addr );
       
   465         elems->SetToHeaderL( toHeader );
       
   466         
       
   467         CSIPMessageElements& mesElems = elems->MessageElements();
       
   468         
       
   469         // Add Expires Header
       
   470         if ( aReq.RefreshTime() )
       
   471             {
       
   472             RPointerArray<CSIPHeaderBase> headers;
       
   473             CleanupClosePushL( headers );  // CS: 4
       
   474             
       
   475             CSIPExpiresHeader* exprH = new (ELeave) CSIPExpiresHeader(
       
   476                 aReq.RefreshTime() );
       
   477             CleanupStack::PushL( exprH );  // CS: 5
       
   478             User::LeaveIfError( headers.Append( exprH ) );
       
   479             CleanupStack::Pop( exprH ); // CS: 4
       
   480             
       
   481             mesElems.SetUserHeadersL( headers );
       
   482             // headers ownership given to mesElems
       
   483             CleanupStack::Pop( &headers ); // CS: 3
       
   484             }
       
   485         
       
   486         // Set content type and content
       
   487         HBufC8* buffer = aContent.AllocLC(); // CS: 4
       
   488         CSIPContentTypeHeader* contTypeH = CSIPContentTypeHeader::NewL(
       
   489             KSimpleMediaType, KSimpleMediaSubType );
       
   490         CleanupStack::Pop( buffer ); // CS: 3
       
   491         mesElems.SetContentL( buffer, contTypeH );
       
   492         // buffer ownership given to mesElems
       
   493         // contTypeH ownership given to mesElems
       
   494         
       
   495         // Set method
       
   496         elems->SetMethodL( SIPStrings::StringF( SipStrConsts::EMessage ) );
       
   497         
       
   498         CleanupStack::Pop( elems ); // CS: 2
       
   499         // Send the request transaction
       
   500         // elems, ownership given
       
   501         CSIPClientTransaction* sipTrans = iSipConnection->SendRequestL( elems,
       
   502             *regContext );
       
   503         
       
   504         // Save SIP client transaction
       
   505         request->SetTransaction( sipTrans );
       
   506         
       
   507         CleanupStack::PopAndDestroy( temp ); // CS: 1
       
   508         
       
   509         // Start refresh timer, it's used for garbage collection too.
       
   510         request->StartRefreshTimer();
       
   511         }
       
   512     else if ( iSipState == ESimpleSipSuspend )
       
   513         {
       
   514         request->SetReqState( CSimpleRequest::ESimplePendingInit );
       
   515         }
       
   516     else
       
   517         {
       
   518         User::Leave( KErrNotReady );
       
   519         }
       
   520     
       
   521     // Save the request into queue
       
   522     iRequestList.AddLast( *request );
       
   523     CleanupStack::Pop( request );  // CS: 0
       
   524     
       
   525     // Update SOURCE-THROTTLE-PUBLISH time
       
   526     if ( iSettings.Throttle() )
       
   527         {
       
   528         request->SetThrottleTime( iSettings.Throttle() );
       
   529         }
       
   530     
       
   531     // Start timer to detect infinite wait situation
       
   532     request->StartExpiryTimer( iSettings.ExpiryApi() );
       
   533     
       
   534 #ifdef _DEBUG
       
   535     TSimpleLogger::Log(
       
   536         _L( "CSimpleSipConnection::SendInstantMessageL - End" ) );
       
   537 #endif
       
   538     }
       
   539 
       
   540 // ----------------------------------------------------------
       
   541 // CSimpleSipConnection::StartPublishL
       
   542 // ----------------------------------------------------------
       
   543 //
       
   544 void CSimpleSipConnection::StartPublishL(
       
   545     MSimpleEngineRequest& aReq )
       
   546     {
       
   547 #ifdef _DEBUG
       
   548     TSimpleLogger::Log(_L("SipConnection: StartPublishL" ));
       
   549     TSimpleLogger::Dump( aReq.RequestData(), iFs, 0 );
       
   550 #endif
       
   551 
       
   552     // create the request
       
   553     CSimpleRequest* r = CSimpleRequest::NewL( *this,
       
   554         aReq, CSimpleRequest::EReqPublish, aReq.RefreshTime() );
       
   555     CleanupStack::PushL( r );
       
   556     r->SetDataL( aReq.RequestData() );
       
   557     r->SetRequestContentTypeL( aReq.RequestContentType() );
       
   558     
       
   559     // Set ETag if given
       
   560     if ( aReq.ETag().Length() )
       
   561         {
       
   562         HBufC8* etagBuf = aReq.ETag().AllocL();
       
   563         // Ownership is transferred
       
   564         r->SetETag( etagBuf );        
       
   565         }  
       
   566 
       
   567     // save refresh time
       
   568     r->SetRefreshTime( aReq.RefreshTime() );
       
   569 
       
   570     if ( iSipState == ESimpleSipActive )
       
   571         {
       
   572         // set request state
       
   573         r->SetReqState( CSimpleRequest::ESimpleRunningInit );
       
   574         // Do the SIP Publish transaction
       
   575         CSIPClientTransaction* sipTrans = DoPublishL(
       
   576             iProfileObserver->GiveUserAorL(),            
       
   577             aReq.RefreshTime(),
       
   578             r->Data(),
       
   579             r->ETag(), r->RequestContentType() );
       
   580         // Save SIP client transaction
       
   581         r->SetTransaction( sipTrans );
       
   582 
       
   583         // Start re-fresh timer, it's used for garbage collection too.
       
   584         // expires [ no refresh ]
       
   585         r->StartRefreshTimer();
       
   586         }
       
   587     else if ( iSipState == ESimpleSipSuspend )
       
   588         {
       
   589         r->SetReqState( CSimpleRequest::ESimplePendingInit );
       
   590         }
       
   591     else
       
   592         {
       
   593         User::Leave( KErrNotReady );
       
   594         }
       
   595 
       
   596     // Save the request into queue
       
   597     iRequestList.AddLast( *r );
       
   598     CleanupStack::Pop( r );
       
   599 
       
   600     // update SOURCE-THROTTLE-PUBLISH time
       
   601     if ( iSettings.Throttle() )
       
   602         {
       
   603         r->SetThrottleTime( iSettings.Throttle() );
       
   604         }
       
   605 
       
   606     // Start timer to detect infinite wait situation
       
   607     r->StartExpiryTimer( iSettings.ExpiryApi() );
       
   608     }
       
   609 
       
   610 // ----------------------------------------------------------
       
   611 // CSimpleSipConnection::ModifyPublishL
       
   612 // ----------------------------------------------------------
       
   613 //
       
   614 void CSimpleSipConnection::ModifyPublishL(
       
   615     MSimpleEngineRequest& aReq )
       
   616     {
       
   617 #ifdef _DEBUG
       
   618     TSimpleLogger::Log(_L("SipConnection: ModifyPublishL" ));
       
   619     TSimpleLogger::Dump( aReq.RequestData(), iFs, 0 );
       
   620 #endif
       
   621 
       
   622     // Get initial SIP transaction in order to get ETag value.
       
   623     CSimpleRequest* r = GetCliRequest( aReq );
       
   624     if ( !r || r->ETag().Length() == 0  )
       
   625         {
       
   626         User::Leave( KErrNotFound );
       
   627         }
       
   628 
       
   629     // Check the request state is valid
       
   630     CSimpleRequest::TSimpleReqState myState = r->ReqState();
       
   631     if ( myState != CSimpleRequest::ESimpleActive &&
       
   632          myState != CSimpleRequest::ESimplePending &&
       
   633          myState != CSimpleRequest::ESimpleRunning )
       
   634         {
       
   635         User::Leave( KErrNotReady );
       
   636         }
       
   637 
       
   638     // initialize SIP status
       
   639     r->SetStatus( 0 );
       
   640 
       
   641     // check SOURCE-THROTTLE-PUBLISH
       
   642     TTime myTime;
       
   643     myTime.HomeTime();
       
   644     if ( iSettings.Throttle() && myTime < r->ThrottleTime() )
       
   645         {
       
   646         // Leave if not enough time elapsed since last publish 
       
   647         // for this publication.
       
   648         User::Leave( KSimpleErrSettingsLimit );
       
   649         }
       
   650 
       
   651     // send PUBLISH modify transaction if network is available
       
   652     if ( iSipState == ESimpleSipActive && 
       
   653          myState != CSimpleRequest::ESimpleRunning )
       
   654         {
       
   655         // set state
       
   656         r->SetReqState( CSimpleRequest::ESimpleRunning );
       
   657         r->SetDataL( aReq.RequestData() );
       
   658         r->SetRequestContentTypeL( aReq.RequestContentType() );        
       
   659 
       
   660         CSIPClientTransaction* sipTrans = DoPublishL(
       
   661             iProfileObserver->GiveUserAorL(),            
       
   662             aReq.RefreshTime(),
       
   663             r->Data(),
       
   664             r->ETag(), r->RequestContentType() );
       
   665 
       
   666         // save latest client transaction
       
   667         r->SetTransaction( sipTrans );
       
   668 
       
   669         // Re-fresh timer is started in ok response, not yet here.
       
   670 
       
   671         // update SOURCE-THROTTLE-PUBLISH time
       
   672         if ( iSettings.Throttle() )
       
   673             {
       
   674             r->SetThrottleTime( iSettings.Throttle() );
       
   675             }
       
   676         }
       
   677     else if ( iSipState == ESimpleSipActive && 
       
   678               myState == CSimpleRequest::ESimpleRunning )
       
   679         {
       
   680         // not to send the ETag only.
       
   681         r->AddPendingState( CSimpleRequest::EPendingModify );
       
   682         r->SetDataL( aReq.RequestData() );
       
   683         }
       
   684     else if ( iSipState == ESimpleSipSuspend )
       
   685         {
       
   686         // set state
       
   687         r->SetReqState( CSimpleRequest::ESimplePending );
       
   688         // not to send the ETag only.
       
   689         r->AddPendingState( CSimpleRequest::EPendingModify );
       
   690         r->SetDataL( aReq.RequestData() );
       
   691         }
       
   692     else
       
   693         {
       
   694         // very rare situation
       
   695         User::Leave( KErrNotReady );
       
   696         }
       
   697 
       
   698     // start expiry timer to detect infinite wait situation
       
   699     r->StartExpiryTimer( iSettings.ExpiryApi() );
       
   700 
       
   701 #ifdef _DEBUG
       
   702     TBuf<100> myETag;
       
   703     myETag.Copy( r->ETag() );
       
   704     TSimpleLogger::Log(_L("SipConnection: ModifyPublishL ETag=%S" ), &myETag );
       
   705 #endif
       
   706     }
       
   707 
       
   708 // ----------------------------------------------------------
       
   709 // CSimpleSipConnection::StartToRefreshL
       
   710 // ----------------------------------------------------------
       
   711 //
       
   712 void CSimpleSipConnection::StartToRefreshL( CSimpleRequest& aReq )
       
   713     {
       
   714 #ifdef _DEBUG
       
   715     TSimpleLogger::Log(_L("SipConnection: StartToRefresh"));
       
   716 #endif
       
   717 
       
   718     // This refreshes PUBLISH request or makes garbage collection for
       
   719     // subscription without refresh.
       
   720 
       
   721     // There are two cases: normal re-publish
       
   722     // or expiration of publication
       
   723 
       
   724     if ( aReq.Match( CSimpleRequest::EReqPublish ) )
       
   725         {
       
   726         // refresh[ network ]
       
   727         // time to retry
       
   728         // expires[ no refresh ]
       
   729         // expires
       
   730         DoRefreshPublishL( aReq );
       
   731         }
       
   732     else if ( aReq.Match( CSimpleRequest::EReqSubscribe ) ||
       
   733               aReq.Match( CSimpleRequest::EReqSubscribeList ) ||
       
   734               aReq.Match( CSimpleRequest::EReqSubscribeWinfo ))
       
   735         {
       
   736         DoRefreshSubscribe( aReq );
       
   737         }
       
   738     else
       
   739         {
       
   740         // No other cases
       
   741         }
       
   742     }
       
   743 
       
   744 // ----------------------------------------------------------
       
   745 // CSimpleSipConnection::StopPublishL
       
   746 // ----------------------------------------------------------
       
   747 //
       
   748 void CSimpleSipConnection::StopPublishL(
       
   749     MSimpleEngineRequest& aReq )
       
   750     {
       
   751 #ifdef _DEBUG
       
   752     TSimpleLogger::Log(_L("SipConnection: StopPublishL" ));
       
   753 #endif
       
   754 
       
   755     CSIPClientTransaction* sipTrans = NULL;
       
   756     
       
   757     TBool stopETagScratch (EFalse);
       
   758 
       
   759     // Get SIP transaction in order to get ETag value.
       
   760     CSimpleRequest* r = GetCliRequest( aReq );
       
   761     if ( !r && aReq.ETag().Length() == 0 )
       
   762         {       
       
   763         User::Leave( KErrNotFound );
       
   764         }
       
   765     else if ( !r )
       
   766         {
       
   767         // create the request
       
   768         r = CSimpleRequest::NewL( *this,
       
   769             aReq, CSimpleRequest::EReqPublish, aReq.RefreshTime() );
       
   770         CleanupStack::PushL( r ); 
       
   771         stopETagScratch = ETrue;       
       
   772         }
       
   773         
       
   774     // Set ETag if given
       
   775     if ( aReq.ETag().Length() )
       
   776         {
       
   777         HBufC8* etagBuf = aReq.ETag().AllocL();
       
   778         // Ownership is transferred
       
   779         r->SetETag( etagBuf ); 
       
   780         r->SetGivenETag( ETrue );       
       
   781         }        
       
   782 
       
   783     // initialize SIP status
       
   784     r->SetStatus( 0 );
       
   785 
       
   786     // refresh timer not needed
       
   787     r->StopRefreshTimer();
       
   788 
       
   789     // set state
       
   790     r->SetReqState( CSimpleRequest::ESimpleStopping );
       
   791     
       
   792     // Check if the transaction is pending or running
       
   793     if ( r->ETag().Length() == 0  )
       
   794         {
       
   795         r->SetReqState( CSimpleRequest::ESimpleComplete );
       
   796         r->Complete( KErrNone );
       
   797         return;
       
   798         }
       
   799 
       
   800     // send PUBLISH transaction
       
   801     TRAPD( errx, sipTrans = DoPublishL(
       
   802         iProfileObserver->GiveUserAorL(),        
       
   803         0,  // 0 epiry headers value
       
   804         KNullDesC8,  //  request data
       
   805         r->ETag(), r->RequestContentType() ));
       
   806     if ( errx )
       
   807         {
       
   808         // In error case complete the request immediately
       
   809         r->Complete( errx );
       
   810         return;
       
   811         }
       
   812 
       
   813     // save latest client transaction
       
   814     r->SetTransaction( sipTrans );
       
   815 
       
   816     // start expiry timer to detect infinite wait situation
       
   817     r->StartExpiryTimer( iSettings.ExpiryApi() );
       
   818     
       
   819     if ( stopETagScratch )
       
   820         {
       
   821         // Save the request into queue
       
   822         iRequestList.AddLast( *r );
       
   823         CleanupStack::Pop( r );        
       
   824         }
       
   825     }
       
   826 
       
   827 // ----------------------------------------------------------
       
   828 // CSimpleSipConnection::SubscribeL
       
   829 // ----------------------------------------------------------
       
   830 //
       
   831 void CSimpleSipConnection::SubscribeL(
       
   832     MSimpleEngineRequest& aReq )
       
   833     {
       
   834 #ifdef _DEBUG
       
   835     TSimpleLogger::Log(_L("SipConnection: SubscribeL" ));
       
   836 #endif
       
   837 
       
   838     CSIPSubscribeDialogAssoc* subsDialog = NULL;
       
   839 
       
   840     // create the request
       
   841     CSimpleRequest* r = CSimpleRequest::NewL( *this,
       
   842         aReq, CSimpleRequest::EReqSubscribe, aReq.RefreshTime() );
       
   843     CleanupStack::PushL( r );
       
   844 
       
   845     if ( iSipState == ESimpleSipActive )
       
   846         {
       
   847         r->SetDataL( aReq.RequestData() );
       
   848         r->SetReqState( CSimpleRequest::ESimpleRunningInit );
       
   849         CSIPClientTransaction* sipTrans = DoSubscribeL(
       
   850             aReq.RemoteURI(),
       
   851             aReq.RefreshTime(),
       
   852             r->Data(),
       
   853             subsDialog,
       
   854             aReq.IsRefresh(),
       
   855             ESubsRegular,
       
   856             aReq.Aux() ? ETrue : EFalse );
       
   857         // save SIP Dialog and SIP client transaction
       
   858         r->SetDialog( subsDialog );
       
   859         r->SetTransaction( sipTrans );
       
   860         }
       
   861     else if ( iSipState == ESimpleSipSuspend )
       
   862         {
       
   863         r->SetReqState( CSimpleRequest::ESimplePendingInit );
       
   864         }
       
   865     else
       
   866         {
       
   867         User::Leave( KErrNotReady );
       
   868         }
       
   869 
       
   870     CleanupStack::Pop( r );
       
   871     iRequestList.AddLast( *r );
       
   872 
       
   873     // start timer to detect infinite wait situation
       
   874     r->StartExpiryTimer( iSettings.ExpiryApi() );
       
   875 
       
   876     if ( !aReq.IsRefresh() )
       
   877         {
       
   878         // Start refresh timer for garbage colletion for
       
   879         // subscription not needing refresh.
       
   880         TUint myTime = ( aReq.RefreshTime() > iSettings.ExpiryApi() ?
       
   881                          aReq.RefreshTime() : iSettings.ExpiryApi() );
       
   882         r->SetRefreshTime( myTime );
       
   883         r->StartRefreshTimer();
       
   884         }
       
   885     // increase subscription counter
       
   886     IncreaseNbrSubs();
       
   887     }
       
   888 
       
   889 // ----------------------------------------------------------
       
   890 // CSimpleSipConnection::SubscribeListL
       
   891 // ----------------------------------------------------------
       
   892 //
       
   893 void CSimpleSipConnection::SubscribeListL(
       
   894     MSimpleEngineRequest& aReq )
       
   895     {
       
   896 #ifdef _DEBUG
       
   897     TSimpleLogger::Log(_L("SipConnection: SubscribeListL" ));
       
   898 #endif
       
   899 
       
   900     CSIPSubscribeDialogAssoc* subsDialog = NULL;
       
   901 
       
   902     // create the request
       
   903     CSimpleRequest* r = CSimpleRequest::NewL( *this,
       
   904         aReq, CSimpleRequest::EReqSubscribeList, aReq.RefreshTime() );
       
   905     CleanupStack::PushL( r );
       
   906 
       
   907     if ( iSipState == ESimpleSipActive )
       
   908         {
       
   909         r->SetDataL( aReq.RequestData() );
       
   910         r->SetReqState( CSimpleRequest::ESimpleRunningInit );
       
   911         CSIPClientTransaction* sipTrans = DoSubscribeL(
       
   912             aReq.RemoteURI(),
       
   913             aReq.RefreshTime(),
       
   914             r->Data(),
       
   915             subsDialog,
       
   916             aReq.IsRefresh(),
       
   917             ESubsList,
       
   918             aReq.Aux() ? ETrue : EFalse );
       
   919         // save SIP Dialog and SIP client transaction
       
   920         r->SetDialog( subsDialog );
       
   921         r->SetTransaction( sipTrans );
       
   922         }
       
   923     else if ( iSipState == ESimpleSipUnavailable || iSipState == ESimpleSipIdle )
       
   924         {
       
   925         User::Leave( KErrNotReady );
       
   926         }
       
   927     else
       
   928         {
       
   929         r->SetReqState( CSimpleRequest::ESimplePendingInit );
       
   930         }
       
   931 
       
   932     CleanupStack::Pop( r );
       
   933     iRequestList.AddLast( *r );
       
   934 
       
   935     // Start timer to detect infinite wait situation
       
   936     r->StartExpiryTimer( iSettings.ExpiryApi() );
       
   937 
       
   938     if ( !aReq.IsRefresh() )
       
   939         {
       
   940         // Start refresh timer for garbage colletion for
       
   941         // subscription not needing refresh.
       
   942         TUint myTime = ( aReq.RefreshTime() > iSettings.ExpiryApi() ?
       
   943                         aReq.RefreshTime() : iSettings.ExpiryApi() );
       
   944         r->SetRefreshTime( myTime );
       
   945         r->StartRefreshTimer();
       
   946         }
       
   947     // increase subscription counter
       
   948     IncreaseNbrSubs();
       
   949     }
       
   950 
       
   951 // ----------------------------------------------------------
       
   952 // CSimpleSipConnection::SubscribeWinfoL
       
   953 // ----------------------------------------------------------
       
   954 //
       
   955 void CSimpleSipConnection::SubscribeWinfoL(
       
   956     MSimpleEngineRequest& aReq )
       
   957     {
       
   958 #ifdef _DEBUG
       
   959     TSimpleLogger::Log(_L("SipConnection: SubscribeWinfoL" ));
       
   960 #endif
       
   961     // get request-URI from SIP profiles
       
   962     TPtrC8 aor = iProfileObserver->GiveUserAorL();
       
   963     aReq.SetRemoteURIL( aor );
       
   964 
       
   965     CSIPSubscribeDialogAssoc* subsDialog = NULL;
       
   966 
       
   967     // create the request
       
   968     CSimpleRequest* r = CSimpleRequest::NewL( *this,
       
   969         aReq, CSimpleRequest::EReqSubscribeWinfo, aReq.RefreshTime() );
       
   970     CleanupStack::PushL( r );
       
   971 
       
   972     if ( iSipState == ESimpleSipActive )
       
   973         {
       
   974         r->SetDataL( aReq.RequestData() );
       
   975         r->SetReqState( CSimpleRequest::ESimpleRunningInit );
       
   976         CSIPClientTransaction* sipTrans = DoSubscribeL(
       
   977             aReq.RemoteURI(),
       
   978             aReq.RefreshTime(),
       
   979             r->Data(),
       
   980             subsDialog,
       
   981             ETrue,
       
   982             ESubsWinfo,
       
   983             EFalse );
       
   984         // save SIP Dialog and SIP client transaction
       
   985         r->SetDialog( subsDialog );
       
   986         r->SetTransaction( sipTrans );
       
   987         }
       
   988     else if ( iSipState == ESimpleSipUnavailable || iSipState == ESimpleSipIdle )
       
   989         {
       
   990         User::Leave( KErrNotReady );
       
   991         }
       
   992     else
       
   993         {
       
   994         r->SetReqState( CSimpleRequest::ESimplePendingInit );
       
   995         }
       
   996 
       
   997     CleanupStack::Pop( r );
       
   998     iRequestList.AddLast( *r );
       
   999 
       
  1000     // Start timer to detect infinite wait situation
       
  1001     r->StartExpiryTimer( iSettings.ExpiryApi() );
       
  1002     }
       
  1003 
       
  1004 // ----------------------------------------------------------
       
  1005 // CSimpleSipConnection::StopSubscribeL
       
  1006 // ----------------------------------------------------------
       
  1007 //
       
  1008 void CSimpleSipConnection::StopSubscribeL(
       
  1009     MSimpleEngineRequest& aReq )
       
  1010     {
       
  1011 
       
  1012 #ifdef _DEBUG
       
  1013     TSimpleLogger::Log(_L("SipConnection: StopSubscribeL" ));
       
  1014 #endif
       
  1015 
       
  1016     // Get SIP transaction
       
  1017     CSimpleRequest* r = GetCliRequest( aReq );
       
  1018     if ( !r )
       
  1019         {
       
  1020         User::Leave( KErrNotFound );
       
  1021         }
       
  1022 
       
  1023     CSIPSubscribeDialogAssoc* dialog = r->Dialog();
       
  1024     if ( !dialog )
       
  1025         {
       
  1026         User::Leave(KErrNotFound);
       
  1027         }
       
  1028 
       
  1029     if ( r->ReqState() == CSimpleRequest::ESimpleReTry ||
       
  1030          r->ReqState() == CSimpleRequest::ESimplePendingInit ||
       
  1031          r->ReqState() == CSimpleRequest::ESimplePending )
       
  1032         {
       
  1033         // There is not active SIP dialog,
       
  1034         // therefore real stopping is not needed.
       
  1035         r->SetReqState( CSimpleRequest::ESimpleStopping );
       
  1036         r->Request().SetResponseMethod( MSimpleEngineRequest::EUnknownResponse );
       
  1037         r->Complete( KErrCompletion );
       
  1038         return;
       
  1039         }
       
  1040     else if ( r->ReqState() == CSimpleRequest::ESimpleDeleting ) 
       
  1041         {
       
  1042         // there is no active subscription
       
  1043         User::Leave( KErrNotFound );
       
  1044         }
       
  1045 
       
  1046     // modify the old request entity
       
  1047     r->SetTransaction( NULL );
       
  1048 
       
  1049     // create new unsubscribe transaction in the dialog
       
  1050     // Add accepted header
       
  1051     CSIPMessageElements* mesElems = CSIPMessageElements::NewLC();
       
  1052     RPointerArray<CSIPHeaderBase> headers;
       
  1053     CleanupClosePushL( headers );
       
  1054     // Accept header with application/pidf+xml is
       
  1055     // added for reqular subscription and list subscription
       
  1056     CSIPAcceptHeader* acceH = NULL;
       
  1057     TInt popCount(0);
       
  1058 
       
  1059     if ( r->Match( CSimpleRequest::EReqSubscribe ) ||
       
  1060          r->Match( CSimpleRequest::EReqSubscribeList ))
       
  1061         {
       
  1062         acceH = CSIPAcceptHeader::NewLC(
       
  1063                 KSimpleApplicationType, KSimplePidfSubType );
       
  1064         User::LeaveIfError( headers.Append( acceH ));
       
  1065         ++popCount;
       
  1066         }
       
  1067     if ( r->Match( CSimpleRequest::EReqSubscribeList ))
       
  1068         {
       
  1069         acceH = CSIPAcceptHeader::NewLC(
       
  1070             KSimpleApplicationType, KSimpleListSubType );
       
  1071         User::LeaveIfError( headers.Append( acceH ));
       
  1072         ++popCount;
       
  1073 
       
  1074         acceH = CSIPAcceptHeader::NewLC(
       
  1075             KSimpleMultiType, KSimpleMultipartSubType );
       
  1076         User::LeaveIfError( headers.Append( acceH ));
       
  1077         ++popCount;
       
  1078 
       
  1079         // add supported header with value eventlist
       
  1080         RPointerArray<CSIPSupportedHeader> suppHs =
       
  1081             CSIPSupportedHeader::DecodeL( KSimpleEventlist);
       
  1082         for( TInt count=0; count < suppHs.Count(); count++ )
       
  1083             {
       
  1084             User::LeaveIfError( headers.Append( suppHs[count] ));
       
  1085             }
       
  1086         suppHs.Close();
       
  1087         }
       
  1088     if ( r->Match( CSimpleRequest::EReqSubscribeWinfo ))
       
  1089         {
       
  1090         acceH = CSIPAcceptHeader::NewLC(
       
  1091             KSimpleApplicationType, KSimpleWinfoSubType );
       
  1092         User::LeaveIfError( headers.Append( acceH ));
       
  1093         ++popCount;
       
  1094         }
       
  1095         
       
  1096     // ---------------------------------------------------------        
       
  1097 #ifdef _DEBUG        
       
  1098 #ifdef __LOCAL_MODE
       
  1099     /**
       
  1100      * INTERNAL TEST SUITE
       
  1101      */
       
  1102     CSimpleLocalModeUtils::AddTestHeaderL( headers );    	
       
  1103 #endif
       
  1104 #endif
       
  1105     // ---------------------------------------------------------         
       
  1106 
       
  1107     // add content
       
  1108     mesElems->SetUserHeadersL( headers );
       
  1109 
       
  1110     // Pop AccessHeaders
       
  1111     CleanupStack::Pop( popCount );
       
  1112     CleanupStack::PopAndDestroy( &headers );
       
  1113 
       
  1114     // Send SUBSCRIBE message
       
  1115     CSIPClientTransaction* sipTrans = dialog->SendUnsubscribeL( mesElems );
       
  1116     CleanupStack::Pop( mesElems );
       
  1117 
       
  1118     // save client transaction
       
  1119     r->SetTransaction( sipTrans );
       
  1120 
       
  1121     // Start timer to detect infinite wait situation
       
  1122     r->SetReqState( CSimpleRequest::ESimpleStopping );
       
  1123     r->StartExpiryTimer( iSettings.ExpiryApi() );
       
  1124     }
       
  1125 
       
  1126 // ----------------------------------------------------------
       
  1127 // CSimpleSipConnection::IncomingRequest
       
  1128 // ----------------------------------------------------------
       
  1129 //
       
  1130 void CSimpleSipConnection::IncomingRequest( TUint32 /*aIapId*/,
       
  1131                      CSIPServerTransaction* /*aTransaction*/)
       
  1132     {
       
  1133     // Nothing to do.
       
  1134 #ifdef _DEBUG
       
  1135     TSimpleLogger::Log(_L("SipConnection: IncomingRequest" ));
       
  1136 #endif
       
  1137     }
       
  1138 
       
  1139 // ----------------------------------------------------------
       
  1140 // CSimpleSipConnection::TimedOut
       
  1141 // ----------------------------------------------------------
       
  1142 //
       
  1143 void CSimpleSipConnection::TimedOut( CSIPServerTransaction& /*aTransaction*/)
       
  1144     {
       
  1145     // Nothing to do.
       
  1146 #ifdef _DEBUG
       
  1147     TSimpleLogger::Log(_L("SipConnection: TimeOut" ));
       
  1148 #endif
       
  1149     }
       
  1150 
       
  1151 // ----------------------------------------------------------
       
  1152 // CSimpleSipConnection::ConnectionStateChange
       
  1153 // ----------------------------------------------------------
       
  1154 //
       
  1155 void CSimpleSipConnection::ConnectionStateChange( 
       
  1156     TSimpleSipState aState, TInt aSipError )
       
  1157     {
       
  1158 #ifdef _DEBUG
       
  1159     TSimpleLogger::Log(_L("SipConnection: ConnectionStateChange %d->%d"),
       
  1160         iSipState, aState);
       
  1161 #endif
       
  1162 
       
  1163     // re-try to get connection
       
  1164     TSimpleSipState oldState = iSipState;
       
  1165         
       
  1166     RecognizeSipState( aState );
       
  1167     
       
  1168     // Complete status event
       
  1169     if ( oldState != iSipState )
       
  1170         {
       
  1171         CompleteStatusRequest();
       
  1172         }
       
  1173 
       
  1174     // Profile observer gives active event and then the connection can be started to create.
       
  1175     if ( oldState == ESimpleSipIdle && aState == ESimpleSipActive )
       
  1176         {
       
  1177         TRAPD( err, iSipConnection = iProfileObserver->GiveConnectionL() );
       
  1178         if ( !err )
       
  1179             {
       
  1180             SetSipState( ESimpleSipActive );
       
  1181             // complete client requests
       
  1182             CompleteRegisterRequests( KErrNone );
       
  1183             }
       
  1184         else if ( err != KErrNotReady )
       
  1185             {
       
  1186             // error callback to SimpleEngine
       
  1187             SetSipState( ESimpleSipInactive );
       
  1188             CompleteRegisterRequests( err );
       
  1189             }
       
  1190         else
       
  1191             {
       
  1192             // KErrNotReady is a normal error indicating
       
  1193             // pending initialization.
       
  1194             }
       
  1195         }
       
  1196     else if ( iSipState == ESimpleSipUnavailable )
       
  1197         {
       
  1198         iCurrentNbrSubs = 0;
       
  1199         // Complete all pending register requests with an error code
       
  1200         TInt retErr = aSipError ? aSipError : KErrDisconnected;
       
  1201         CompleteRegisterRequests( retErr );
       
  1202         // Complete all active subscriptions and publications and
       
  1203         // call API callbacks. KErrDisconnected has a special handling
       
  1204         // in CSimpleRequest::Complete().
       
  1205         CompleteRegularRequests( KErrDisconnected );
       
  1206         }
       
  1207     else if ( iSipState == ESimpleSipInactive )
       
  1208         {
       
  1209         iCurrentNbrSubs = 0;
       
  1210         // Complete all pending register requests with an error code
       
  1211         TInt retErr = aSipError ? aSipError : KErrDisconnected;
       
  1212         CompleteRegisterRequests( retErr );        
       
  1213         // All the dialogs and transactions are lost.
       
  1214         // Registeration is done automatically when state is active again.
       
  1215         // Complete all active subscriptions and publications and
       
  1216         // call API callbacks now. KErrDisconnected has a special handling
       
  1217         // in CSimpleRequest::Complete().
       
  1218         CompleteRegularRequests( KErrDisconnected );
       
  1219         }
       
  1220     else if ( iSipState == ESimpleSipSuspend )
       
  1221         {
       
  1222         // Wait till the active state
       
  1223         }
       
  1224     else if ( oldState == ESimpleSipSuspend && iSipState == ESimpleSipActive )
       
  1225         {
       
  1226         // Scan all the pending requests and start to proceed them
       
  1227         HandlePendings();
       
  1228         }
       
  1229     else
       
  1230         {
       
  1231         // nothing to do
       
  1232         }
       
  1233     }
       
  1234 
       
  1235 // ----------------------------------------------------------
       
  1236 // CSimpleSipConnection::HandleReceivedMessage
       
  1237 // ----------------------------------------------------------
       
  1238 //
       
  1239 TInt CSimpleSipConnection::HandleReceivedMessage( const TDesC8& aFrom,
       
  1240     const TDesC8& aContent )
       
  1241     {
       
  1242 #ifdef _DEBUG
       
  1243     TSimpleLogger::Log( _L("CSimpleSipConnection::HandleReceivedMessage") );
       
  1244 #endif
       
  1245     TInt error( KErrNone );
       
  1246     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1247     rIter.SetToFirst();
       
  1248     
       
  1249     while ( rIter )
       
  1250         {
       
  1251         CSimpleRequest* req = rIter;
       
  1252         rIter++; //lint !e1757
       
  1253         
       
  1254         if ( req->Match( CSimpleRequest::EReqReceiveIM ) )
       
  1255             {
       
  1256             TRAP( error, DoHandleReceivedMessageL( aFrom, aContent, *req ) )
       
  1257             }
       
  1258         }
       
  1259     
       
  1260     // KErrNoMemory is returned here if error occurred when allocating
       
  1261     // memory for heap descriptors in DoHandleReceivedMessageL
       
  1262     return error;
       
  1263     }
       
  1264 
       
  1265 // ----------------------------------------------------------
       
  1266 // CSimpleSipConnection::ConnectionChanged
       
  1267 // ----------------------------------------------------------
       
  1268 //
       
  1269 void CSimpleSipConnection::ConnectionChanged() 
       
  1270     {
       
  1271 #ifdef _DEBUG
       
  1272     TSimpleLogger::Log(_L("SipConnection: ConnectionChanged"));
       
  1273     if( iSipConnection )
       
  1274         {
       
  1275         TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : old conn state %d (internal:%d)"), iSipConnection->State(), iSipState );
       
  1276         TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : old IAP %d"),  iSipConnection->IapId() );
       
  1277         }
       
  1278 #endif
       
  1279 
       
  1280     iCurrentNbrSubs = 0;
       
  1281     CSIPConnection* conn = NULL;
       
  1282     TRAPD( err, conn = iProfileObserver->GiveConnectionL() );
       
  1283     if( !err )
       
  1284         {
       
  1285         delete iSipConnection;
       
  1286         iSipConnection = conn;
       
  1287 #ifdef _DEBUG
       
  1288         TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : new conn state %d"), iSipConnection->State() );
       
  1289         TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : new IAP %d"),  iSipConnection->IapId() );
       
  1290 #endif
       
  1291         }
       
  1292 #ifdef _DEBUG
       
  1293     else
       
  1294         {
       
  1295         TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : Get SIP connection error %d"), err );        
       
  1296         }
       
  1297 #endif
       
  1298     
       
  1299     if( iSipConnection )
       
  1300         {
       
  1301         if( iSipState != iSipConnection->State() )
       
  1302             {
       
  1303             iConnectionObserver->ConnectionStateChanged( iSipConnection->State() );
       
  1304             }
       
  1305         }
       
  1306     }
       
  1307 
       
  1308 // ----------------------------------------------------------
       
  1309 // CSimpleSipConnection::StartToCheckExpiryL
       
  1310 // ----------------------------------------------------------
       
  1311 //
       
  1312 void CSimpleSipConnection::StartToCheckExpiryL( CSimpleRequest& aReq )
       
  1313     {
       
  1314 #ifdef _DEBUG
       
  1315     TSimpleLogger::Log(_L("SipConnection: StartToCheckExpiryL"));
       
  1316 #endif
       
  1317 
       
  1318     // This is expired
       
  1319     aReq.Complete( KErrTimedOut );
       
  1320     }
       
  1321 
       
  1322 // ----------------------------------------------------------
       
  1323 // CSimpleSipConnection::GetRequest
       
  1324 // ----------------------------------------------------------
       
  1325 //
       
  1326 CSimpleRequest* CSimpleSipConnection::GetRequest(
       
  1327     CSIPClientTransaction& aTrans )
       
  1328     {
       
  1329     // Search the correspoding request element
       
  1330     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1331     rIter.SetToFirst();
       
  1332 
       
  1333     while ( rIter )
       
  1334         {
       
  1335         CSimpleRequest* req = rIter;
       
  1336         rIter++; //lint !e1757
       
  1337         if ( req->Match( aTrans ))
       
  1338             {
       
  1339             return req;
       
  1340             }
       
  1341         }
       
  1342 
       
  1343     return (CSimpleRequest*)NULL;
       
  1344     }
       
  1345 
       
  1346 // ----------------------------------------------------------
       
  1347 // CSimpleSipConnection::GetCliRequest
       
  1348 // ----------------------------------------------------------
       
  1349 //
       
  1350 CSimpleRequest* CSimpleSipConnection::GetCliRequest(
       
  1351     MSimpleEngineRequest& aReq )
       
  1352     {
       
  1353     // Search the correspoding request element
       
  1354     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1355     rIter.SetToFirst();
       
  1356 
       
  1357     while ( rIter )
       
  1358         {
       
  1359         CSimpleRequest* req = rIter;
       
  1360         rIter++; //lint !e1757
       
  1361         if ( req->Match( aReq ))
       
  1362             {
       
  1363             return req;
       
  1364             }
       
  1365         }
       
  1366 
       
  1367     return (CSimpleRequest*)NULL;
       
  1368     }
       
  1369 
       
  1370 // ----------------------------------------------------------
       
  1371 // CSimpleSipConnection::GetdDialogRequest
       
  1372 // ----------------------------------------------------------
       
  1373 //
       
  1374 CSimpleRequest* CSimpleSipConnection::GetdDialogRequest( const CSIPDialog& aDialog )
       
  1375     {
       
  1376     // Search the correspoding request element
       
  1377     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1378     rIter.SetToFirst();
       
  1379 
       
  1380     while ( rIter )
       
  1381         {
       
  1382         CSimpleRequest* req = rIter;
       
  1383         rIter++; //lint !e1757
       
  1384         if ( req->Match( aDialog ))
       
  1385             {
       
  1386             return req;
       
  1387             }
       
  1388         }
       
  1389 
       
  1390     return (CSimpleRequest*)NULL;
       
  1391     }
       
  1392 
       
  1393 // -----------------------------------------------------------------------------
       
  1394 // CSimpleSipConnection::DeleteRequests
       
  1395 // -----------------------------------------------------------------------------
       
  1396 void CSimpleSipConnection::DeleteRequests()
       
  1397     {
       
  1398 #ifdef _DEBUG
       
  1399     TSimpleLogger::Log(_L("SipConnection: DeleteRequests" ));
       
  1400 #endif
       
  1401     // Delete all buffered transaction requests
       
  1402     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1403     rIter.SetToFirst();
       
  1404 
       
  1405     while ( rIter )
       
  1406         {
       
  1407         CSimpleRequest* req = rIter;
       
  1408         rIter++; //lint !e1757
       
  1409         
       
  1410         // open request EReqReceiveIM should not be deleted
       
  1411         // will be deleted only when im message received
       
  1412         // or destructor is called.
       
  1413         if ( !req->Match( CSimpleRequest::EReqReceiveIM ) )
       
  1414             {
       
  1415             req->Destroy();
       
  1416             }
       
  1417         }
       
  1418     }
       
  1419 
       
  1420 // -----------------------------------------------------------------------------
       
  1421 // CSimpleSipConnection::DeleteRequests
       
  1422 // -----------------------------------------------------------------------------
       
  1423 void CSimpleSipConnection::DeleteRequests( 
       
  1424     CSimpleRequest::TSimpleSipReqType aRequestType )
       
  1425     {
       
  1426 #ifdef _DEBUG
       
  1427     TSimpleLogger::Log(_L("SipConnection: DeleteRequests type=%d" ),
       
  1428         aRequestType );
       
  1429 #endif
       
  1430     // Delete buffered transaction requests match to the aRequestType
       
  1431     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1432     rIter.SetToFirst();
       
  1433 
       
  1434     while ( rIter )
       
  1435         {
       
  1436         CSimpleRequest* req = rIter;
       
  1437         rIter++; //lint !e1757
       
  1438         
       
  1439         if ( req->Match( aRequestType ) )
       
  1440             {
       
  1441             req->Destroy();
       
  1442             }
       
  1443         }
       
  1444     }
       
  1445 
       
  1446 // -----------------------------------------------------------------------------
       
  1447 // CSimpleSipConnection::DeleteRequest
       
  1448 // -----------------------------------------------------------------------------
       
  1449 void CSimpleSipConnection::DeleteRequest( MSimpleEngineRequest& aReq )
       
  1450     {
       
  1451 #ifdef _DEBUG
       
  1452     TSimpleLogger::Log(_L("SipConnection: DeleteRequest" ));
       
  1453 #endif
       
  1454 
       
  1455     CSimpleRequest* r = CSimpleSipConnection::GetCliRequest( aReq );
       
  1456     if ( r )
       
  1457         {
       
  1458         if ( r->Match( CSimpleRequest::EReqSubscribe ) ||
       
  1459              r->Match( CSimpleRequest::EReqSubscribeList ) )
       
  1460             {
       
  1461             DecreaseNbrSubs();
       
  1462             }
       
  1463         r->Destroy();
       
  1464         }
       
  1465     }
       
  1466 
       
  1467 // -----------------------------------------------------------------------------
       
  1468 // CSimpleSipConnection::DeleteRequestStart
       
  1469 // -----------------------------------------------------------------------------
       
  1470 void CSimpleSipConnection::DeleteRequestStart( MSimpleEngineRequest& aReq )
       
  1471     {
       
  1472 #ifdef _DEBUG
       
  1473     TSimpleLogger::Log(_L("SipConnection: DeleteRequestStart" ));
       
  1474 #endif
       
  1475 
       
  1476     CSimpleRequest* r = CSimpleSipConnection::GetCliRequest( aReq );
       
  1477     if ( r )
       
  1478         {
       
  1479         if ( r->Match( CSimpleRequest::EReqSubscribe ) ||
       
  1480              r->Match( CSimpleRequest::EReqSubscribeList ))
       
  1481             {
       
  1482             DecreaseNbrSubs();
       
  1483             }
       
  1484         r->DestroyStart();
       
  1485         }
       
  1486     }
       
  1487 
       
  1488 // -----------------------------------------------------------------------------
       
  1489 // CSimpleSipConnection::CompleteRegisterRequests
       
  1490 // -----------------------------------------------------------------------------
       
  1491 void CSimpleSipConnection::CompleteRegisterRequests( TInt aStatus )
       
  1492     {
       
  1493 #ifdef _DEBUG
       
  1494     TSimpleLogger::Log(_L("SipConnection: CompleteRegisterRequests %d" ), aStatus);
       
  1495 #endif
       
  1496     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1497     rIter.SetToFirst();
       
  1498 
       
  1499     while ( rIter )
       
  1500         {
       
  1501         CSimpleRequest* req = rIter;
       
  1502         rIter++; //lint !e1757
       
  1503         if ( req->Match( CSimpleRequest::EReqRegister ))
       
  1504             {
       
  1505             req->Complete( aStatus );
       
  1506             // Open request can be deletetd after completion.
       
  1507             req->Destroy();
       
  1508             }
       
  1509         }
       
  1510     }
       
  1511 
       
  1512 // -----------------------------------------------------------------------------
       
  1513 // CSimpleSipConnection::CompleteRegularRequests
       
  1514 // -----------------------------------------------------------------------------
       
  1515 void CSimpleSipConnection::CompleteRegularRequests( TInt aStatus )
       
  1516     {
       
  1517 #ifdef _DEBUG
       
  1518     TSimpleLogger::Log(_L("SipConnection: CompleteRegularRequests %d" ), aStatus);
       
  1519 #endif
       
  1520     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1521     rIter.SetToFirst();
       
  1522 
       
  1523     while ( rIter )
       
  1524         {
       
  1525         CSimpleRequest* req = rIter;
       
  1526         rIter++; //lint !e1757
       
  1527         if ( req->Match( CSimpleRequest::EReqPublish ) ||
       
  1528              req->Match( CSimpleRequest::EReqSubscribe ) ||
       
  1529              req->Match( CSimpleRequest::EReqSubscribeList ) ||
       
  1530              req->Match( CSimpleRequest::EReqSubscribeWinfo ))
       
  1531             {
       
  1532             req->SetReason( KErrNone );
       
  1533             req->Request().SetResponseMethod( MSimpleEngineRequest::EUnknownResponse );
       
  1534             req->Complete( aStatus );
       
  1535             }
       
  1536         }
       
  1537     }
       
  1538 
       
  1539 // -----------------------------------------------------------------------------
       
  1540 // CSimpleSipConnection::CompleteStatusRequest
       
  1541 // -----------------------------------------------------------------------------
       
  1542 void CSimpleSipConnection::CompleteStatusRequest( )
       
  1543     {
       
  1544 #ifdef _DEBUG
       
  1545     TSimpleLogger::Log(_L("SipConnection: CompleteStatusRequest" ) );
       
  1546 #endif
       
  1547     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  1548     rIter.SetToFirst();
       
  1549 
       
  1550     while ( rIter )
       
  1551         {
       
  1552         CSimpleRequest* req = rIter;
       
  1553         rIter++; //lint !e1757
       
  1554         if ( req->Match( CSimpleRequest::EReqListenEvents ))
       
  1555             {
       
  1556             req->CompleteEvent( );
       
  1557             return;
       
  1558             }
       
  1559         }
       
  1560     }
       
  1561 
       
  1562 // ----------------------------------------------------------
       
  1563 // CSimpleSipConnection::DoPublishL
       
  1564 // ----------------------------------------------------------
       
  1565 //
       
  1566 CSIPClientTransaction* CSimpleSipConnection::DoPublishL(
       
  1567     const TDesC8& aRemoteURI, TInt aExpiry,
       
  1568     const TDesC8& aContent, const TDesC8& aSipIfMatch,
       
  1569     const TDesC8& aContentType )
       
  1570     {
       
  1571 #ifdef _DEBUG
       
  1572     TBuf<100> testBuf;
       
  1573     testBuf.Copy( aSipIfMatch );
       
  1574     TSimpleLogger::Log(_L("SipConnection: DoPublishL expiry=%d sip-if-match=%S" ),
       
  1575                        aExpiry, &testBuf);
       
  1576 #endif
       
  1577 
       
  1578     TBool multi( EFalse );
       
  1579               
       
  1580     if ( aContent.Length() && 
       
  1581          aContentType.CompareF( KSimpleDocumentType ))
       
  1582         {
       
  1583         // content exists and not pidf+xml (not refresh) 
       
  1584         multi = ETrue;            
       
  1585         }
       
  1586 
       
  1587     if ( !iSipConnection || iSipState != ESimpleSipActive || !iProfileObserver )
       
  1588         {
       
  1589         User::Leave( KErrNotReady );
       
  1590         }
       
  1591 
       
  1592     MSIPRegistrationContext* regContext = iProfileObserver->ProfileContext();
       
  1593     if ( !regContext )
       
  1594         {
       
  1595         User::Leave( KErrNotReady );
       
  1596         }
       
  1597 
       
  1598     // Check CLIENT-OBJ-DATA-LIMIT
       
  1599     TUint myLimit = iSettings.ObjLimit();
       
  1600     // Breakpoint:
       
  1601     if ( myLimit && (TUint)aContent.Size() > myLimit )
       
  1602         {
       
  1603         // This is too big mesasge, an error is returned
       
  1604         User::Leave( KSimpleErrSettingsLimit );
       
  1605         }
       
  1606 
       
  1607     // get request uri from a request
       
  1608     TUriParser8 parser;
       
  1609     User::LeaveIfError( parser.Parse( aRemoteURI ));
       
  1610     CUri8* uri = CUri8::NewLC( parser );
       
  1611 
       
  1612     // Start to fill headres,  Remote URI
       
  1613     CSIPRequestElements* elems = CSIPRequestElements::NewL(uri);
       
  1614     CleanupStack::Pop( uri); // ownership given to elems
       
  1615     CleanupStack::PushL( elems );
       
  1616     // To header not needed when remote uri set
       
  1617 
       
  1618     uri = CUri8::NewLC( parser );
       
  1619     CSIPAddress* sipAddress = CSIPAddress::NewL( uri );
       
  1620     CleanupStack::Pop( uri ); // ownership given to sipAddress
       
  1621     CleanupStack::PushL( sipAddress );
       
  1622 
       
  1623     // From header
       
  1624     CSIPFromHeader* fromH = CSIPFromHeader::NewL( sipAddress );
       
  1625     CleanupStack::Pop( sipAddress ); // ownership given to FromHeader
       
  1626     CleanupStack::PushL( fromH );
       
  1627     elems->SetFromHeaderL( fromH );
       
  1628     CleanupStack::Pop( fromH ); // fromH, ownership given to elems
       
  1629 
       
  1630     // start to add other headers
       
  1631     RPointerArray<CSIPHeaderBase> headers;
       
  1632     CleanupClosePushL(headers);
       
  1633 
       
  1634     // Expires header
       
  1635     CSIPExpiresHeader* exprH = new (ELeave) CSIPExpiresHeader(aExpiry);
       
  1636     CleanupStack::PushL( exprH );
       
  1637     User::LeaveIfError( headers.Append( exprH ));
       
  1638     CleanupStack::Pop( exprH ); // exprH
       
  1639 
       
  1640     // Event header
       
  1641     CSIPEventHeader* eventH = CSIPEventHeader::NewLC( KSimplePRESENCE_LOW );
       
  1642     User::LeaveIfError( headers.Append( eventH ));
       
  1643     CleanupStack::Pop( eventH ); // eventH
       
  1644 
       
  1645     // create SIP-ETAG header with CSIPExtensionHeader
       
  1646     if ( aSipIfMatch.Length() )
       
  1647         {
       
  1648         CSIPExtensionHeader* etagH = CSIPExtensionHeader::NewLC(
       
  1649             KSimpleSipIfMatch, aSipIfMatch );
       
  1650         User::LeaveIfError( headers.Append( etagH ));
       
  1651         CleanupStack::Pop( etagH ); // etagH
       
  1652         }
       
  1653             
       
  1654     // ---------------------------------------------------------        
       
  1655 #ifdef _DEBUG        
       
  1656 #ifdef __LOCAL_MODE
       
  1657     /**
       
  1658      * INTERNAL TEST SUITE
       
  1659      */
       
  1660     CSimpleLocalModeUtils::AddTestHeaderL( headers );    	
       
  1661 #endif
       
  1662 #endif
       
  1663       // --------------------------------------------------------- 
       
  1664 
       
  1665     CSIPMessageElements& mesElems = elems->MessageElements();
       
  1666     mesElems.SetUserHeadersL( headers );
       
  1667     CleanupStack::PopAndDestroy( &headers );
       
  1668 
       
  1669     // set Content type and content    
       
  1670       
       
  1671     CSIPContentTypeHeader* contTypeH = NULL;
       
  1672     if ( aContent.Length() ) //lint !e830
       
  1673         {
       
  1674         if ( multi )
       
  1675             {             
       
  1676             // Set CID and Boundary parameters as well
       
  1677             // ***************************************     
       
  1678             /*
       
  1679             HBufC8* contentTypeB = HBufC8::NewLC( 
       
  1680                 NSimpleDocument::NSimpleMulti::KContentTypeSize + 
       
  1681                 NSimpleDocument::KSimpleBoundarySize );    // << contentTypeB
       
  1682             TPtr8 typeAppend( contentTypeB->Des() );
       
  1683             TBuf8<10> temppi;
       
  1684             temppi.Copy( NSimpleDocument::KSimpleBoundary );
       
  1685             typeAppend.Format( NSimpleDocument::NSimpleMulti::KContentType, &temppi ); 
       
  1686             */
       
  1687             
       
  1688             TBuf8<200> temppi;
       
  1689             temppi.Copy( NSimpleDocument::NSimpleMulti::KContentTypeFullValue );
       
  1690                                                              
       
  1691             contTypeH = CSIPContentTypeHeader::DecodeL( temppi );              
       
  1692             // CleanupStack::PopAndDestroy( contentTypeB );   // >> contentTypeB         
       
  1693             CleanupStack::PushL( contTypeH );              // << contTypeH
       
  1694             }
       
  1695         else
       
  1696             {
       
  1697             contTypeH = CSIPContentTypeHeader::NewLC(
       
  1698               KSimpleApplicationType, KSimplePidfSubType );  //  // << contTypeH           
       
  1699             }    
       
  1700                                 
       
  1701         // copy content from a request parameter
       
  1702         HBufC8* buffer = aContent.AllocLC();
       
  1703         mesElems.SetContentL( buffer, contTypeH );   //  >> contTypeH
       
  1704         // buffer ownership given to mesElems
       
  1705         CleanupStack::Pop( buffer );
       
  1706         // contTypeH ownership given to mesElems
       
  1707         CleanupStack::Pop( contTypeH );
       
  1708         }
       
  1709     else
       
  1710         {
       
  1711         // No need to insert content, there wasn't any.
       
  1712         }
       
  1713 
       
  1714     // set method
       
  1715     RStringF method = SIPStrings::Pool().OpenFStringL( KSimplePUBLISH );
       
  1716     CleanupClosePushL( method );
       
  1717     elems->SetMethodL( method );
       
  1718 
       
  1719     // Send the request transaction
       
  1720     CSIPClientTransaction* sipTrans = iSipConnection->SendRequestL( elems,  *regContext );
       
  1721     // PopAndDestroy calls method.Close()
       
  1722     CleanupStack::PopAndDestroy( &method );
       
  1723     CleanupStack::Pop( elems ); // elems, ownership given
       
  1724     return sipTrans;
       
  1725     }
       
  1726 
       
  1727 // ----------------------------------------------------------
       
  1728 // CSimpleSipConnection::HandlePublishRespL
       
  1729 // ----------------------------------------------------------
       
  1730 //
       
  1731 void CSimpleSipConnection::HandlePublishRespL(
       
  1732     const CSIPMessageElements& aMesElems, CSimpleRequest* aReq )
       
  1733     {
       
  1734 #ifdef _DEBUG
       
  1735     TSimpleLogger::Log(_L("SipConnection: HandlePublishRespL" ));
       
  1736 #endif
       
  1737     TBool ETagReceived(EFalse);
       
  1738     RStringF extensionName = SIPStrings::Pool().OpenFStringL( KSimpleETag );
       
  1739     CleanupClosePushL( extensionName );
       
  1740     const RPointerArray<CSIPHeaderBase>& userHs = aMesElems.UserHeaders();
       
  1741     for ( TInt i = 0; i < userHs.Count(); i++ )
       
  1742         {
       
  1743         const CSIPHeaderBase* header = userHs[ i ];
       
  1744         if ( header->Name() == extensionName )
       
  1745             {
       
  1746             HBufC8* hValue = header->ToTextValueL();
       
  1747             // hValue ownership is transferred
       
  1748             aReq->SetETag( hValue );
       
  1749             // store etag to vimpstsettingstore
       
  1750             StoreETagL( *hValue );
       
  1751             ETagReceived = ETrue;
       
  1752             }
       
  1753         else if ( header->Name() == SIPStrings::StringF( SipStrConsts::EExpiresHeader))
       
  1754             {
       
  1755             // Save the new refresh time.
       
  1756             // Start the timer later in CSimplerequest::Complete()
       
  1757             CSIPExpiresHeader* eH = (CSIPExpiresHeader*)header;
       
  1758             TUint expires = eH->Value();
       
  1759             aReq->SetRefreshTime( expires );
       
  1760             }
       
  1761         else
       
  1762             {
       
  1763             // We igonre other than Expires and ETag headers
       
  1764             }
       
  1765         }
       
  1766     if ( !ETagReceived || !aReq->RefreshTime() )
       
  1767         {
       
  1768         // Remove old ETag if nore received or if the expires header was 0 in our request.
       
  1769         aReq->SetETag( NULL );
       
  1770         //TPtrC8 nullETag = nullETag.Alloc( KNullDesC8 ); 
       
  1771         TBufC8<1> nullETag( KNullDesC8 );
       
  1772         HBufC8* buf;
       
  1773         buf = nullETag.Alloc();
       
  1774         StoreETagL( *buf );
       
  1775         delete buf;
       
  1776         }
       
  1777     // PopAndDestroy calls extensionName.Close()
       
  1778     CleanupStack::PopAndDestroy( &extensionName );
       
  1779     }
       
  1780 
       
  1781 // ----------------------------------------------------------
       
  1782 // CSimpleSipConnection::HandleDialogRequestL
       
  1783 // ----------------------------------------------------------
       
  1784 //
       
  1785 void CSimpleSipConnection::HandleDialogRequestL( 
       
  1786     const CSIPMessageElements& aMesElems, CSimpleRequest& aReq,
       
  1787     const TDesC8& aMethod )
       
  1788     {
       
  1789 #ifdef _DEBUG
       
  1790     TBuf<20> myBuf;
       
  1791     myBuf.Copy( aMethod );
       
  1792     TSimpleLogger::Log(_L("SipConnection: HandleDialogRequestL %S" ), &myBuf);
       
  1793     CSIPRefresh* sipR = aReq.Refresh();
       
  1794     if ( sipR )
       
  1795         {
       
  1796         TSimpleLogger::Log(_L("SIPREFRESH STATE = %d" ), sipR->State() );
       
  1797         }
       
  1798 #endif
       
  1799 
       
  1800     _LIT8( KMyActive, "active");
       
  1801     _LIT8( KMyPending, "pending");
       
  1802 
       
  1803     if ( aMethod.CompareF( KSimpleNOTIFY ))
       
  1804         {
       
  1805         // Only NOTIFY is handled.
       
  1806         return;
       
  1807         }
       
  1808 
       
  1809     aReq.Request().SetResponseMethod( MSimpleEngineRequest::ENotify );
       
  1810     aReq.SetReason( KErrNone );
       
  1811 
       
  1812     // Start to search subscription-state header
       
  1813     const RPointerArray<CSIPHeaderBase>& userHs = aMesElems.UserHeaders();
       
  1814     for ( TInt i = 0; i < userHs.Count(); i++ )
       
  1815         {
       
  1816         const CSIPHeaderBase* header = userHs[ i ];
       
  1817         if ( header->Name() == SIPStrings::StringF( SipStrConsts::ESubscriptionStateHeader))
       
  1818             {
       
  1819             CSIPSubscriptionStateHeader* stateH =
       
  1820                 (CSIPSubscriptionStateHeader*)header;
       
  1821             TPtrC8 p = stateH->SubStateValue();
       
  1822 #ifdef _DEBUG
       
  1823             myBuf.Copy( p);
       
  1824             TSimpleLogger::Log(_L("SipConnection: Subscription-State = %S" ), &myBuf);
       
  1825 #endif
       
  1826             if ( !p.CompareF( KMyActive ))
       
  1827                 {
       
  1828                 // "active" Notification received
       
  1829                 aReq.ResetErrCount();
       
  1830                 aReq.Complete( KErrNone );
       
  1831                 }
       
  1832             else if ( !p.CompareF( KMyPending ))
       
  1833                 {
       
  1834                 // "pending" Notification received
       
  1835                 aReq.ResetErrCount();
       
  1836                 aReq.Complete( KSimpleErrPending );
       
  1837                 }
       
  1838             else // KMyTerminated
       
  1839                 {
       
  1840                 // "terminated"
       
  1841 
       
  1842                 aReq.PlusErrCount();
       
  1843 
       
  1844                 // Get the value of reason parameter if any exists.
       
  1845                 RStringF value;
       
  1846                 value = stateH->ParamValue( SIPStrings::StringF(
       
  1847                     SipStrConsts::EReason ));
       
  1848                 DoSetResponseReason( value.DesC(), aReq );
       
  1849 
       
  1850                 // Get retry-after parameter
       
  1851                 TInt retryAfter = stateH->RetryAfterParameter();
       
  1852                 if ( retryAfter < 0 )
       
  1853                     {
       
  1854                     retryAfter = 0;
       
  1855                     }
       
  1856                 aReq.SetRetryAfter( retryAfter );
       
  1857 
       
  1858                 // Retry in certain situations and do not send
       
  1859                 // the final error to the client yet.
       
  1860 
       
  1861                 // Detect an error loop if server always returns "terminated"
       
  1862                 // Certain errors are serious, and no reason to retry.
       
  1863                 if ( aReq.ErrCount() > 1 ||
       
  1864                      IsPermanentReason( aReq.Reason() ) ||
       
  1865                      !(aReq.Request().IsRefresh()) ||
       
  1866                      aReq.ReqState() != CSimpleRequest::ESimpleActiveSubs )
       
  1867                     {
       
  1868                     // Complete the client request.
       
  1869                     // KErrCompletion has a special handling in a client observer.
       
  1870                     // Set the reason code too.
       
  1871                     DoSetResponseReason2( aReq.Reason(), aReq.Request() );
       
  1872                     aReq.Complete( KErrCompletion );
       
  1873                     }
       
  1874                 else // ESimpleActiveSubs, no fatal error
       
  1875                     {
       
  1876                     // terminated[ refresh ]
       
  1877                     // Retry later
       
  1878                     // Notice that permanent reason is handled above
       
  1879                     // also for ESimpleActiveSubs
       
  1880                     //
       
  1881                     DoSetResponseReason2( aReq.Reason(), aReq.Request() );
       
  1882                     // CSimpleRequest::Complete handles this case even when re-tried
       
  1883                     // without API callback..
       
  1884                     aReq.Complete( KSimpleErrTemporary );
       
  1885                     }
       
  1886                 }
       
  1887             // No need to scan rest of the SIP headers
       
  1888             return;
       
  1889             }
       
  1890         }
       
  1891     }
       
  1892 
       
  1893 // ----------------------------------------------------------
       
  1894 // CSimpleSipConnection::DoSubscribeL
       
  1895 // ----------------------------------------------------------
       
  1896 //
       
  1897 CSIPClientTransaction* CSimpleSipConnection::DoSubscribeL(
       
  1898     const TDesC8& aRemoteURI, TInt aExpiry,
       
  1899     const TDesC8& aContent,
       
  1900     CSIPSubscribeDialogAssoc*& aSubsDialog,
       
  1901     TBool aRefresh,
       
  1902     TSimpleSubsType aType,
       
  1903     TBool aAnonymous )
       
  1904     {
       
  1905 #ifdef _DEBUG
       
  1906     TSimpleLogger::Log(_L("SipConnection: DoSubscribeL expiry=%d" ), aExpiry);
       
  1907 #endif
       
  1908 
       
  1909     // array grow granularity
       
  1910     const TInt KMyGran = 10; 
       
  1911 
       
  1912     if ( !iSipConnection || iSipState != ESimpleSipActive )
       
  1913         {
       
  1914 #ifdef _DEBUG
       
  1915         TSimpleLogger::Log(_L("SipConnection: DoSubscribeL LEAVES **" ));
       
  1916 #endif
       
  1917         User::Leave( KErrNotReady );
       
  1918         }
       
  1919 
       
  1920     TUint myLimit = iSettings.MaxSubscriptions();
       
  1921     // Breakpoint:
       
  1922     if ( myLimit && iCurrentNbrSubs >= myLimit && aType != ESubsWinfo )
       
  1923         {
       
  1924         User::Leave( KSimpleErrSettingsLimit );
       
  1925         }
       
  1926 
       
  1927     // get request (remote) uri from a request
       
  1928     TUriParser8 parser;
       
  1929     User::LeaveIfError( parser.Parse( aRemoteURI ));
       
  1930     CUri8* uri = CUri8::NewLC( parser );
       
  1931 
       
  1932     // Event header
       
  1933     CSIPEventHeader* eventH = NULL;
       
  1934     if ( aType == ESubsRegular || aType == ESubsList )
       
  1935         {
       
  1936         eventH = CSIPEventHeader::NewLC( KSimplePRESENCE_LOW );
       
  1937         }
       
  1938     else // if ( aType == ESubsWinfo )
       
  1939         {
       
  1940         eventH = CSIPEventHeader::NewLC( KSimplePRESENCE_LOW );
       
  1941         CDesC8ArrayFlat* flat =  new (ELeave) CDesC8ArrayFlat( KMyGran );
       
  1942         CleanupStack::PushL( flat );
       
  1943         flat->AppendL( KSimpleWINFO );
       
  1944         eventH->SetEventTemplatesL( *flat );
       
  1945         CleanupStack::PopAndDestroy( flat );
       
  1946         }
       
  1947 
       
  1948     // From header
       
  1949     // Create is if anonymous request, otherwise use SIP Profile AOR
       
  1950     CSIPFromHeader* fromH  = NULL;
       
  1951 
       
  1952     if ( aAnonymous )
       
  1953         {
       
  1954         // Generate From header
       
  1955         fromH = CSIPFromHeader::DecodeL( KSimpleAnonymous );
       
  1956         }
       
  1957     CleanupStack::PushL( fromH );
       
  1958 
       
  1959     // Subscribe Dialog
       
  1960     CSIPSubscribeDialogAssoc* sda = CSIPSubscribeDialogAssoc::NewL(
       
  1961         *iSipConnection, uri, *iProfileObserver->ProfileContext(),
       
  1962         eventH, fromH );
       
  1963 
       
  1964     CleanupStack::Pop( fromH );
       
  1965     CleanupStack::Pop( eventH );
       
  1966     CleanupStack::Pop( uri );
       
  1967     CleanupStack::PushL( sda );
       
  1968 
       
  1969     // start to add other headers
       
  1970     CSIPMessageElements* mesElems = CSIPMessageElements::NewLC();
       
  1971     RPointerArray<CSIPHeaderBase> headers;
       
  1972     CleanupClosePushL( headers );
       
  1973 
       
  1974     // Expires header
       
  1975     CSIPExpiresHeader* exprH = new (ELeave) CSIPExpiresHeader(aExpiry);
       
  1976     CleanupStack::PushL( exprH );
       
  1977     User::LeaveIfError( headers.Append( exprH ));
       
  1978 
       
  1979     // Accept header with application/pidf+xml is
       
  1980     // added for reqular subscription and list subscription
       
  1981     CSIPAcceptHeader* acceH = NULL;
       
  1982     if ( aType != ESubsWinfo )
       
  1983         {
       
  1984         acceH = CSIPAcceptHeader::NewLC(
       
  1985             KSimpleApplicationType, KSimplePidfSubType );
       
  1986         User::LeaveIfError( headers.Append( acceH ));
       
  1987         
       
  1988         // notice: allow multipart/related always!
       
  1989         acceH = CSIPAcceptHeader::NewLC(
       
  1990             KSimpleMultiType, KSimpleMultipartSubType );
       
  1991         User::LeaveIfError( headers.Append( acceH ));        
       
  1992         }
       
  1993 
       
  1994     if ( aType == ESubsList )
       
  1995         {
       
  1996         acceH = CSIPAcceptHeader::NewLC(
       
  1997             KSimpleApplicationType, KSimpleListSubType );
       
  1998         User::LeaveIfError( headers.Append( acceH ));
       
  1999 
       
  2000         // add supported header with value eventlist
       
  2001         RPointerArray<CSIPSupportedHeader> suppHs =
       
  2002             CSIPSupportedHeader::DecodeL( KSimpleEventlist);
       
  2003         for( TInt count=0; count < suppHs.Count(); count++ )
       
  2004             {
       
  2005             User::LeaveIfError( headers.Append( suppHs[count] ));
       
  2006             }
       
  2007         suppHs.Close();
       
  2008         }
       
  2009 
       
  2010     if ( aType == ESubsWinfo )
       
  2011         {
       
  2012         acceH = CSIPAcceptHeader::NewLC(
       
  2013             KSimpleApplicationType, KSimpleWinfoSubType );
       
  2014         User::LeaveIfError( headers.Append( acceH ));
       
  2015         }
       
  2016 
       
  2017     // For anonymous request add Privacy and P-Preferred-Identity headers
       
  2018     CSIPExtensionHeader* privacyH = NULL;
       
  2019     CSIPExtensionHeader* pPIH = NULL;
       
  2020     HBufC8* myBuffer = NULL;
       
  2021     if ( aAnonymous )
       
  2022         {
       
  2023         privacyH = CSIPExtensionHeader::NewLC(
       
  2024             KSimplePrivacy, KSimpleId );
       
  2025         User::LeaveIfError( headers.Append( privacyH ));
       
  2026         TInt aorLength = iProfileObserver->GiveUserAorL().Length();
       
  2027         myBuffer = HBufC8::NewLC( aorLength + 2 ); // room for brackets
       
  2028         *myBuffer = _L8("<");
       
  2029         myBuffer->Des().Append( iProfileObserver->GiveUserAorL() );
       
  2030         myBuffer->Des().Append( _L8(">"));
       
  2031         pPIH = CSIPExtensionHeader::NewLC(
       
  2032             KSimplePIdentity, myBuffer->Des() );
       
  2033         User::LeaveIfError( headers.Append( pPIH ));
       
  2034         }
       
  2035         
       
  2036     // ---------------------------------------------------------        
       
  2037 
       
  2038 #ifdef _DEBUG        
       
  2039 #ifdef __LOCAL_MODE 
       
  2040     /**
       
  2041      * INTERNAL TEST SUITE
       
  2042      */
       
  2043     CSimpleLocalModeUtils::AddTestHeaderL(headers);   
       
  2044 #endif
       
  2045 #endif  
       
  2046       // ---------------------------------------------------------         
       
  2047 
       
  2048     // add content and create refresh entity
       
  2049     mesElems->SetUserHeadersL( headers );
       
  2050     // ownership of elements is given to mesElems
       
  2051     if ( aAnonymous )
       
  2052         {
       
  2053         CleanupStack::Pop( pPIH );
       
  2054         CleanupStack::PopAndDestroy( myBuffer );
       
  2055         CleanupStack::Pop( privacyH );
       
  2056         }
       
  2057     if ( aType == ESubsList )
       
  2058         {
       
  2059         CleanupStack::Pop( 3 ); //  3 * acceH
       
  2060         }
       
  2061     else if ( aType == ESubsRegular )
       
  2062         {
       
  2063         CleanupStack::Pop( 2 ); //  2 * acceH
       
  2064         }
       
  2065     else // ESubsWinfo
       
  2066         {
       
  2067         CleanupStack::Pop( 1 ); //  1 * acceH
       
  2068         }
       
  2069     CleanupStack::Pop( exprH );
       
  2070     CleanupStack::PopAndDestroy( &headers );
       
  2071 
       
  2072     // set Content type and content
       
  2073     if ( aContent.Length() )
       
  2074         {
       
  2075         CSIPContentTypeHeader* contTypeH = CSIPContentTypeHeader::NewLC(
       
  2076           KSimpleApplicationType, KSimpleSubscribeSubType );
       
  2077         // copy content from a request parameter
       
  2078         HBufC8* buffer = aContent.AllocLC();
       
  2079         mesElems->SetContentL( buffer, contTypeH );
       
  2080         // buffer ownership given to mesElems
       
  2081         CleanupStack::Pop( buffer );
       
  2082         // contTypeH ownership given to mesElems
       
  2083         CleanupStack::Pop( contTypeH );
       
  2084         }
       
  2085                 
       
  2086     CSIPRefresh* refresh = NULL;
       
  2087     if ( aExpiry && aRefresh )
       
  2088         {
       
  2089         refresh = CSIPRefresh::NewLC();
       
  2090         }
       
  2091     // Refresh gets its value from expires header.
       
  2092     CSIPClientTransaction* sipTrans = sda->SendSubscribeL( mesElems, refresh );
       
  2093     if ( refresh )
       
  2094         {
       
  2095         CleanupStack::Pop( refresh );
       
  2096         }
       
  2097     CleanupStack::Pop( mesElems );
       
  2098     // CSIPSubscribeDialogAssoc must not be deleted until it is ubsubscribed
       
  2099     CleanupStack::Pop( sda );
       
  2100     aSubsDialog = sda;
       
  2101 
       
  2102     return sipTrans;
       
  2103     }
       
  2104 
       
  2105 // ----------------------------------------------------------
       
  2106 // CSimpleSipConnection::RegisterDefaultL
       
  2107 // ----------------------------------------------------------
       
  2108 //
       
  2109 void CSimpleSipConnection::RegisterDefaultL( MSimpleEngineRequest& aReq )
       
  2110     {
       
  2111 #ifdef _DEBUG
       
  2112     TSimpleLogger::Log(_L("SipConnection: RegisterDefaultL" ));
       
  2113 #endif
       
  2114     iProfileObserver->RegisterDefaultProfileL();
       
  2115     SetSipState( ESimpleSipIdle );
       
  2116     TRAPD( err, iSipConnection = iProfileObserver->GiveConnectionL() );
       
  2117     if ( !err )
       
  2118         {
       
  2119         SetSipState( ESimpleSipActive );
       
  2120         aReq.Complete( KErrNone );
       
  2121         }
       
  2122     else if ( err != KErrNotReady )
       
  2123         {
       
  2124         // KErrNotReady is a normal error indicating
       
  2125         // pending initialization
       
  2126         User::Leave( err );
       
  2127         }
       
  2128     else
       
  2129         {
       
  2130         // KErrNotReady situation
       
  2131         }
       
  2132     // Save the request to wait a response
       
  2133     CSimpleRequest* simpleR = CSimpleRequest::NewL(
       
  2134         *this, aReq, CSimpleRequest::EReqRegister, aReq.RefreshTime() );
       
  2135     iRequestList.AddLast( *simpleR );
       
  2136     // Start timer to detect infinite wait situation
       
  2137     simpleR->StartExpiryTimer( iSettings.ExpiryApi() );
       
  2138     }
       
  2139 
       
  2140 // ----------------------------------------------------------
       
  2141 // CSimpleSipConnection::RegisterAnyL
       
  2142 // ----------------------------------------------------------
       
  2143 //
       
  2144 void CSimpleSipConnection::RegisterAnyL( MSimpleEngineRequest& aReq )
       
  2145     {
       
  2146 #ifdef _DEBUG
       
  2147     TSimpleLogger::Log(_L("SipConnection: RegisterAnyL" ));
       
  2148 #endif
       
  2149 
       
  2150     iSettings.ReadOTASettingsL( aReq.Aux() );
       
  2151     
       
  2152     TInt32 uniqueId = iSettings.SipProfileId();
       
  2153     TUid uniqueUid;
       
  2154     uniqueUid.iUid = uniqueId;
       
  2155         
       
  2156     if ( !iSip && !iProfileObserver )
       
  2157         {        
       
  2158         iSip = CSIP::NewL( uniqueUid, *this );
       
  2159         
       
  2160         iProfileObserver = CSimpleSipProfileObserver::NewL( 
       
  2161             iSip, *iConnectionObserver);        
       
  2162         }
       
  2163     
       
  2164     iProfileObserver->RegisterGivenProfileL( iSettings.SipProfileId() );
       
  2165     SetSipState( ESimpleSipIdle );
       
  2166     TRAPD( err, iSipConnection = iProfileObserver->GiveConnectionL() );
       
  2167     if ( !err )
       
  2168         {
       
  2169         SetSipState( ESimpleSipActive );
       
  2170         aReq.Complete( KErrNone );
       
  2171         }
       
  2172     else if ( err != KErrNotReady )
       
  2173         {
       
  2174         // KErrNotReady is a normal error indicating
       
  2175         // pending initialization
       
  2176         User::Leave( err );
       
  2177         }
       
  2178     else
       
  2179         {
       
  2180         // KErrNotReady situation
       
  2181         }
       
  2182     // Save the request to wait a response
       
  2183     CSimpleRequest* simpleR = CSimpleRequest::NewL(
       
  2184         *this, aReq, CSimpleRequest::EReqRegister, aReq.RefreshTime() );
       
  2185     iRequestList.AddLast( *simpleR );
       
  2186     // Start timer to detect infinite wait situation
       
  2187     simpleR->StartExpiryTimer( iSettings.ExpiryApi() );
       
  2188     }
       
  2189 
       
  2190 // ----------------------------------------------------------
       
  2191 // CSimpleSipConnection::SetSipState
       
  2192 // ----------------------------------------------------------
       
  2193 //
       
  2194 void CSimpleSipConnection::SetSipState( TSimpleSipState aState )
       
  2195     {
       
  2196 #ifdef _DEBUG
       
  2197     TSimpleLogger::Log(_L("SipConnection: SetSipState %d this=%d" ), aState, (TInt)this );
       
  2198 #endif
       
  2199     iSipState = aState;
       
  2200     }
       
  2201 
       
  2202 // ----------------------------------------------------------
       
  2203 // CSimpleSipConnection::DoSetResponseReason
       
  2204 // ----------------------------------------------------------
       
  2205 //
       
  2206 void CSimpleSipConnection::DoSetResponseReason(
       
  2207     const TDesC8& aReason, CSimpleRequest& aR )
       
  2208     {
       
  2209     if ( aReason.Length() == 0 )
       
  2210         {
       
  2211         aR.SetReason( KErrNone );
       
  2212         }
       
  2213     else if ( !aReason.CompareF( KSimpleRejected ))
       
  2214         {
       
  2215         aR.SetReason( KSimpleErrRejected );
       
  2216         }
       
  2217     else if ( !aReason.CompareF( KSimpleTimeout ))
       
  2218         {
       
  2219         aR.SetReason( KSimpleErrTimeout );
       
  2220         }
       
  2221     else if ( !aReason.CompareF( KSimpleDeactivated ))
       
  2222         {
       
  2223         aR.SetReason( KSimpleErrDeactivated );
       
  2224         }
       
  2225     else if ( !aReason.CompareF( KSimpleProbation ))
       
  2226         {
       
  2227         aR.SetReason( KSimpleErrProbation );
       
  2228         }
       
  2229     else if ( !aReason.CompareF( KSimpleNoresource ))
       
  2230         {
       
  2231         aR.SetReason( KSimpleErrNoresource );
       
  2232         }
       
  2233     else if ( !aReason.CompareF( KSimpleGiveup ))
       
  2234         {
       
  2235         aR.SetReason( KSimpleErrGiveup);
       
  2236         }
       
  2237     else
       
  2238         {
       
  2239         aR.SetReason( KErrNone );
       
  2240         }
       
  2241     }
       
  2242 
       
  2243 // ----------------------------------------------------------
       
  2244 // CSimpleSipConnection::DoSetResponseReason2
       
  2245 // ----------------------------------------------------------
       
  2246 //
       
  2247 void CSimpleSipConnection::DoSetResponseReason2(
       
  2248     TInt aReason, MSimpleEngineRequest& aR )
       
  2249     {
       
  2250     switch ( aReason )
       
  2251         {
       
  2252         case KSimpleErrRejected:
       
  2253             aR.SetResponseReason( MSimpleEngineRequest::ERejected );
       
  2254             break;
       
  2255         case KSimpleErrTimeout:
       
  2256             aR.SetResponseReason( MSimpleEngineRequest::ETimeout );
       
  2257             break;
       
  2258         case KSimpleErrDeactivated:
       
  2259             aR.SetResponseReason( MSimpleEngineRequest::EDeactivated );
       
  2260             break;
       
  2261         case KSimpleErrProbation:
       
  2262             aR.SetResponseReason( MSimpleEngineRequest::EProbation );
       
  2263             break;
       
  2264         case KSimpleErrNoresource:
       
  2265             aR.SetResponseReason( MSimpleEngineRequest::ENoresource );
       
  2266             break;
       
  2267         case KSimpleErrGiveup:
       
  2268             aR.SetResponseReason( MSimpleEngineRequest::EGiveup );
       
  2269             break;
       
  2270         default:
       
  2271             aR.SetResponseReason( MSimpleEngineRequest::ENoReason );
       
  2272         }
       
  2273     }
       
  2274 
       
  2275 // ----------------------------------------------------------
       
  2276 // CSimpleSipConnection::IsPermanentReason
       
  2277 // ----------------------------------------------------------
       
  2278 //
       
  2279 TBool CSimpleSipConnection::IsPermanentReason( TInt aReason )
       
  2280     {
       
  2281     switch ( aReason )
       
  2282         {
       
  2283         case KSimpleErrPending:
       
  2284         case KSimpleErrDeactivated:
       
  2285         case KSimpleErrProbation:
       
  2286         case KSimpleErrTimeout:
       
  2287         case KSimpleErrGiveup:
       
  2288         case KSimpleErrTemporary:
       
  2289             return EFalse;
       
  2290         default:
       
  2291             return ETrue;
       
  2292         }
       
  2293     }
       
  2294 
       
  2295 // ----------------------------------------------------------
       
  2296 // CSimpleSipConnection::IncreaseNbrSubs
       
  2297 // ----------------------------------------------------------
       
  2298 //
       
  2299 void CSimpleSipConnection::IncreaseNbrSubs()
       
  2300     {
       
  2301     ++iCurrentNbrSubs;
       
  2302 #ifdef _DEBUG
       
  2303     TSimpleLogger::Log(_L("SipConnection: ++iCurrentNbrSubs %d" ),
       
  2304         iCurrentNbrSubs );
       
  2305 #endif
       
  2306     }
       
  2307 
       
  2308 // ----------------------------------------------------------
       
  2309 // CSimpleSipConnection::DecreaseNbrSubs
       
  2310 // ----------------------------------------------------------
       
  2311 //
       
  2312 void CSimpleSipConnection::DecreaseNbrSubs()
       
  2313     {
       
  2314     if ( iCurrentNbrSubs )
       
  2315         {
       
  2316         --iCurrentNbrSubs;
       
  2317         }
       
  2318 #ifdef _DEBUG
       
  2319     TSimpleLogger::Log(_L("SipConnection: --iCurrentNbrSubs %d" ),
       
  2320         iCurrentNbrSubs );
       
  2321 #endif
       
  2322     }
       
  2323 
       
  2324 // ----------------------------------------------------------
       
  2325 // CSimpleSipConnection::DoRefreshPublishL
       
  2326 // ----------------------------------------------------------
       
  2327 //
       
  2328 void CSimpleSipConnection::DoRefreshPublishL( CSimpleRequest& aReq )
       
  2329     {
       
  2330 #ifdef _DEBUG
       
  2331     TSimpleLogger::Log(_L("SipConnection: DoRefreshPublishL"));
       
  2332 #endif
       
  2333 
       
  2334     CSimpleRequest::TSimpleReqState orig = aReq.ReqState();
       
  2335 
       
  2336     // First, handle
       
  2337     // expires [ no refresh ]
       
  2338     if ( !aReq.Request().IsRefresh() && orig==CSimpleRequest::ESimpleActive )
       
  2339         {
       
  2340         aReq.SetStatus( 0 );
       
  2341         aReq.Complete( KErrTimedOut );
       
  2342         return;
       
  2343         }
       
  2344     if ( orig == CSimpleRequest::ESimpleRunningInit )
       
  2345         {
       
  2346         // This might happen with short expiry time when there is no response
       
  2347         // from a network.
       
  2348         aReq.SetStatus( 0 );        
       
  2349         aReq.Complete( KErrTimedOut );
       
  2350         return;
       
  2351         }
       
  2352     else if ( orig == CSimpleRequest::ESimplePending )
       
  2353         {
       
  2354         // If refresh is already once set to pending,then this publication is terminated (expired)
       
  2355         if ( aReq.PendingState() == CSimpleRequest::EPendingRefresh ||
       
  2356              aReq.PendingState() == CSimpleRequest::EPendingModifyAndRefresh )
       
  2357             {
       
  2358             // special error code that terminates the whole publication.        
       
  2359             aReq.Complete( KErrCompletion );
       
  2360             return;
       
  2361             }
       
  2362 
       
  2363         }        
       
  2364     else if ( orig != CSimpleRequest::ESimpleActive )
       
  2365         {
       
  2366         // special error code that terminates the whole publication.        
       
  2367         aReq.Complete( KErrCompletion );
       
  2368         return;
       
  2369         }
       
  2370 
       
  2371     if ( iSipState == ESimpleSipActive )
       
  2372         {       
       
  2373         // set request state
       
  2374         aReq.SetReqState( CSimpleRequest::ESimpleRunning );
       
  2375         TInt errx = DoSendPendingPublish( aReq );
       
  2376         if ( errx )
       
  2377             {
       
  2378             // Error changes the state and calls API callback when needed
       
  2379             aReq.Complete( errx );
       
  2380             }
       
  2381         else
       
  2382             {
       
  2383             // start refresh timer to detect expiry of publication
       
  2384             aReq.StartRefreshTimer( aReq.RetryExpiryTime() );
       
  2385             // Do not start expiry timer
       
  2386             }                
       
  2387         }
       
  2388     else if ( iSipState == ESimpleSipSuspend )
       
  2389         {
       
  2390         // no network available
       
  2391         // refresh [ no network ]
       
  2392         // start refresh timer to detect expiry of publication
       
  2393         aReq.StartRefreshTimer( aReq.RetryExpiryTime() );
       
  2394         // Do not start expiry timer
       
  2395         aReq.SetReqState( CSimpleRequest::ESimplePending );
       
  2396         aReq.AddPendingState( CSimpleRequest::EPendingRefresh );
       
  2397         }
       
  2398     else
       
  2399         {
       
  2400         User::Leave( KErrNotReady );
       
  2401         }
       
  2402 
       
  2403     // DO NOT update SOURCE-THROTTLE-PUBLISH time
       
  2404     }
       
  2405 
       
  2406 // ----------------------------------------------------------
       
  2407 // CSimpleSipConnection::DoRefreshSubscribe
       
  2408 // ----------------------------------------------------------
       
  2409 //
       
  2410 void CSimpleSipConnection::DoRefreshSubscribe( CSimpleRequest& aReq )
       
  2411     {
       
  2412 #ifdef _DEBUG
       
  2413     TSimpleLogger::Log(_L("SipConnection: DoRefreshSubscribe"));
       
  2414 #endif
       
  2415 
       
  2416     if ( !aReq.Request().IsRefresh() )
       
  2417         {
       
  2418 #ifdef _DEBUG
       
  2419         TSimpleLogger::Log(_L("SipConnection: Refresh EXPIRED **"));
       
  2420 #endif
       
  2421         // This is expired and no need to refresh
       
  2422         aReq.Complete( KErrTimedOut );
       
  2423         }
       
  2424 
       
  2425     aReq.StartExpiryTimer( aReq.RetryExpiryTime() );
       
  2426 
       
  2427     if ( iSipState != ESimpleSipActive )
       
  2428         {
       
  2429         if ( aReq.ReqState() == CSimpleRequest::ESimpleReTry )
       
  2430             {
       
  2431             // time to retry [ no network ]
       
  2432             aReq.SetReqState( CSimpleRequest::ESimplePending );
       
  2433             // expiry timer i already runnig
       
  2434             }
       
  2435         }
       
  2436     else
       
  2437         {
       
  2438         if ( aReq.ReqState() == CSimpleRequest::ESimplePending || 
       
  2439              aReq.ReqState() == CSimpleRequest::ESimpleReTry )
       
  2440             {
       
  2441             // time to retry / SIP req
       
  2442             // recreate a dialog
       
  2443             aReq.SetReqState( CSimpleRequest::ESimpleDialogReCre );
       
  2444             TRAPD( errx, DoCreateDialogL( aReq ) );
       
  2445             if ( errx )
       
  2446                 {
       
  2447                 // error
       
  2448                 // This will call API callback
       
  2449                 // Original error has been SIP error
       
  2450                 aReq.SetReqState( CSimpleRequest::ESimpleFailed );
       
  2451                 aReq.Complete( KSimpleErrTemporary );
       
  2452                 }
       
  2453             else
       
  2454                 {
       
  2455                 // waiting OK resp
       
  2456                 }
       
  2457             }
       
  2458         }
       
  2459     }
       
  2460 
       
  2461 // ----------------------------------------------------------
       
  2462 // CSimpleSipConnection::DoCreateDialogL
       
  2463 // ----------------------------------------------------------
       
  2464 //
       
  2465 void CSimpleSipConnection::DoCreateDialogL( CSimpleRequest& aReq )
       
  2466     {
       
  2467 #ifdef _DEBUG
       
  2468     TSimpleLogger::Log(_L("SipConnection: DoCreateDialogL"));
       
  2469 #endif
       
  2470 
       
  2471     CSIPSubscribeDialogAssoc* subsDialog = NULL;
       
  2472     CSIPClientTransaction* sipTrans = NULL;
       
  2473 
       
  2474     // Check whether regular subscription or WINFO subscription is needed.
       
  2475     MSimpleEngineRequest::TSimpleRequest reqType= aReq.Request().RequestType();
       
  2476     TSimpleSubsType subsType = ESubsRegular;
       
  2477     if ( reqType == MSimpleEngineRequest::ESubscribeLista )
       
  2478         {
       
  2479         subsType = ESubsList;
       
  2480         }
       
  2481     else if ( reqType == MSimpleEngineRequest::ESubscribeWinfo )
       
  2482         {
       
  2483         subsType = ESubsWinfo;
       
  2484         }
       
  2485     
       
  2486     // send SIP request
       
  2487     sipTrans = DoSubscribeL(
       
  2488         aReq.Request().RemoteURI(),
       
  2489         aReq.Request().RefreshTime(),
       
  2490         aReq.Data(),
       
  2491         subsDialog,
       
  2492         aReq.Request().IsRefresh(),
       
  2493         subsType,
       
  2494         aReq.Request().Aux() ? ETrue : EFalse );
       
  2495 
       
  2496     // save SIP Dialog and SIP client transaction
       
  2497     aReq.SetDialog( subsDialog );
       
  2498     aReq.SetTransaction( sipTrans );
       
  2499 
       
  2500     }
       
  2501 
       
  2502 // ----------------------------------------------------------
       
  2503 // CSimpleSipConnection::DoSendPendingPublish
       
  2504 // ----------------------------------------------------------
       
  2505 //
       
  2506 TInt CSimpleSipConnection::DoSendPendingPublish(
       
  2507     CSimpleRequest& aReq )
       
  2508     {
       
  2509 #ifdef _DEBUG
       
  2510     TSimpleLogger::Log(_L("SipConnection: DoSendPendingPublish" ));
       
  2511 #endif
       
  2512 
       
  2513     // Do the SIP Publish transaction
       
  2514     TBool sendData = aReq.PendingState() == CSimpleRequest::EPendingModify || 
       
  2515                      aReq.PendingState() == CSimpleRequest::EPendingModifyAndRefresh  ? 
       
  2516                      ETrue : EFalse;
       
  2517     TPtrC8 myData = sendData ? aReq.Data() : TPtrC8();
       
  2518     CSIPClientTransaction* sipTrans = NULL;
       
  2519     TRAPD( errx, sipTrans = DoPublishL(
       
  2520         iProfileObserver->GiveUserAorL(),        
       
  2521         aReq.Request().RefreshTime(),
       
  2522         myData,
       
  2523         aReq.ETag(), aReq.RequestContentType() ));
       
  2524     if ( errx )
       
  2525         {
       
  2526         return errx;
       
  2527         }
       
  2528     // Save SIP client transaction
       
  2529     aReq.SetTransaction( sipTrans );
       
  2530     
       
  2531     aReq.SetPendingState( CSimpleRequest::ENoPending );
       
  2532 
       
  2533     // Do not update SOURCE-THROTTLE-PUBLISH time
       
  2534 
       
  2535     // Expiry timer is already running
       
  2536 
       
  2537     return KErrNone;
       
  2538     }
       
  2539 
       
  2540 // ----------------------------------------------------------
       
  2541 // CSimpleSipConnection::HandlePendings
       
  2542 // ----------------------------------------------------------
       
  2543 //
       
  2544 void CSimpleSipConnection::HandlePendings( )
       
  2545     {
       
  2546     TInt errx( KErrNone );
       
  2547     TDblQueIter<CSimpleRequest> rIter( iRequestList );
       
  2548     rIter.SetToFirst();
       
  2549 
       
  2550     while ( rIter )
       
  2551         {
       
  2552         CSimpleRequest* req = rIter;
       
  2553         rIter++; //lint !e1757
       
  2554 
       
  2555         if ( req->Match( CSimpleRequest::EReqSubscribe ) ||
       
  2556              req->Match( CSimpleRequest::EReqSubscribeList ) ||
       
  2557              req->Match( CSimpleRequest::EReqSubscribeWinfo ))
       
  2558             {
       
  2559             // Subscritions
       
  2560             // Set new request state
       
  2561             if ( req->ReqState() == CSimpleRequest::ESimplePendingInit )
       
  2562                 {
       
  2563                 req->SetReqState( CSimpleRequest::ESimpleRunningInit );
       
  2564                 }
       
  2565             else if ( req->ReqState() == CSimpleRequest::ESimplePending )
       
  2566                 {
       
  2567                 req->SetReqState( CSimpleRequest::ESimpleDialogReCre );
       
  2568                 }
       
  2569             else
       
  2570                 {
       
  2571                 // other states do not need network recovery
       
  2572                 break;
       
  2573                 }
       
  2574 
       
  2575             // create new dialog
       
  2576             TRAP( errx, DoCreateDialogL( *req ) );
       
  2577             if ( errx )
       
  2578                 {
       
  2579                 // error
       
  2580                 // This will call API callback
       
  2581                 req->SetReqState( CSimpleRequest::ESimpleFailed );
       
  2582                 req->Complete( errx );
       
  2583                 }
       
  2584             else
       
  2585                 {
       
  2586                 // Start to wait response from SIP stack.
       
  2587                 // Expiry timer is already runnig to detect infinite wait situation
       
  2588                 }
       
  2589             }
       
  2590         else if ( req->Match( CSimpleRequest::EReqPublish ) )
       
  2591             {
       
  2592             // Publications
       
  2593             if ( req->ReqState() == CSimpleRequest::ESimplePendingInit )
       
  2594                 {
       
  2595                 req->SetReqState( CSimpleRequest::ESimpleRunningInit );
       
  2596                 }
       
  2597             else if ( req->ReqState() == CSimpleRequest::ESimplePending )
       
  2598                 {
       
  2599                 req->SetReqState( CSimpleRequest::ESimpleRunning );
       
  2600                 }
       
  2601             else
       
  2602                 {
       
  2603                 // other states do not need network recovery
       
  2604                 break;
       
  2605                 }
       
  2606             // retry publication
       
  2607             if ( DoSendPendingPublish( *req ) )
       
  2608                 {
       
  2609                 // error
       
  2610                 // This will call API callback
       
  2611                 req->SetReqState( CSimpleRequest::ESimpleFailed );
       
  2612                 req->Complete( errx );
       
  2613                 }
       
  2614             else
       
  2615                 {
       
  2616                 // Start to wait response from SIP stack.
       
  2617                 // Expiry timer is already runnig to detect infinite wait situation
       
  2618                 }
       
  2619             }
       
  2620         } // while
       
  2621     }
       
  2622     
       
  2623 // ----------------------------------------------------------
       
  2624 // CSimpleSipConnection::RecognizeSipState
       
  2625 // ----------------------------------------------------------
       
  2626 //
       
  2627 void CSimpleSipConnection::RecognizeSipState( 
       
  2628     TSimpleSipState aState )
       
  2629     {
       
  2630     if ( aState == ESimpleSipActive )
       
  2631         {
       
  2632         // Check that both SIP Profile and SIP connection are ready.
       
  2633         // iProfileObserver is created in ConstructL.
       
  2634         if ( iProfileObserver->IsProfileActive() && 
       
  2635              iSipConnection &&
       
  2636              iSipConnection->State() == CSIPConnection::EActive )
       
  2637             {
       
  2638             SetSipState( aState );            
       
  2639             }
       
  2640         }
       
  2641     else
       
  2642         {
       
  2643         SetSipState( aState );
       
  2644         }    
       
  2645     }    
       
  2646 
       
  2647 // ----------------------------------------------------------
       
  2648 // CSimpleSipConnection::DoHandleReceivedMessageL
       
  2649 // ----------------------------------------------------------
       
  2650 //
       
  2651 void CSimpleSipConnection::DoHandleReceivedMessageL( const TDesC8& aFrom,
       
  2652     const TDesC8& aContent, CSimpleRequest& aRequest )
       
  2653     {
       
  2654 #ifdef _DEBUG
       
  2655     TSimpleLogger::Log( _L(
       
  2656         "CSimpleSipConnection::DoHandleReceivedMessageL - Start" ) );
       
  2657 #endif
       
  2658     aRequest.SetReason( KErrNone );
       
  2659     aRequest.SetRecipientL( aFrom );
       
  2660     aRequest.SetDataL( aContent );
       
  2661     aRequest.Complete( KErrNone );
       
  2662     // Open request can be deleted after completion.
       
  2663     aRequest.Destroy();
       
  2664 #ifdef _DEBUG
       
  2665     TSimpleLogger::Log( _L(
       
  2666         "CSimpleSipConnection::DoHandleReceivedMessageL - End" ) );
       
  2667 #endif
       
  2668     }
       
  2669 
       
  2670 // -----------------------------------------------------------------------------
       
  2671 // CSimpleRequest::SetServiceId
       
  2672 // -----------------------------------------------------------------------------
       
  2673 EXPORT_C void CSimpleSipConnection::SetServiceId( TInt32 aServiceId )
       
  2674     {
       
  2675 #ifdef _DEBUG
       
  2676     TSimpleLogger::Log( _L(
       
  2677                "CSimpleSipConnection::SetServiceId old serviceId = %d, new serviceId = %d" ),
       
  2678                    iServiceId, aServiceId );
       
  2679 #endif
       
  2680     iServiceId = aServiceId;
       
  2681     }
       
  2682 
       
  2683 // -----------------------------------------------------------------------------
       
  2684 // CSimpleRequest::StoreETag
       
  2685 // -----------------------------------------------------------------------------
       
  2686 void CSimpleSipConnection::StoreETagL( HBufC8& aETag )
       
  2687     {
       
  2688 #ifdef _DEBUG
       
  2689     TBuf<255> printDocumentId;
       
  2690         printDocumentId.Copy( aETag );
       
  2691     TSimpleLogger::Log(_L("CSimpleSipConnection: StoreETag ETag = %S, serviceId = %d" ),
       
  2692         &printDocumentId, iServiceId );
       
  2693 #endif
       
  2694     MVIMPSTSettingsStore* settings = CVIMPSTSettingsStore::NewLC();
       
  2695     
       
  2696     // Store ETag to uiservicetabsettings
       
  2697     User::LeaveIfError( settings->SetL( 
       
  2698         iServiceId, EServicePresenceSessionIdentifier, aETag ) );
       
  2699     
       
  2700     CleanupStack::PopAndDestroy(); //settings   
       
  2701     }
       
  2702