smsprotocols/smsstack/smsprot/Src/smsprov.cpp
changeset 0 3553901f7fa8
child 14 7ef16719d8cb
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the CSmsProvider service access point (SAP) class.
       
    15 // Includes
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #include "smsprot.h"
       
    24 
       
    25 #include <es_ver.h>
       
    26 #include <es_mbuf.h>
       
    27 
       
    28 #include "Gsmuelem.h"
       
    29 #include "gsmubuf.h"
       
    30 #include "Gsmumsg.h"
       
    31 
       
    32 #include "smsustrm.h"
       
    33 #include "smspmain.h"
       
    34 #include "smspfacadestor.h"
       
    35 
       
    36 // CSmsProvider policies
       
    37 //
       
    38 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlDeleteSmsMessagePolicy,ECapabilityWriteUserData);
       
    39 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlEnumerateSmsMessagesPolicy,ECapabilityReadUserData );
       
    40 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlReadMessageSucceededPolicy,ECapabilityReadUserData );
       
    41 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlReadMessageFailedPolicy,ECapabilityReadUserData );
       
    42 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlSendSmsMessagePolicy,ECapabilityNetworkServices );
       
    43 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlWriteSmsMessagePolicy,ECapabilityWriteUserData );
       
    44 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlReadSmsParamsPolicy,ECapability_None );
       
    45 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlCompleteReadSmsParamsPolicy,ECapability_None );
       
    46 static _LIT_SECURITY_POLICY_C1(smsProviderIoctlWriteSmsParamsPolicy,ECapabilityWriteDeviceData );
       
    47 
       
    48 // following not implemented as too paranoid
       
    49 //static _LIT_SECURITY_POLICY_C1(smsProviderIoctlSelectModemPresentPolicy,ECapabilityWriteDeviceData );
       
    50 //static _LIT_SECURITY_POLICY_C1(smsProviderIoctlSelectModemNotPresentPolicy,ECapabilityWriteDeviceData );
       
    51 static _LIT_SECURITY_POLICY_C1(smsProviderSetLocalNamePolicy,ECapabilityNetworkServices);
       
    52 static _LIT_SECURITY_POLICY_C1(smsProviderWritePolicy,ECapability_None);
       
    53 
       
    54 /**
       
    55  *  2 Phase constructor.
       
    56  *  
       
    57  *  @param aProtocol a reference to the SMS protocol object.
       
    58  *  @leave Leaves if ContructL() leaves, or not enough memory is available.
       
    59  *  @return a new CSmsProvider object.
       
    60  *  
       
    61  */
       
    62 CSmsProvider* CSmsProvider::NewL(CSmsProtocol& aProtocol)
       
    63     {
       
    64     LOGSMSPROT1("CSmsProvider::NewL");
       
    65     
       
    66     CSmsProvider* self =new(ELeave) CSmsProvider(aProtocol);
       
    67     CleanupStack::PushL(self);
       
    68     self->ConstructL();
       
    69     CleanupStack::Pop(self);
       
    70 
       
    71     LOGSMSPROT1("-> CSmsProvider::NewL - done");
       
    72     
       
    73     return self;
       
    74     }
       
    75 
       
    76 /**
       
    77  *  C'tor
       
    78  *  
       
    79  *  @param aProtocol a reference to the SMS protocol object.
       
    80  */
       
    81 CSmsProvider::CSmsProvider(CSmsProtocol& aProtocol)
       
    82 : iProtocol(aProtocol),iEnumSocket(EFalse),iNumOfEnumeratedMessages(0)
       
    83     {
       
    84     }
       
    85 
       
    86 /**
       
    87  *  2nd Phase of construction.
       
    88  *  Subscribes to the protocol as an observer, and creates our send and
       
    89  *  receive buffers.
       
    90  *  
       
    91  */
       
    92 void CSmsProvider::ConstructL()
       
    93     {
       
    94     LOGSMSPROT1("CSmsProvider::ConstructL");
       
    95     
       
    96     iProtocol.AddSmsMessageObserverL(*this);
       
    97     SetObserverAddedToProtocol(ETrue);
       
    98     iRecvBufSegArray=new(ELeave) CArrayPtrFlat<CBufSeg>(8);
       
    99     iSendBufSeg = CBufSeg::NewL(KSmsMaxSegmentLength);
       
   100     
       
   101     LOGSMSPROT1("-> CSmsProvider::ConstructL - done");
       
   102     }
       
   103 
       
   104 /**
       
   105  *  D'tor
       
   106  *  
       
   107  *  Removes this SAP as an observer of the SMS protocol, and
       
   108  *  frees the send and receive buffers.
       
   109  *  
       
   110  */
       
   111 CSmsProvider::~CSmsProvider()
       
   112     {
       
   113     if( ObserverAddedToProtocol() )
       
   114         {
       
   115         iProtocol.RemoveSmsMessageObserver(*this);
       
   116         }
       
   117     if( iRecvBufSegArray )
       
   118         {
       
   119         iRecvBufSegArray->ResetAndDestroy();
       
   120         delete iRecvBufSegArray;
       
   121         }
       
   122     delete iSendBufSeg;
       
   123     }
       
   124 
       
   125 /**
       
   126  *  Does nothing.  Implementation of pure virtual CServProviderBase::Start().
       
   127  *  
       
   128  */
       
   129 void CSmsProvider::Start()
       
   130     {
       
   131     LOGSMSPROT1("CSmsProvider::Start");
       
   132     }
       
   133 
       
   134 /**
       
   135  *  Returns the local address of this SAP.  Implementation of
       
   136  *  pure virtual CServProviderBase::LocalName().
       
   137  *  
       
   138  */
       
   139 void CSmsProvider::LocalName(TSockAddr& aAddr) const
       
   140     {
       
   141     LOGSMSPROT1("CSmsProvider::LocalName");
       
   142     aAddr = iLocalAddress;
       
   143     }
       
   144 
       
   145 /**
       
   146  *  Sets the local address of this SAP by binding it to the protocol.
       
   147  *  The protocol ensures that there are no duplicate observers, and
       
   148  *  then calls back on the CSmsProvider::SetLocalAddress() method
       
   149  *  to set the address.
       
   150  *  
       
   151  *  Implementation of the pure virtual CServProviderBase::SetLocalName().
       
   152  *  
       
   153  *  @capability NetworkServices
       
   154  */
       
   155 TInt CSmsProvider::SetLocalName(TSockAddr& aAddr)
       
   156     {
       
   157     LOGSMSPROT1("CSmsProvider::SetLocalName");
       
   158     
       
   159     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderSetLocalNamePolicy,"CSmsProvider SetLocal Name policy check") != KErrNone) )
       
   160         {
       
   161         return KErrPermissionDenied;
       
   162         }
       
   163     TSmsAddr& smsAddr=static_cast<TSmsAddr&>(aAddr);
       
   164     if( ( smsAddr.SmsAddrFamily() == ESmsAddrApplication8BitPort  || smsAddr.SmsAddrFamily() == ESmsAddrApplication16BitPort ) && smsAddr.Port() == 0 )
       
   165         {
       
   166         if( !iProtocol.AllocateLocalAddress(smsAddr) )
       
   167             {
       
   168             return KErrInUse;
       
   169             }
       
   170         }
       
   171     return iProtocol.BindSmsMessageObserver(*this,smsAddr);
       
   172     }
       
   173 
       
   174 /**
       
   175  *  Called by the protocol to retrieve the remote name of the connection.
       
   176  *  This protocol is not connection oriented so this is not supported.
       
   177  *  
       
   178  *  Implementation of the pure virtual CServProviderBase::RemName().
       
   179  *  
       
   180  */
       
   181 void CSmsProvider::RemName(TSockAddr& /*aAddr*/) const
       
   182     {
       
   183     // Ignore in code coverage - not intended to be used
       
   184     BULLSEYE_OFF    
       
   185     LOGSMSPROT1("CSmsProvider::RemName");
       
   186     BULLSEYE_RESTORE
       
   187     }
       
   188 
       
   189 /**
       
   190  *  Called by the protocol to set the remote name of the connection.
       
   191  *  This protocol is not connection oriented so this is not supported.
       
   192  *  
       
   193  *  Implementation of the pure virtual CServProviderBase::SetRemName().
       
   194  *  
       
   195  */
       
   196 TInt CSmsProvider::SetRemName(TSockAddr& /*aAddr*/)
       
   197     {
       
   198     // Ignore in code coverage - not intended to be used
       
   199     BULLSEYE_OFF    
       
   200     LOGSMSPROT1("CSmsProvider::SetRemName");
       
   201     return KErrNotSupported;
       
   202     BULLSEYE_RESTORE
       
   203     }
       
   204 
       
   205 /**
       
   206  *  Returns the current value of an option setting for this SAP.
       
   207  *  No settings are currently defined.
       
   208  *  Implementation of pure virtual CServProviderBase::GetOption().
       
   209  *  
       
   210  */
       
   211 TInt CSmsProvider::GetOption(TUint /*aLevel*/,TUint /*aName*/,TDes8& /*aOption*/) const
       
   212     {
       
   213     // Ignore in code coverage - not intended to be used
       
   214     BULLSEYE_OFF    
       
   215     LOGSMSPROT1("CSmsProvider::GetOption");
       
   216     return 0;
       
   217     BULLSEYE_RESTORE
       
   218     }
       
   219 
       
   220 /**
       
   221  *  Called to perform specific IO control by the client.  All of the SMS protocol
       
   222  *  services are provided through this interface.
       
   223  *  
       
   224  *  The local address of this SAP must already be bound, and only one ioctl request
       
   225  *  may be outstanding at any one time.
       
   226  *  
       
   227  *  A resulting socket error of KErrEof can result from a KErrNoMemory during a
       
   228  *  preceding write to the socket.
       
   229  *  
       
   230  *  Implementation of pure virtual CServProviderBase::Ioctl().
       
   231  *  
       
   232  *  @param aLevel the IOCTL level.  Only KSolSmsProv is supported.
       
   233  *  @param aName the IOCTL name.
       
   234  *  @param aOption the IOCTL option.
       
   235  *  
       
   236  */
       
   237 void CSmsProvider::Ioctl(TUint aLevel,TUint aName,TDes8* aOption)
       
   238     {
       
   239     LOGSMSPROT3("CSmsProvider::Ioctl [aLevel=%d, aName=%d]", aLevel, aName);
       
   240     LOGSMSPROT2("CSmsProvider::Ioctl [provider=0x%08x]",this);
       
   241     
       
   242     // Panic in debug mode if this call is invalid in this SAPs current state
       
   243     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrUnbound,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   244     __ASSERT_DEBUG(!IoctlOutstanding(),SmspPanic(KSmspPanicIoctlAlreadyOutstanding));
       
   245     // Gracefully handle invalid calls in release build
       
   246     if( iLocalAddress.SmsAddrFamily()==ESmsAddrUnbound )
       
   247         {
       
   248         iSocket->Error(KErrNotReady,MSocketNotify::EErrorIoctl);
       
   249         return;
       
   250         }
       
   251     if( IoctlOutstanding() )
       
   252         {
       
   253         iSocket->Error(KErrInUse,MSocketNotify::EErrorIoctl);
       
   254         return;
       
   255         }
       
   256     // General state is OK, now try to service the request
       
   257     iName=aName;
       
   258     switch( aLevel )
       
   259         {
       
   260         case KSolSmsProv:
       
   261             {
       
   262             switch( iName )
       
   263                 {
       
   264                 case KIoctlSupportOODClass0SmsMessages:
       
   265                     {
       
   266                     if( iProtocol.iReassemblyStore )
       
   267                         {
       
   268                         if( iProtocol.iReassemblyStore->IsSeparateClass0StoreSupported() )
       
   269                             {
       
   270                             iSocket->IoctlComplete(NULL);
       
   271                             }
       
   272                         else
       
   273                             {
       
   274                             iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   275                             }
       
   276                         }
       
   277                     else
       
   278                         {
       
   279                         iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   280                         }
       
   281                     } break;
       
   282                 case KIoctlSendSmsMessage:
       
   283                     {
       
   284                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlSendSmsMessagePolicy,"CSmsProvider Ioctl SendSmsMessage policy check") != KErrNone) )
       
   285                         {
       
   286                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   287                         return;
       
   288                         }
       
   289                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrLocalOperation,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   290                     __ASSERT_DEBUG(aOption!=NULL,SmspPanic(KSmspPanicOptionBufferNull));
       
   291                     // Handle bad requests gracefully
       
   292                     if( iLocalAddress.SmsAddrFamily()==ESmsAddrLocalOperation )
       
   293                         {
       
   294                         iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   295                         return;
       
   296                         }
       
   297                     if( aOption == NULL )
       
   298                         {
       
   299                         iSocket->Error(KErrArgument,MSocketNotify::EErrorIoctl);
       
   300                         return;
       
   301                         }
       
   302                     // Read message from socket
       
   303                     CSmsMessage* smsmessage=NULL;
       
   304                     TRAPD(ret,(smsmessage=InternalizeMessageL()));
       
   305                     if( ret!=KErrNone )
       
   306                         {
       
   307                         iSendBufSeg->Reset();
       
   308                         iSocket->Error(ret,MSocketNotify::EErrorIoctl);
       
   309                         }
       
   310                     else
       
   311                         {
       
   312                             // Pass the message to the protocol for sending
       
   313                         TPckgBuf<TUint> buf;
       
   314                         buf.Copy(*aOption);
       
   315                         SetIoctlOutstanding(ETrue);
       
   316                         iProtocol.SendSmsMessage(smsmessage,*this, buf());
       
   317 						}
       
   318                     } break;
       
   319                 case KIoctlEnumerateSmsMessages:
       
   320                     {
       
   321                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlEnumerateSmsMessagesPolicy, "CSmsProvider Ioctl EnumerateSmsMessages policy check") != KErrNone) )
       
   322                         {
       
   323                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   324                         return;
       
   325                         }
       
   326                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   327                     // Handle bad requests gracefully
       
   328                     if( iLocalAddress.SmsAddrFamily()==ESmsAddrSendOnly )
       
   329                         {
       
   330                         iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   331                         return;
       
   332                         }
       
   333                     
       
   334                     SetIoctlOutstanding(ETrue);
       
   335                     iProtocol.EnumeratePhone(*this);
       
   336                     } break;
       
   337                 case KIoctlWriteSmsMessage:
       
   338                     {
       
   339                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlWriteSmsMessagePolicy,"CSmsProvider IoctlWriteSmsMessage policy check") != KErrNone) )
       
   340                         {
       
   341                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   342                         return;
       
   343                         }
       
   344                     // Read message from the socket
       
   345                     CSmsMessage*smsmessage=NULL;
       
   346                     TRAPD(ret,(smsmessage=InternalizeMessageL()));
       
   347                     if( ret!=KErrNone )
       
   348                         {
       
   349                         iSendBufSeg->Reset();
       
   350                         iSocket->Error(ret,MSocketNotify::EErrorIoctl);
       
   351                         }
       
   352                     else
       
   353                         {
       
   354                         // Pass message to the protocol for writing
       
   355                         SetIoctlOutstanding(ETrue);
       
   356                         iProtocol.WriteSmsMessage(smsmessage,*this);
       
   357                         }
       
   358                     } break;
       
   359                 case KIoctlDeleteSmsMessage:
       
   360                     {
       
   361                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlDeleteSmsMessagePolicy,"CSmsProvider Ioctl DeleteSmsMessage policy check") != KErrNone) )
       
   362                         {
       
   363                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   364                         return;
       
   365                         }
       
   366                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   367                     // Handle bad requests gracefully
       
   368                     if( iLocalAddress.SmsAddrFamily()==ESmsAddrSendOnly )
       
   369                         {
       
   370                         iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   371                         return;
       
   372                         }
       
   373                     // Read message from the socket
       
   374                     CSmsMessage*smsmessage=NULL;
       
   375                     TRAPD(ret,(smsmessage=InternalizeMessageL()));
       
   376                     if( ret!=KErrNone )
       
   377                         {
       
   378                         LOGSMSPROT2("-> CSmsProvider::Ioctl - CSmsProvider::InternalizeMessageL [ret=%d]", ret);
       
   379                         iSendBufSeg->Reset();
       
   380                         iSocket->Error(ret, MSocketNotify::EErrorIoctl);
       
   381                         }
       
   382                     else
       
   383                         {
       
   384                         // Pass request to protocol
       
   385                         SetIoctlOutstanding(ETrue);
       
   386                         iProtocol.DeleteSmsMessage(smsmessage,*this);
       
   387                         }
       
   388                     } break;
       
   389                 case KIoctlReadMessageSucceeded:
       
   390                     {
       
   391                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlReadMessageSucceededPolicy,"CSmsProvider Ioctl ReadMessageSucceeded policy check") != KErrNone) )
       
   392                         {
       
   393                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   394                         return;
       
   395                         }
       
   396                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   397                     __ASSERT_DEBUG(NumSegments(iSegmentIndex==NumSegments(iRecvBufSegArray->At(0)->Size())),SmspPanic(KSmspPanicBadClientIoctlCall));
       
   398                     // TODO - flag
       
   399                     // i)  delete entry from reassemblystore
       
   400                     //     smsmsg = MyInternalize( iRecvBufSegArray );
       
   401                     //     iReasStore->GetIndex( Index, smsmsg ); // iReasStore->DeleteSMS(smsmsg);
       
   402                     //     iReasStore->DeleteEntry( Index );
       
   403                     // ii) looking for more sms left in the store
       
   404                     //     iPotocol.ProcessCompleteSMSMessage();
       
   405                     //     @note if this is only called from here the msg stay for a long time
       
   406                     //     in the reassembly store if the processmessage fails
       
   407                     // i)
       
   408                     CSmsMessage*smsmessage=NULL;
       
   409                     TRAPD(ret,(smsmessage=InternalizeMessageL(iRecvBufSegArray->At(0))));
       
   410                     if( ret==KErrNone )
       
   411                         {
       
   412                         TRAP(ret,(iProtocol.DeleteSMSFromReaStoreL( *smsmessage )));
       
   413                         LOGSMSPROT2("-> CSmsProvider::Ioctl - CSmsProvider::DeleteSMSFromReaStoreL [ret=%d]", ret);
       
   414                         }
       
   415                     else
       
   416                         {
       
   417                         LOGSMSPROT2("-> CSmsProvider::Ioctl - CSmsProvider::InternalizeMessageL [ret=%d]", ret);
       
   418                         }
       
   419                     delete smsmessage;
       
   420                     // ii)
       
   421                     // this is now down after finishing the readprocess
       
   422                     // it has to be called here o in pdureadprocescompleted???
       
   423                     iProtocol.MessageReadedSuccessfully();
       
   424                     if( iEnumSocket )
       
   425                         {
       
   426                         --iNumOfEnumeratedMessages;
       
   427                         LOGSMSPROT2("-> CSmsProvider::Ioctl - [iNumOfEnumeratedMessages=%d]", iNumOfEnumeratedMessages);
       
   428                         if( iNumOfEnumeratedMessages <= 0 )
       
   429                             {
       
   430                             iProtocol.iPhoneEnumerationObserver=NULL;
       
   431                             iEnumSocket=EFalse;
       
   432                             iProtocol.MessageReadedSuccessfully();
       
   433                             LOGSMSPROT1("-> CSmsProvider::Ioctl - [iNumOfEnumeratedMessages=NULL]");
       
   434                             }
       
   435                         }
       
   436                     // Remove the message from the receive buffer & complete
       
   437                     delete iRecvBufSegArray->At(0);
       
   438                     iRecvBufSegArray->At(0) = NULL;
       
   439                     iRecvBufSegArray->Delete(0);
       
   440     
       
   441                     iSegmentIndex=0;
       
   442                     iSocket->IoctlComplete(NULL);
       
   443                     } break;
       
   444                 case KIoctlReadMessageFailed:
       
   445                     {
       
   446                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlReadMessageFailedPolicy,"CSmsProvider Ioctl ReadMessageFailed policy check") != KErrNone) )
       
   447                         {
       
   448                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   449                         return;
       
   450                         }
       
   451                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   452                     __ASSERT_DEBUG(NumSegments(iSegmentIndex<=NumSegments(iRecvBufSegArray->At(0)->Size())),SmspPanic(KSmspPanicBadClientIoctlCall));
       
   453                     // Handle bad requests gracefully
       
   454                     if( iLocalAddress.SmsAddrFamily()==ESmsAddrSendOnly )
       
   455                         {
       
   456                         if( iEnumSocket )
       
   457                             {
       
   458                             --iNumOfEnumeratedMessages;
       
   459                             if( iNumOfEnumeratedMessages <= 0 )
       
   460                                 {
       
   461                                 iProtocol.iPhoneEnumerationObserver=NULL;
       
   462                                 LOGSMSPROT1("-> CSmsProvider::Ioctl - fail [iNumOfEnumeratedMessages=NULL]");
       
   463                                 iEnumSocket=EFalse;
       
   464                                 iProtocol.MessageReadedSuccessfully();
       
   465                                 }
       
   466                             }
       
   467                         iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   468                         return;
       
   469                         }
       
   470                     // Re-notify the socket that data is available, reset the segment
       
   471                     // index of the current message back to the start & complete
       
   472                     iSocket->NewData(iSegmentIndex);
       
   473                     iSegmentIndex=0;
       
   474                     iSocket->IoctlComplete(NULL);
       
   475                     } break;
       
   476                 case KIoctlReadSmsParams:
       
   477                     {
       
   478                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlReadSmsParamsPolicy,"CSmsProvider Ioctl ReadSmsParams policy check") != KErrNone) )
       
   479                         {
       
   480                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   481                         return;
       
   482                         }
       
   483                     // Handle bad requests gracefully
       
   484                     if( iLocalAddress.SmsAddrFamily()!=ESmsAddrLocalOperation )
       
   485                         {
       
   486                         iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   487                         return;
       
   488                         }
       
   489                    
       
   490                    // Pass request on to the protocol
       
   491                    SetIoctlOutstanding(ETrue);
       
   492                    iProtocol.ReadSmsParameters(*this);
       
   493                     } break;
       
   494                 case KIoctlCompleteReadSmsParams:
       
   495                     {
       
   496                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlCompleteReadSmsParamsPolicy,"CSmsProvider Ioctl CompleteReadSmsParams policy check") != KErrNone) )
       
   497                         {
       
   498                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   499                         return;
       
   500                         }
       
   501                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   502                     __ASSERT_DEBUG(NumSegments(iSegmentIndex==NumSegments(iRecvBufSegArray->At(0)->Size())),SmspPanic(KSmspPanicBadClientIoctlCall));
       
   503                     // Handle bad requests gracefully
       
   504                     if ( iLocalAddress.SmsAddrFamily()==ESmsAddrSendOnly )
       
   505                         {
       
   506                         iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   507                         return;
       
   508                         }
       
   509                     // Remove the parameter list from the receive buffer & complete
       
   510                     delete iRecvBufSegArray->At(0);
       
   511                     iRecvBufSegArray->At(0) = NULL;
       
   512                     iRecvBufSegArray->Delete(0);
       
   513                     iSegmentIndex=0;
       
   514                     iSocket->IoctlComplete(NULL);
       
   515                     } break; 
       
   516                 case KIoctlWriteSmsParams:
       
   517                     {
       
   518                     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderIoctlWriteSmsParamsPolicy,"CSmsProvider Ioctl WriteSmsParams policy check") != KErrNone) )
       
   519                         {
       
   520                         iSocket->Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
       
   521                         return;
       
   522                         }
       
   523                     // Read parameters from the socket
       
   524                     CMobilePhoneSmspList*mobilePhoneSmspList=NULL;
       
   525                     TRAPD(ret,(mobilePhoneSmspList=InternalizeParametersL()));
       
   526                     if( ret!=KErrNone )
       
   527                         {
       
   528                         iSendBufSeg->Reset();
       
   529                         iSocket->Error(ret,MSocketNotify::EErrorIoctl);
       
   530                         }
       
   531                     else
       
   532                         {
       
   533                         // Pass parameters to the protocol for writing.
       
   534                         // CSmsWriteParams takes ownership of mobilePhoneSmspList.
       
   535                         SetIoctlOutstanding(ETrue);
       
   536                         iProtocol.WriteSmsParameters(mobilePhoneSmspList, *this);
       
   537                         }
       
   538                     } break;
       
   539                 default:
       
   540                     {
       
   541                     // Panic in debug build
       
   542                     __ASSERT_DEBUG(EFalse,SmspPanic(KSmspUndefinedName));
       
   543                     // Error gracefully in release build
       
   544                     iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   545                     } break;
       
   546                 }
       
   547             } break;
       
   548         default:
       
   549             {
       
   550             // Unsupported ioctl level, panic in debug build
       
   551             __ASSERT_DEBUG(EFalse,SmspPanic(KSmspUndefinedLevel));
       
   552             // Gracefully error in release build
       
   553             iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
   554             } break;
       
   555         }
       
   556     }
       
   557 
       
   558 /**
       
   559  *  Cancels an outstanding ioctl.
       
   560  *  Since there can only be a single ioctl request outstanding, the parameters
       
   561  *  must match those of the original request.
       
   562  *  Implementation of the pure virtual CServProviderBase::CancelIoctl().
       
   563  *  
       
   564  *  @param aLevel the level of the ioctl request to cancel.
       
   565  *  @param aName the name of the ioctl request to cancel.
       
   566  *  
       
   567  */
       
   568 void CSmsProvider::CancelIoctl(TUint aLevel, TUint aName)
       
   569     {
       
   570     LOGSMSPROT3("CSmsProvider::CancelIoctl [aLevel=%d, aName=%d]", aLevel, aName);
       
   571     
       
   572     // Panic in debug mode if this call is invalid in this SAPs current state
       
   573     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrUnbound,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   574     __ASSERT_DEBUG(iName==aName,SmspPanic(ESmspBadIoctlName));
       
   575     if( iName != aName )
       
   576         {
       
   577         return;
       
   578         }
       
   579     switch( aLevel )
       
   580         {
       
   581         case KSolSmsProv:
       
   582             {
       
   583             // Request cancel via protocol
       
   584             switch( iName )
       
   585                 {
       
   586                 case KIoctlSendSmsMessage:
       
   587                     {
       
   588                     iProtocol.CancelSendSmsMessage(*this);
       
   589                     } break;
       
   590                 case KIoctlEnumerateSmsMessages:
       
   591                     {
       
   592                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   593                     iProtocol.CancelEnumeratePhone(*this);
       
   594                     iEnumSocket=EFalse;
       
   595                     iProtocol.iPhoneEnumerationObserver=NULL;
       
   596                     LOGSMSPROT1("-> CSmsProvider::CancelIoctl - [iNumOfEnumeratedMessages=NULL]");
       
   597                     } break;
       
   598                 case KIoctlWriteSmsMessage:
       
   599                     {
       
   600                     iProtocol.CancelWriteSmsMessage(*this);
       
   601                     } break;
       
   602                 case KIoctlDeleteSmsMessage:
       
   603                     {
       
   604                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   605                     iProtocol.CancelDeleteSmsMessage(*this);
       
   606                     } break;
       
   607                 case KIoctlReadMessageSucceeded:
       
   608                 case KIoctlReadMessageFailed:
       
   609                     {
       
   610                     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   611                     } break;
       
   612                 case KIoctlReadSmsParams:
       
   613                     {
       
   614                     iProtocol.CancelReadSmsParams();
       
   615                     } break;
       
   616                 case KIoctlWriteSmsParams:
       
   617                     {
       
   618                     iProtocol.CancelWriteSmsParams();
       
   619                     } break;
       
   620                 default:
       
   621                     {
       
   622                     __ASSERT_DEBUG(EFalse,SmspPanic(KSmspUndefinedName));
       
   623                     } break;
       
   624                 }
       
   625             } break;
       
   626         default:
       
   627             {
       
   628             __ASSERT_DEBUG(EFalse,SmspPanic(KSmspUndefinedLevel));
       
   629             } break;
       
   630         }
       
   631     }
       
   632 
       
   633 /**
       
   634  *  Sets an option on the SAP.  No options are currently implemented.
       
   635  *  
       
   636  *  Implements the pure virtual CServProviderBase::SetOption().
       
   637  *  
       
   638  */
       
   639 TInt CSmsProvider::SetOption(TUint /*aLevel*/,TUint /*aName*/,const TDesC8& /*aOption*/)
       
   640     {
       
   641     // Ignore in code coverage - not intended to be used
       
   642     BULLSEYE_OFF    
       
   643     LOGSMSPROT1("CSmsProvider::SetOption()");
       
   644     return 0;
       
   645     BULLSEYE_RESTORE
       
   646     }
       
   647 
       
   648 /**
       
   649  *  Called by the socket server to write data into the send queue.
       
   650  *  The data is a single segment of a serialized SMS message.
       
   651  *  
       
   652  *  A KErrNoMemory condition arising in this write will not be reported directly (due to
       
   653  *  the ESOCK design), instead it will be reflected in a KErrEof from the subsequent Ioctl()
       
   654  *  call.
       
   655  *  
       
   656  *  Implementation of the pure virtual CServProviderBase::Write().
       
   657  *  
       
   658  *  @param aBufChain the data to write into the send buffer.
       
   659  *  @param aOptions not used.
       
   660  *  @param aAddr not used.
       
   661  *  @return 1 (datagram written) on success, otherwise an error.
       
   662  *  
       
   663  *  @capability None
       
   664  */
       
   665 TInt CSmsProvider::Write(RMBufChain& aBufChain, TUint /*aOptions*/, TSockAddr* /*aAddr*/)
       
   666     {
       
   667     LOGSMSPROT1("CSmsProvider::Write");
       
   668     
       
   669     if( !iSecurityChecker || (iSecurityChecker->CheckPolicy(smsProviderWritePolicy,"CSmsProvider Write policy check") != KErrNone) )
       
   670         {
       
   671         return KErrPermissionDenied;
       
   672         }
       
   673     __ASSERT_DEBUG(iLocalAddress.SmsAddrFamily()!=ESmsAddrUnbound,SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   674     
       
   675     /// @note: LOGIFH2A2 macro for logging esock write
       
   676     LOGSMSPROT2("-> CSmsProvider::Write [%d bytes]", aBufChain.Length());
       
   677 #ifdef SMSLOGGERIF
       
   678 	HBufC8* debugBuf = HBufC8::New(aBufChain.Length());
       
   679 	if(debugBuf)
       
   680 		{
       
   681 		TPtr8 debugData = debugBuf->Des();
       
   682 		aBufChain.CopyOut(debugData);
       
   683 		LOGIF2(_L8("ESOCK WRITE: %S"),&debugData);
       
   684 		LOGIFH2A2(_L8("ESOCK WRITE: "),debugData);
       
   685 		delete debugBuf;
       
   686 		}
       
   687 #endif
       
   688     
       
   689     TUint bytesCopied = 0;
       
   690     // Append all of the mbufs to the send buffer
       
   691     TInt ret = KErrNone;
       
   692     TMBufIter iter(aBufChain);
       
   693     while( iter.More() )
       
   694         {
       
   695         RMBuf* p = iter++;
       
   696         TRAP(ret, iSendBufSeg->InsertL(iSendBufSeg->Size(), p->Ptr(), p->Length()));
       
   697         if(ret != KErrNone)
       
   698             break;
       
   699         bytesCopied += p->Length();
       
   700         }
       
   701     if( ret != KErrNone )
       
   702         {
       
   703         iSendBufSeg->Reset();	// it has always done this, but won't innocent data get zapped?
       
   704         }
       
   705     else
       
   706         {
       
   707         aBufChain.Free();	   // we accepted it all; flag these by consuming all buffers
       
   708         }
       
   709     return (ret == KErrNone)? 1: ret;
       
   710     }
       
   711 
       
   712 /**
       
   713  *  Called by the socket server to retrieve data that this SAP has indicated
       
   714  *  is waiting in its buffers.
       
   715  *  
       
   716  *  Implentation of the pure virtual CServProviderBase::GetData().
       
   717  *  
       
   718  *  Once the provider has indicated new data is available using
       
   719  *  MSocketNotify::NewData(), the socket server will call on this method
       
   720  *  to retrieve the serialized SMS message in segments.
       
   721  *  Once the sockets client has streamed out the entire message, it
       
   722  *  will call on ioctl with KIoctlReadMessageSucceeded which resets the internal
       
   723  *  counters.
       
   724  *  
       
   725  *  @param aBufChain the buffer to insert the data.
       
   726  *  @param aLength not used.
       
   727  *  @param aOptions not used.
       
   728  *  @param aAddr not used.
       
   729  *  @return 1 (datagram read) on success, otherwise an error.
       
   730  *  
       
   731  */
       
   732 TInt CSmsProvider::GetData(RMBufChain& aBufChain, TUint /*aLength*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/)
       
   733     {
       
   734     __ASSERT_DEBUG((iLocalAddress.SmsAddrFamily()!=ESmsAddrUnbound) && (iLocalAddress.SmsAddrFamily()!=ESmsAddrSendOnly),SmspPanic(KSmspPanicWrongSmsAddressFamily));
       
   735 
       
   736     LOGSMSPROT2("CSmsProvider::GetData [provider=0x%08x]", this);
       
   737     
       
   738     // Get the segmented buffer of first message
       
   739     CBufSeg* recvbufseg=iRecvBufSegArray->At(0);
       
   740     TInt size=recvbufseg->Size();
       
   741     __ASSERT_DEBUG(iSegmentIndex<NumSegments(size),SmspPanic(KSmspPanicBadClientMessageRead));
       
   742 
       
   743     // Caculate the position of the next segment of the serialized message,
       
   744     // insert into the buffer parameter and update our segment counter
       
   745     TInt pos=iSegmentIndex*KSmsMaxSegmentLength;
       
   746     TInt length = pos+KSmsMaxSegmentLength>size? size-pos: KSmsMaxSegmentLength;
       
   747     
       
   748     TRAPD(err, aBufChain.AllocL(length));
       
   749     if( err == KErrNone )
       
   750         {
       
   751         // For want of a segmented buffer copy for Mbufs we have a little loop. Because we're
       
   752         // reading consecutive data out of the CBufSeg there shouldn't be a bad performance hit
       
   753         // (see CBufSeg::Ptr() doco; CBufBase::Read() uses this)
       
   754         TInt segPos = 0;
       
   755         TMBufIter iter(aBufChain);
       
   756         while( segPos < length )
       
   757             {
       
   758             RMBuf* p = iter++;
       
   759             TInt readSize = Min(p->Size(), length - segPos);
       
   760             recvbufseg->Read(pos + segPos, p->Buffer(), readSize);
       
   761             segPos += readSize;
       
   762             }
       
   763         }
       
   764     else if( err == KErrNoMBufs )
       
   765         {
       
   766         return KErrNoMBufs;	// ask ESock to call us back when some buffers are free
       
   767         }
       
   768     else
       
   769         {
       
   770         iSocket->Error(err, MSocketNotify::EErrorRecv);
       
   771         }
       
   772     ++iSegmentIndex;
       
   773     return 1;	// datagrams are counted as atoms not bytes
       
   774     }
       
   775 
       
   776 /**
       
   777  *  Called by the socket server to indicate the provider should connect to
       
   778  *  a peer.  Not a connection oriented protocol so this is not implemented.
       
   779  *  
       
   780  *  Implementation of the pure virtual CServProviderBase::ActiveOpen().
       
   781  *  
       
   782  */
       
   783 void CSmsProvider::ActiveOpen()
       
   784     {
       
   785     // Ignore in code coverage - not intended to be used
       
   786     BULLSEYE_OFF    
       
   787     LOGSMSPROT1("CSmsProvider::ActiveOpen [does nothing]");
       
   788     BULLSEYE_RESTORE
       
   789     }
       
   790 
       
   791 /**
       
   792  *  Called by the socket server to indicate the provider should connect to
       
   793  *  a peer.  Not a connection oriented protocol so this is not implemented.
       
   794  *  
       
   795  *  Implementation of the pure virtual CServProviderBase::ActiveOpen().
       
   796  *  
       
   797  */
       
   798 void CSmsProvider::ActiveOpen(const TDesC8& /*aConnectionData*/)
       
   799     {
       
   800     // Ignore in code coverage - not intended to be used
       
   801     BULLSEYE_OFF    
       
   802     LOGSMSPROT1("CSmsProvider::ActiveOpen [does nothing]");
       
   803     BULLSEYE_RESTORE
       
   804     }
       
   805 
       
   806 /**
       
   807  *  Called by the socket server to indicate the provider should wait for an
       
   808  *  incoming client connection request.  Not a connection oriented protocol
       
   809  *  so this is not implemented.
       
   810  *  
       
   811  *  Implementation of the pure virtual CServiceProviderBase::PassiveOpen().
       
   812  *  
       
   813  */
       
   814 TInt CSmsProvider::PassiveOpen(TUint /*aQueSize*/)
       
   815     {
       
   816     // Ignore in code coverage - not intended to be used
       
   817     BULLSEYE_OFF    
       
   818     LOGSMSPROT1("CSmsProvider::PassiveOpen [not supported]");
       
   819     return KErrNotSupported;
       
   820     BULLSEYE_RESTORE
       
   821     }
       
   822 
       
   823 /**
       
   824  *  Called by the socket server to indicate the provider should wait for an
       
   825  *  incoming client connection request.  Not a connection oriented protocol
       
   826  *  so this is not implemented.
       
   827  *  
       
   828  *  Implementation of the pure virtual CServiceProviderBase::PassiveOpen().
       
   829  *  
       
   830  */
       
   831 TInt CSmsProvider::PassiveOpen(TUint /*aQueSize*/,const TDesC8& /*aConnectionData*/)
       
   832     {
       
   833     // Ignore in code coverage - not intended to be used
       
   834     BULLSEYE_OFF    
       
   835     LOGSMSPROT1("CSmsProvider::PassiveOpen [not supported]");
       
   836     return KErrNotSupported;
       
   837     BULLSEYE_RESTORE
       
   838     }
       
   839 
       
   840 /**
       
   841  *  Called by the socket server to shutdown a connection.
       
   842  *  
       
   843  *  Implementation of the pure virtual CServProviderBase::Shutdown().
       
   844  *  
       
   845  */
       
   846 void CSmsProvider::Shutdown(TCloseType aOption)
       
   847     {
       
   848     LOGSMSPROT2("CSmsProvider::Shutdown [aOption=%d]", aOption);
       
   849     
       
   850     TInt messagesInBuffer = iRecvBufSegArray->Count();
       
   851     for( TInt index = 0; index < messagesInBuffer; ++index )
       
   852         {
       
   853         // Read message from the socket
       
   854         CSmsMessage*smsmessage=NULL;
       
   855         TRAPD(ret,(smsmessage=InternalizeMessageL(iRecvBufSegArray->At(index))));
       
   856         if( ret == KErrNone )
       
   857             {
       
   858             TRAP(ret, (iProtocol.iReassemblyStore->SetMessagePassedToClientL(*smsmessage, EFalse)));
       
   859             LOGSMSPROT2("-> CSmsProvider::Shutdown - SetMessagePassedToClientL [ret=%d]", ret);
       
   860             }
       
   861         else
       
   862             {
       
   863             LOGSMSPROT2("-> CSmsProvider::Shutdown - CSmsProvider::InternalizeMessageL leave [ret=%d]", ret);
       
   864             }
       
   865         delete smsmessage;
       
   866         }
       
   867     
       
   868     if( iEnumSocket && iProtocol.iPhoneEnumerationObserver == this )
       
   869         {
       
   870         iEnumSocket=EFalse;
       
   871         iProtocol.iPhoneEnumerationObserver=NULL;
       
   872         }
       
   873     if( ObserverAddedToProtocol() )
       
   874         {
       
   875         iProtocol.CancelSendSmsMessage(*this);
       
   876         }    
       
   877     if( aOption!=CServProviderBase::EImmediate )
       
   878         {
       
   879         iSocket->CanClose();
       
   880         }
       
   881     } 
       
   882 
       
   883 /**
       
   884  *  Called by the socket server to shutdown a connection.  Simply calls
       
   885  *  the single parameter version shutdown method.
       
   886  *  
       
   887  *  Implementation of the pure virtual CServProviderBase::Shutdown().
       
   888  *  
       
   889  */
       
   890 void CSmsProvider::Shutdown(TCloseType aOption, const TDesC8& /*aDisconnectionData*/)
       
   891 	{
       
   892 	LOGSMSPROT1("CSmsProvider::Shutdown");
       
   893 	Shutdown(aOption);
       
   894 	}
       
   895 
       
   896 /**
       
   897  *  Called by the socket server to indicate the provider should choose
       
   898  *  a local address and bind to it.  Not supported by this protocol.
       
   899  *  
       
   900  *  Implementation of the pure virtual CServProviderBase::AutoBind().
       
   901  *  
       
   902  */
       
   903 void CSmsProvider::AutoBind()
       
   904 	{
       
   905     // Ignore in code coverage - not intended to be used
       
   906     BULLSEYE_OFF    
       
   907 	LOGSMSPROT1("CSmsProvider::AutoBind [does nothing]");
       
   908     BULLSEYE_RESTORE
       
   909 	}
       
   910 
       
   911 /**
       
   912  *  Called by the SMS protocol to obtain the local address of this SAP.
       
   913  *  
       
   914  *  @return the local address of this SAP.
       
   915  *  
       
   916  */
       
   917 const TSmsAddr& CSmsProvider::GetLocalAddress() const
       
   918 	{
       
   919 	LOGSMSPROT1("CSmsProvider::GetLocalAddress");
       
   920 	return iLocalAddress;
       
   921 	}
       
   922 
       
   923 /**
       
   924  *  Called by the SMS protocol to bind a local address to this SAP.
       
   925  *  
       
   926  */
       
   927 void CSmsProvider::SetLocalAddress(const TSmsAddr& aSmsAddr)
       
   928 	{
       
   929 	LOGSMSPROT1("CSmsProvider::SetLocalAddress");
       
   930 	iLocalAddress = aSmsAddr;
       
   931 	}
       
   932 
       
   933 /**
       
   934  *  Called by the protocol when the modem connection state has changed.
       
   935  *  Notifies any standard KIoctlSelect requests of this event.
       
   936  *  
       
   937  *  @param aStatus either KIoctlSelectModemPresent or KIoctlSelectModemNotPresent.
       
   938  *  
       
   939  */
       
   940 void CSmsProvider::ModemNotificationCompleted(TInt aStatus)
       
   941 	{
       
   942 	LOGSMSPROT2("CSmsProvider::ModemNotificationCompleted [aStatus=%d]", aStatus);
       
   943 
       
   944 	if( !IoctlOutstanding() )
       
   945 	    {
       
   946 		iSocket->Error(aStatus,MSocketNotify::EErrorIoctl);
       
   947 	    }
       
   948 	}
       
   949 
       
   950 /**
       
   951  *  Called by the protocol when a message send request made by this
       
   952  *  SAP has completed.
       
   953  *  
       
   954  *  @param aStatus the result of the send.
       
   955  *  
       
   956  */
       
   957 void CSmsProvider::MessageSendCompleted(TInt aStatus)
       
   958     {
       
   959     LOGSMSPROT2("CSmsProvider::MessageSendCompleted [aStatus=%d]", aStatus);
       
   960     
       
   961     iSocket->Error(aStatus,MSocketNotify::EErrorIoctl);
       
   962     SetIoctlOutstanding(EFalse);
       
   963     }
       
   964 
       
   965 /**
       
   966  *  Called by the protocol when a message has been received for this SAP.
       
   967  *  
       
   968  *  @param aSmsMessage the received message.
       
   969  *  @return KErrNone if the message was serialized to the receive buffer successfully.
       
   970  *  
       
   971  */
       
   972 TInt CSmsProvider::MessageReceived(const CSmsMessage& aSmsMessage,TDes& /*aDes*/)
       
   973     {
       
   974     LOGSMSPROT1("CSmsProvider::MessageReceived");
       
   975     
       
   976     // Attempt to serial the message to the receive buffer & notify
       
   977     // the socket of the new data
       
   978     TInt numnewsegments=0;
       
   979     TRAPD(ret,(numnewsegments=ExternalizeMessageL(aSmsMessage,ETrue)));
       
   980     if( ret==KErrNone )
       
   981         {
       
   982         iSocket->NewData(numnewsegments);
       
   983         }
       
   984     return ret;
       
   985     }
       
   986 
       
   987 /**
       
   988  *  Informs protocol whether client confirms received message
       
   989  */
       
   990 TBool CSmsProvider::ClientConfirmsMessage() const
       
   991     {
       
   992     LOGSMSPROT1("CSmsProvider::ClientConfirmsMessage");
       
   993     
       
   994     return ETrue;
       
   995     }
       
   996 
       
   997 /**
       
   998  *  Informs protocol whether address is ued by the observer
       
   999  */
       
  1000 TInt CSmsProvider::SmsAddrIsDuplicate(const MSmsMessageObserver* aObserver, const TSmsAddr& aAddr) const
       
  1001     {
       
  1002     LOGSMSPROT1("CSmsProvider::SmsAddrIsDuplicate");
       
  1003     
       
  1004     if( this == aObserver )
       
  1005         {
       
  1006         return EFalse;
       
  1007         }
       
  1008     return iLocalAddress==aAddr;
       
  1009     }
       
  1010 
       
  1011 /**
       
  1012  *  Called by the protocol when an enumeration of the phone's message stores
       
  1013  *  requested by this SAP has completed.
       
  1014  *  
       
  1015  *  @param aStatus the result of the enumeration.
       
  1016  *  
       
  1017  */
       
  1018 void CSmsProvider::EnumeratePhoneCompleted(TInt aStatus)
       
  1019     {
       
  1020     LOGSMSPROT2("CSmsProvider::EnumeratePhoneCompleted [aStatus=%d]", aStatus);
       
  1021     
       
  1022     // Attempt to serialize all enumerated messages to the receive buffer
       
  1023     TInt numnewsegments=0;
       
  1024     TInt count=0;
       
  1025     if( aStatus==KErrNone )
       
  1026         {
       
  1027         // Save current message count in case we need to rollback on error
       
  1028         TInt nummessages=iRecvBufSegArray->Count();
       
  1029         TRAP(aStatus, (numnewsegments=ExternalizeEnumeratedMessagesL(count)));
       
  1030         if( aStatus==KErrNone )
       
  1031             {
       
  1032             // Success, obtain the message count and notify socket of the new data
       
  1033             if( numnewsegments>0 )
       
  1034                 {
       
  1035                 iSocket->NewData(numnewsegments);
       
  1036                 }
       
  1037             }
       
  1038         else
       
  1039             {
       
  1040             // Error, rollback the messages we added
       
  1041             for( TInt i=(iRecvBufSegArray->Count()-nummessages)-1; i>=0; i-- )
       
  1042                 {
       
  1043                 delete iRecvBufSegArray->At(i);
       
  1044                 iRecvBufSegArray->Delete(i);
       
  1045                 }
       
  1046             }
       
  1047         }
       
  1048     // On success, complete with the count of messages enumerated
       
  1049     if( aStatus==KErrNone )
       
  1050         {
       
  1051         TPckgBuf<TInt> buf;
       
  1052         buf()=count;
       
  1053         if( count>0 )
       
  1054             {
       
  1055             iEnumSocket=ETrue;
       
  1056             }
       
  1057         else
       
  1058             {
       
  1059             iEnumSocket=EFalse;
       
  1060             iProtocol.iPhoneEnumerationObserver=NULL;
       
  1061             }
       
  1062         iNumOfEnumeratedMessages=count;
       
  1063         iSocket->IoctlComplete(&buf);
       
  1064         }
       
  1065     else
       
  1066         {
       
  1067         iEnumSocket=EFalse;
       
  1068         if( iProtocol.iPhoneEnumerationObserver == this)
       
  1069             {
       
  1070             iProtocol.iPhoneEnumerationObserver=NULL;
       
  1071             }
       
  1072         iSocket->Error(aStatus,MSocketNotify::EErrorIoctl);
       
  1073         }
       
  1074     SetIoctlOutstanding(EFalse);
       
  1075     }
       
  1076 
       
  1077 /**
       
  1078  *  Called by the protocol when a request to write a message to
       
  1079  *  a phone store by this SAP has completed.
       
  1080  *  Implements the pure virtual MSmsMessageObserver::MessageWriteCompleted().
       
  1081  *  
       
  1082  *  @param aStatus the result of the write operation.
       
  1083  *  
       
  1084  */
       
  1085 void CSmsProvider::MessageWriteCompleted(TInt aStatus, const CSmsMessage* aSmsMessage)
       
  1086 	{
       
  1087 	LOGSMSPROT2("CSmsProvider::MessageWriteCompleted [aStatus=%d]", aStatus);
       
  1088 
       
  1089 	// If no errors at present populate the buffer
       
  1090 	if( aStatus == KErrNone )
       
  1091 	    {
       
  1092 		TRAP(aStatus, (PopulateBufferWithPDUSlotsL(*aSmsMessage)));
       
  1093 	    }
       
  1094 	if( aStatus != KErrNone )
       
  1095 		{
       
  1096 		iSocket->Error(aStatus,MSocketNotify::EErrorIoctl);
       
  1097 		}
       
  1098 	SetIoctlOutstanding(EFalse);
       
  1099 	} // CSmsProvider::MessageWriteCompleted
       
  1100 
       
  1101 
       
  1102 /**
       
  1103  *  Create and populate a buffer containing store type and PDU slot indexes
       
  1104  *  
       
  1105  *  @param aSmsMessage the message containing the slot information.
       
  1106  *  
       
  1107  */
       
  1108 void CSmsProvider::PopulateBufferWithPDUSlotsL(const CSmsMessage& aSmsMessage)
       
  1109     {
       
  1110     LOGSMSPROT1("CSmsProvider::PopulateBufferWithPDUSlotsL");
       
  1111     
       
  1112     // Create buffer for store id and PDU slot indexes based on size of slot array
       
  1113     
       
  1114     HBufC8* buf = HBufC8::NewL(aSmsMessage.iSlotArray.Count()+1 * sizeof(TUint));
       
  1115     buf->Des().Append(aSmsMessage.Storage());
       
  1116     
       
  1117     TInt count = aSmsMessage.iSlotArray.Count();
       
  1118     for( TInt index=0; index<count; ++index )
       
  1119         {
       
  1120         buf->Des().Append(aSmsMessage.iSlotArray[index].iIndex);
       
  1121         }
       
  1122     
       
  1123     TPtr8 textBufPtr(buf->Des());
       
  1124     
       
  1125     iSocket->IoctlComplete(&textBufPtr);
       
  1126     delete buf;
       
  1127 
       
  1128     LOGSMSPROT1("-> CSmsProvider::PopulateBufferWithPDUSlotsL - done");
       
  1129     }
       
  1130 
       
  1131 /**
       
  1132  *  Called by the protocol when a request to delete a message from
       
  1133  *  a phone store by this SAP has completed.
       
  1134  *  Implements the pure virtual MSmsMessageObserver::MessageDeleteCompleted().
       
  1135  *  
       
  1136  *  @param aStatus the result of the deletion.
       
  1137  *  
       
  1138  */
       
  1139 void CSmsProvider::MessageDeleteCompleted(TInt aStatus)
       
  1140     {
       
  1141     LOGSMSPROT2("CSmsProvider::MessageDeleteCompleted [aStatus=%d]", aStatus);
       
  1142     iSocket->Error(aStatus,MSocketNotify::EErrorIoctl);
       
  1143     SetIoctlOutstanding(EFalse);
       
  1144     }
       
  1145 
       
  1146 /**
       
  1147  *  Called by the CSmsReadParams object when a read all SMS parameter sets
       
  1148  *  requested by this SAP has completed.
       
  1149  *  
       
  1150  *  @param aStatus the result of the read operation.
       
  1151  *  @param aSmspList SMS parameter list
       
  1152  *  
       
  1153  */
       
  1154 void CSmsProvider::ReadSmsParamsCompleted(TInt aStatus, CMobilePhoneSmspList* aSmspList)
       
  1155     {
       
  1156     LOGSMSPROT2("CSmsProvider::ReadSmsParamsCompleted [aStatus=%d]", aStatus);
       
  1157     
       
  1158     TInt numNewSegments=0;
       
  1159     
       
  1160     if( aStatus == KErrNone )
       
  1161         {
       
  1162         // Attempt to serial the parameters to the receive buffer & notify
       
  1163         // the socket of the new data
       
  1164         __ASSERT_DEBUG(aSmspList != NULL,SmspPanic(KSmspPanicParameterBufferNull));
       
  1165         TRAP(aStatus,(numNewSegments=ExternalizeParametersL(*aSmspList)));
       
  1166         }
       
  1167     if( aStatus == KErrNone )
       
  1168         {
       
  1169         iSocket->NewData(numNewSegments);
       
  1170         TPckgBuf<TInt> buf;
       
  1171         buf()=1;
       
  1172         iSocket->IoctlComplete(&buf);
       
  1173         }
       
  1174     else
       
  1175         {
       
  1176         iSocket->Error(aStatus,MSocketNotify::EErrorIoctl);
       
  1177         }
       
  1178     SetIoctlOutstanding(EFalse);
       
  1179     }
       
  1180 
       
  1181 /**
       
  1182  *  Called by the CSmsWriteParams object when a request to write SMS
       
  1183  *  parameters to a phone store by this SAP has completed.
       
  1184  *  
       
  1185  *  @param aStatus the result of the write operation.
       
  1186  *  
       
  1187  */
       
  1188 void CSmsProvider::WriteSmsParamsCompleted(TInt aStatus)
       
  1189     {
       
  1190     LOGSMSPROT2("CSmsProvider::WriteSmsParamsCompleted [aStatus=%d]", aStatus);
       
  1191     iSocket->Error(aStatus,MSocketNotify::EErrorIoctl);
       
  1192     SetIoctlOutstanding(EFalse);
       
  1193     }
       
  1194 
       
  1195 /**
       
  1196  *  Internal function called after a phone store enumeration request to
       
  1197  *  serialize the messages to the receive buffer.
       
  1198  *  
       
  1199  *  @leave Leaves if any individual ExternalizeMessageL() call leaves.
       
  1200  *  @return the total number of segments the messages were split into.
       
  1201  *  
       
  1202  */
       
  1203 TInt CSmsProvider::ExternalizeEnumeratedMessagesL(TInt& aCount)
       
  1204     {
       
  1205     LOGSMSPROT1("CSmsProvider::ExternalizeEnumeratedMessagesL");
       
  1206     
       
  1207     TInt numnewsegments(0);
       
  1208     numnewsegments=iProtocol.ExternalizeEnumeratedMessagesL(*this,aCount);
       
  1209     
       
  1210     LOGSMSPROT1("-> CSmsProvider::ExternalizeEnumeratedMessagesL - done");
       
  1211     
       
  1212     return numnewsegments;
       
  1213     }
       
  1214 
       
  1215 /**
       
  1216  *  Internal function used to serialize a message into the receive buffer.
       
  1217  *  Each serialized message is split into smaller segments which form the
       
  1218  *  basic unit of data passed back to the socket server in the GetData() method.
       
  1219  *  
       
  1220  *  @param aSmsMessage the message to serialize.
       
  1221  *  @param aAppend specifies whether the message is inserted at the start or end of the buffer.
       
  1222  *  @leave Leaves if the message could not be serialized or inserted into the buffer.
       
  1223  *  @return the number of segments the message was split into.
       
  1224  *  
       
  1225  */
       
  1226 TInt CSmsProvider::ExternalizeMessageL(const CSmsMessage& aSmsMessage,TBool aAppend)
       
  1227     {
       
  1228     LOGSMSPROT1("CSmsProvider::ExternalizeMessageL()");
       
  1229     
       
  1230     // Create a new segmented buffer for the serialization of this message
       
  1231     CBufSeg* recvbufseg = CBufSeg::NewL(KSmsMaxSegmentLength);
       
  1232     CleanupStack::PushL(recvbufseg);
       
  1233     
       
  1234     // Attempt to serialize this message into the buffer
       
  1235     RBufWriteStream writestream(*recvbufseg);
       
  1236     writestream.Open(*recvbufseg);
       
  1237     CleanupClosePushL(writestream);
       
  1238     writestream << aSmsMessage;
       
  1239     
       
  1240     // Append / insert this buffer at the end / start of the other serialized message buffers
       
  1241     if( aAppend )
       
  1242         {
       
  1243         iRecvBufSegArray->AppendL(recvbufseg);
       
  1244         }
       
  1245     else
       
  1246         {
       
  1247         iRecvBufSegArray->InsertL(0,recvbufseg);
       
  1248         }
       
  1249     CleanupStack::PopAndDestroy();  //  writestream
       
  1250     CleanupStack::Pop();            //  recvbufseg
       
  1251     
       
  1252     LOGSMSPROT1("-> CSmsProvider::ExternalizeMessageL - done");
       
  1253     
       
  1254     return NumSegments(recvbufseg->Size());
       
  1255     }
       
  1256 
       
  1257 /**
       
  1258  *  Internal function to deserialize a message from the send buffer.
       
  1259  *  Each serialized message is split into smaller segments which form the basic
       
  1260  *  unit of data passed to this SAP from the socket server in the Write() method.
       
  1261  *  
       
  1262  *  @leave Leaves if the message could not be de-serialized.
       
  1263  *  @return the de-serialized CSmsMessage object.
       
  1264  *  
       
  1265  */
       
  1266 CSmsMessage* CSmsProvider::InternalizeMessageL()
       
  1267     {
       
  1268     LOGSMSPROT1("CSmsProvider::InternalizeMessageL()");
       
  1269     
       
  1270     // Initialize the read stream with the buffer
       
  1271     RBufReadStream readstream(*iSendBufSeg);
       
  1272     readstream.Open(*iSendBufSeg,0);
       
  1273     CleanupClosePushL(readstream);
       
  1274 
       
  1275     // Create a buffer and message to store the result
       
  1276     CSmsBufferBase* buffer = CSmsBuffer::NewL();
       
  1277     CSmsMessage* smsmessage= CSmsMessage::NewL(iProtocol.FileSession(), CSmsPDU::ESmsDeliver,buffer);
       
  1278     CleanupStack::PushL(smsmessage);
       
  1279 
       
  1280     // De-serialize the message from using the read stream
       
  1281     readstream >> *smsmessage;
       
  1282 
       
  1283     CleanupStack::Pop();  //  smsmessage
       
  1284     CleanupStack::PopAndDestroy();  //  readstream
       
  1285     iSendBufSeg->Reset();
       
  1286 
       
  1287     LOGSMSPROT1("-> CSmsProvider::InternalizeMessageL - done");
       
  1288     
       
  1289     return smsmessage;
       
  1290     }
       
  1291 
       
  1292 /**
       
  1293  *  Internal function used to serialize SMS parameters into the receive buffer.
       
  1294  *  Each serialized parameter object is split into smaller segments which form the
       
  1295  *  basic unit of data passed back to the socket server in the GetData() method.
       
  1296  *  
       
  1297  *  @param aMobilePhoneSmspList the parameters to serialize.
       
  1298  *  @leave Leaves if the parameters could not be serialized or inserted into the buffer.
       
  1299  *  @return the number of segments the parameters was split into.
       
  1300  *  
       
  1301  */
       
  1302 TInt CSmsProvider::ExternalizeParametersL(const CMobilePhoneSmspList& aMobilePhoneSmspList)
       
  1303     {
       
  1304     LOGSMSPROT1("CSmsProvider::ExternalizeParametersL");
       
  1305     
       
  1306     // Create a new segmented buffer for the serialization of this message
       
  1307     CBufSeg* recvBufSeg = CBufSeg::NewL(KSmsMaxSegmentLength);
       
  1308     CleanupStack::PushL(recvBufSeg);
       
  1309 
       
  1310     // Attempt to serialize this message into the buffer
       
  1311     RBufWriteStream writeStream(*recvBufSeg);
       
  1312     writeStream.Open(*recvBufSeg);
       
  1313     CleanupClosePushL(writeStream);
       
  1314     writeStream << aMobilePhoneSmspList;
       
  1315     writeStream.CommitL();
       
  1316 
       
  1317     // Append start of the other serialized message buffers
       
  1318     CleanupStack::PopAndDestroy();	//writeStream
       
  1319     iRecvBufSegArray->InsertL(0,recvBufSeg);
       
  1320     CleanupStack::Pop(recvBufSeg);
       
  1321 
       
  1322     LOGSMSPROT1("-> CSmsProvider::ExternalizeParametersL - done");
       
  1323     
       
  1324     return NumSegments(recvBufSeg->Size());
       
  1325     }
       
  1326 
       
  1327 /**
       
  1328  *  Internal function to retrieve a SMS parameters from the send buffer.
       
  1329  *  Each serialized object is split into smaller segments which form the basic
       
  1330  *  unit of data passed to this SAP from the socket server in the Write() method.
       
  1331  *  
       
  1332  *  @leave Leaves if the parameters could not retrieved.
       
  1333  *  @return the retrieved CMobilePhoneSmspList object.
       
  1334  *  
       
  1335  */
       
  1336 CMobilePhoneSmspList* CSmsProvider::InternalizeParametersL()
       
  1337     {
       
  1338     LOGSMSPROT1("CSmsProvider::InternalizeParametersL");
       
  1339     
       
  1340     // Initialize the read stream with the buffer
       
  1341     RBufReadStream readStream(*iSendBufSeg);
       
  1342     readStream.Open(*iSendBufSeg,0);
       
  1343     CleanupClosePushL(readStream);
       
  1344 
       
  1345     // Create a parameter object to store the result
       
  1346     CMobilePhoneSmspList* mobilePhoneSmspList = CMobilePhoneSmspList::NewL();
       
  1347     CleanupStack::PushL(mobilePhoneSmspList);
       
  1348 
       
  1349     // De-serialize the message from using the read stream
       
  1350     readStream >> *mobilePhoneSmspList;
       
  1351 
       
  1352     CleanupStack::Pop(mobilePhoneSmspList);
       
  1353     CleanupStack::PopAndDestroy();	//readStream
       
  1354     iSendBufSeg->Reset();
       
  1355 
       
  1356     LOGSMSPROT1("-> CSmsProvider::InternalizeParametersL - done");
       
  1357     
       
  1358     return mobilePhoneSmspList;
       
  1359     }
       
  1360 
       
  1361 CSmsMessage* CSmsProvider::InternalizeMessageL(	CBufSeg* aBufSeg)
       
  1362     {
       
  1363     LOGSMSPROT1("CSmsProvider::InternalizeMessageL");
       
  1364     
       
  1365     RBufReadStream readstream(*aBufSeg);
       
  1366     readstream.Open(*aBufSeg,0);
       
  1367     CleanupClosePushL(readstream);
       
  1368     CSmsBufferBase* buffer = CSmsBuffer::NewL();
       
  1369     CSmsMessage* smsmessage= CSmsMessage::NewL(iProtocol.FileSession(),CSmsPDU::ESmsDeliver,buffer);
       
  1370     
       
  1371     CleanupStack::PushL(smsmessage);
       
  1372     readstream >> *smsmessage;
       
  1373     
       
  1374     CleanupStack::Pop();  //  smsmessage
       
  1375     CleanupStack::PopAndDestroy();  //  readsream
       
  1376     
       
  1377     LOGSMSPROT1("-> CSmsProvider::InternalizeMessageL - done");
       
  1378     
       
  1379     return smsmessage;
       
  1380     }
       
  1381 
       
  1382 TInt CSmsProvider::SecurityCheck(MProvdSecurityChecker* aSecurityChecker)
       
  1383     {
       
  1384     LOGSMSPROT1("CSmsProvider::SecurityCheck");
       
  1385     iSecurityChecker = aSecurityChecker;
       
  1386     return KErrNone;
       
  1387     }