atext/server/src/atextsession.cpp
changeset 0 29b1cd4cb562
child 16 9f17f914e828
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atext/server/src/atextsession.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,1086 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include <badesca.h>
+#include <atextpluginbase.h>
+#include <atext.h>
+#include "atextsrv.h"
+#include "atextclientsrv.h"
+#include "atextsession.h"
+#include "utils.h"
+#include "debug.h"
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CATExtSession* CATExtSession::NewL( CATExtSrv& aServer,
+                                    const TVersion& aVersion )
+    {
+    return new (ELeave) CATExtSession( aServer, aVersion );
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CATExtSession::~CATExtSession()
+    {
+    TRACE_FUNC_ENTRY
+    Destruct( EFalse );
+    TRACE_FUNC_EXIT
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of client requests passed to the server
+// ---------------------------------------------------------------------------
+//
+void CATExtSession::ServiceL( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( iVersion.iMajor==KServerMajorVersionNumber &&
+         iVersion.iMinor==KServerMinorVersionNumber &&
+         iVersion.iBuild==KServerBuildVersionNumber )
+        {
+        DoServiceL( aMessage );
+        }
+    else
+        {
+        aMessage.Complete( KErrNotSupported );
+        }
+    TRACE_FUNC_EXIT
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of client requests passed to the server
+// ---------------------------------------------------------------------------
+//
+void CATExtSession::DoServiceL( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    switch ( aMessage.Function() )
+        {
+        case EATExtSetExtensionInterface:
+            {
+            TRAPD( retTrap, IpcSetInterfaceL(aMessage) );
+            if ( retTrap != KErrNone )
+                {
+                aMessage.Complete( retTrap );
+                }
+            else if ( !iMetadata->SupportExists() )
+                {
+                aMessage.Complete( KErrNotFound );
+                }
+            else
+                {
+                aMessage.Complete( KErrNone );
+                }
+            break;
+            }
+        case EATExtSynchronousClose:
+            {
+            IpcSynchronousClose( aMessage );
+            }
+            break;
+        case EATExtHandleCommand:
+            {
+            IpcHandleCommand( aMessage );
+            break;
+            }
+        case EATExtCancelHandleCommand:
+            {
+            IpcCancelHandleCommand( aMessage );
+            break;
+            }
+        case EATExtGetNextPartOfReply:
+            {
+            IpcGetNextPartOfReply( aMessage );
+            break;
+            }
+        case EATExtNumberOfPlugins:
+            {
+            IpcNumberOfPlugins( aMessage );
+            }
+            break;
+        case EATExtReceiveUnsolicitedResult:
+            {
+            IpcReceiveUnsolicitedResult( aMessage );
+            break;
+            }
+        case EATExtCancelReceiveUnsolicitedResult:
+            {
+            IpcCancelReceiveUrc( aMessage );
+            break;
+            }
+        case EATExtMarkUrcHandlingOwnership:
+            {
+            IpcMarkUrcHandlingOwnership( aMessage );
+            break;
+            }
+        case EATExtReceiveEcomPluginChange:
+            {
+            IpcReceiveEcomPluginChange( aMessage );
+            }
+            break;
+        case EATExtCancelReceiveEcomPluginChange:
+            {
+            IpcCancelReceiveEcomPluginChange( aMessage );
+            }
+            break;
+        case EATExtReportQuietModeChange:
+            {
+            IpcReportQuietModeChange( aMessage );
+            }
+            break;
+        case EATExtReportVerboseModeChange:
+            {
+            IpcReportVerboseModeChange( aMessage );
+            }
+            break;
+        case EATExtReportCharacterChange:
+            {
+            IpcReportCharacterChange( aMessage );
+            }
+            break;
+        case EATExtReportListenerUpdateReady:
+            {
+            IpcReportListenerUpdateReady( aMessage );
+            }
+            break;
+        case EATExtBroadcastNvramStatusChange:
+            {
+            IpcBroadcastNvramStatusChange( aMessage );
+            }
+            break;
+        case EATExtReportExternalHandleCommandError:
+            {
+            IpcReportExternalHandleCommandError( aMessage );
+            }
+            break;
+        case EATExtReportHandleCommandAbort:
+            {
+            IpcReportHandleCommandAbort( aMessage );
+            }
+            break;
+        case EATExtGetNextSpecialCommand:
+            {
+            IpcGetNextSpecialCommand( aMessage );
+            }
+            break;
+        default:
+            {
+            aMessage.Complete( KErrNotSupported );
+            break;
+            }
+        }
+    TRACE_FUNC_EXIT
+    }
+
+// ---------------------------------------------------------------------------
+// CATExtSession::CATExtSession
+// ---------------------------------------------------------------------------
+//
+CATExtSession::CATExtSession( CATExtSrv& aServer, const TVersion& aVersion ) :
+    iServer( aServer ),
+    iListener( NULL ),
+    iMetadata( NULL ),
+    iVersion( aVersion )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of setting up interface
+// ---------------------------------------------------------------------------
+//
+void CATExtSession::IpcSetInterfaceL( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( iMetadata || iListener )
+        {
+        TRACE_FUNC_EXIT
+        User::Leave( KErrGeneral );
+        }
+    REComSession& ecomSession = REComSession::OpenL();
+    CleanupClosePushL( ecomSession );
+    TPckgBuf<TUid> ifUidPckgBuf;
+    TInt retTemp = ReadStructFromMessage( ifUidPckgBuf,
+                                          EATExtConnectParamUid,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        TRACE_FUNC_EXIT
+        User::Leave( retTemp );
+        }
+    RBuf8 connectionName;
+    CleanupClosePushL( connectionName );
+    retTemp = ReadStringFromMessage( connectionName,
+                                     EATExtConnectParamName,
+                                     aMessage );
+    if ( retTemp != KErrNone )
+        {
+        TRACE_FUNC_EXIT
+        User::Leave( retTemp );
+        }
+    // Create listener
+    CATExtListen* listener = CATExtListen::NewLC( ecomSession, this );
+    listener->AddInterfaceUid( ifUidPckgBuf() );
+    // Create metadata. Pass iListener to add the UIDs
+    CATExtMetadata* metadata = CATExtMetadata::NewLC( ecomSession,
+                                                      listener,
+                                                      *this );
+    metadata->CreateImplementationMetadataL( ifUidPckgBuf(), connectionName );
+    listener->IssueRequest();
+    CleanupStack::Pop( metadata );
+    CleanupStack::Pop( listener );
+    CleanupStack::PopAndDestroy( &connectionName );
+    CleanupStack::Pop( &ecomSession );
+    iEComSession = ecomSession;
+    iListener = listener;
+    iMetadata = metadata;
+    TRACE_FUNC_EXIT
+    }
+
+// ---------------------------------------------------------------------------
+// Synchronously closes the session
+// Optional: client can do either Close() or SynchronousClose()
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcSynchronousClose( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    Destruct( ETrue );
+    aMessage.Complete( KErrNone );
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of AT commands
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcHandleCommand( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    if ( aMessage.GetDesMaxLength(EATExtHandleCmdParamReply) !=
+         KDefaultCmdBufLength )
+        {
+        aMessage.Complete( KErrBadDescriptor );
+        TRACE_FUNC_EXIT
+        return KErrBadDescriptor;
+        }
+    TATExtCompletionInfo complInfo;
+    complInfo.iProcessed = EFalse;
+    complInfo.iReplyExpected = EFalse;
+    TInt retTemp = iMetadata->HandleCommand( aMessage, complInfo );
+    if ( retTemp != KErrNone )
+        {
+        TRACE_INFO(( _L8("Command handled with failure %d"), retTemp ));
+        iMetadata->CompleteCommandMessage( NULL,
+                                           retTemp,
+                                           EFalse,               // no error reply
+                                           EReplyTypeUndefined,  // general error condition
+                                           EFalse );             // no multipart
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    // Next check the case without support: in this case a reply
+    // can't be expected but return the "ERROR" anyway if needed.
+    if ( !complInfo.iProcessed )
+        {
+        // Return "ERROR".
+        TRACE_INFO(( _L8("Command handled without support: return \"ERROR\"") ));
+        iMetadata->CompleteCommandMessage( NULL,
+                                           KErrNone,
+                                           ETrue,            // error reply
+                                           EReplyTypeError,  // error type
+                                           EFalse );         // no multipart
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    // Third, check a case where there is support but reply is not
+    // expected. In this case "" must be returned to complete processing.
+    if ( !complInfo.iReplyExpected )
+        {
+        // Return ""
+        TRACE_INFO(( _L8("Command handled with support but no reply: return \"\"") ));
+        iMetadata->CompleteCommandMessage( NULL,
+                                           KErrNone,
+                                           EFalse,           // no error reply
+                                           EReplyTypeOther,  // reply type from plugin
+                                           EFalse );         // no multipart
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    // The rest are for known command with reply. This case is handled in
+    // HandleCommand().
+    TRACE_INFO(( _L8("Command handled: wait for asynchronous reply or do nothing") ));
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of pending AT command cancel
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcCancelHandleCommand( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->CancelHandleCommand();
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of getting the next part of a reply for
+// IpcHandleCommand().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcGetNextPartOfReply( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retTemp = iMetadata->GetNextPartOfReply( aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    // Note: Completed in metadata if successfull
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of number of plugins. This information is needed to
+// instantiate one or more listeners by the user of the client.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcNumberOfPlugins( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->NumberOfPlugins();
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of receiving unsolicited result codes. Note that
+// IpcMarkUrcHandlingOwnership() must be called immediately after this in
+// order for the message to receive their destination.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReceiveUnsolicitedResult( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    if ( aMessage.GetDesMaxLength(EATExtReceiveUrcCmdParamBuf) !=
+         KDefaultUrcBufLength )
+        {
+        aMessage.Complete( KErrBadDescriptor );
+        TRACE_FUNC_EXIT
+        return KErrBadDescriptor;
+        }
+    TPckgBuf<TUid> pluginUidPckgBuf;
+    TInt retTemp = ReadStructFromMessage( pluginUidPckgBuf,
+                                          EATExtReceiveUrcCmdParamUid,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TRAPD( retTrap, iMetadata->StartUrcReceivingL(aMessage,pluginUidPckgBuf()) );
+    if ( retTrap != KErrNone )
+        {
+        aMessage.Complete( retTrap );
+        TRACE_FUNC_EXIT
+        return retTrap;
+        }
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of pending receiving unsolicited result code cancel
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcCancelReceiveUrc( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TPckgBuf<TUid> pluginUidPckgBuf;
+    TInt retTemp = ReadStructFromMessage( pluginUidPckgBuf,
+                                          EATExtCancelReceiveUrcCmdParamUid,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TInt retVal = iMetadata->CancelUrcReceiving( pluginUidPckgBuf() );
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of marking URC handling ownership. Call to this
+// function must be done immediately after the call to
+// IpcReceiveUnsolicitedResult().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcMarkUrcHandlingOwnership( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->MarkUrcHandlingOwnership( aMessage );
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of ECOM plugin change notifications
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReceiveEcomPluginChange( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    if ( iEcomStatusMessage.Handle() )
+        {
+        aMessage.Complete( KErrBadHandle );
+        TRACE_FUNC_EXIT
+        return KErrBadHandle;
+        }
+    iEcomStatusMessage = aMessage;
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of pending ECOM plugin change notification cancel
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcCancelReceiveEcomPluginChange(
+    const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    if ( !iEcomStatusMessage.Handle() )
+        {
+        aMessage.Complete( KErrBadHandle );
+        TRACE_FUNC_EXIT
+        return KErrBadHandle;
+        }
+    iEcomStatusMessage.Complete( KErrCancel );
+    aMessage.Complete( KErrNone );
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of quiet mode change reporting. When quiet mode is on
+// the behavior is the same as with AT command "ATQ1: Result code
+// suppression". When quiet mode is on then verbose mode setting has no
+// effect.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReportQuietModeChange( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TPckgBuf<TBool> quietModePckgBuf;
+    TInt retTemp = ReadStructFromMessage( quietModePckgBuf,
+                                          EATExtReportQuietModeChangeParamMode,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    iMetadata->SetQuietMode( quietModePckgBuf() );
+    aMessage.Complete( KErrNone );
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of verbose mode change reporting. When verbose mode
+// is on the behavior is the same as with AT command "ATV1: DCE Response
+// format". If quiet mode is on then this setting has no effect.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReportVerboseModeChange( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TPckgBuf<TBool> verboseModePckgBuf;
+    TInt retTemp = ReadStructFromMessage( verboseModePckgBuf,
+                                          EATExtReportVerboseModeChangeParamMode,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    iMetadata->SetVerboseMode( verboseModePckgBuf() );
+    aMessage.Complete( KErrNone );
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of character change reporting. The change to carriage
+// return, line feed and backspace characters is reported to
+// CATExtPluginBase's protected data so that the it can easily be used by the
+// plugin implementation.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReportCharacterChange( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TPckgBuf<TATExtensionCharType> charTypePckgBuf;
+    TInt retTemp = ReadStructFromMessage( charTypePckgBuf,
+                                          EATExtReportCharacterChangeParamType,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TPckgBuf<TInt8> charPckgBuf;
+    retTemp = ReadStructFromMessage( charPckgBuf,
+                                     EATExtReportCharacterChangeParamChar,
+                                     aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TInt retVal = iMetadata->SetCharacterValue( charTypePckgBuf(),
+                                                charPckgBuf() );
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of reporting listener update readiness. Client side
+// listener has to use this after it has updates its own internal states after
+// ECOM plugin change notification.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReportListenerUpdateReady( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TPckgBuf<TUid> pluginUidPckgBuf;
+    TInt retTemp = ReadStructFromMessage( pluginUidPckgBuf,
+                                          EATExtReportListenerUpdateParamUid,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TPckgBuf<TATExtensionEcomType> updateTypePckgBuf;
+    retTemp = ReadStructFromMessage( updateTypePckgBuf,
+                                     EATExtReportListenerUpdateParamType,
+                                     aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TInt retVal = KErrNone;
+    switch ( updateTypePckgBuf() )
+        {
+        case EEcomTypeUninstall:
+            // 3. When client notifies of removal, remove the locked entry from metadata.
+            // See also NotifyPluginUninstallation()
+            retVal = iMetadata->RemoveImplementation( pluginUidPckgBuf() );
+            break;
+        case EEcomTypeInstall:
+            // 4. When client notifies installation, remove the lock from metadata.
+            // See also NotifyPluginInstallation()
+            retVal = iMetadata->UnlockPluginAccess( pluginUidPckgBuf() );
+            break;
+        default:
+            retVal = KErrNotSupported;
+            break;
+        }
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of NVRAM status change broadcasting. The NVRAM status
+// change is broadcasted to all of the plugins.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcBroadcastNvramStatusChange( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    RBuf8 nvramStatus;
+    TInt retTemp = ReadStringFromMessage( nvramStatus,
+                                          EATExtBroadcastNvramChangeParamNvram,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        nvramStatus.Close();
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TInt retVal = iMetadata->BroadcastNvramStatusChange( nvramStatus );
+    aMessage.Complete( retVal );
+    nvramStatus.Close();
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of reporting about external handle command error
+// condition.
+// This is for cases when for example DUN decided the reply contained an
+// error condition but the plugin is still handling the command internally.
+// Example: "AT+TEST;+TEST2" was given in command line; "AT+TEST" returns
+// non-EReplyTypeError condition and "AT+TEST2" returns EReplyTypeError.
+// As the plugin(s) returning the non-EReplyTypeError may still have some
+// ongoing operation then these plugins are notified about the external
+// EReplyTypeError in command line processing. It is to be noted that
+// HandleCommandCancel() is not sufficient to stop the processing as the
+// command handling has already finished.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReportExternalHandleCommandError(
+    const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->ReportExternalHandleCommandError();
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of reporting about abort condition in command
+// handling.
+// This is for cases when for example DUN decided an abort condition was
+// received from DTE (ITU-T V.250 5.6.1). This API is for notifying the
+// plugin that abort was requested. However the plugin currently handling
+// the command may ignore the request if it doesn't support abort for the
+// command or it may return the changed condition with
+// HandleCommandCompleted()
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcReportHandleCommandAbort( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->ReportHandleCommandAbort( aMessage );
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Handles the servicing of getting the next special command RSS file entry.
+// These commands are commands with a matching start but with any ending
+// sequence. Command "ATD*99***1#" is one of these and the number of these
+// commands should be kept minimal.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::IpcGetNextSpecialCommand( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        aMessage.Complete( KErrGeneral );
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TPckgBuf<TBool> firstSearchPckgBuf;
+    TInt retTemp = ReadStructFromMessage( firstSearchPckgBuf,
+                                          EATExtGetNextSpecialCmdParamFirst,
+                                          aMessage );
+    if ( retTemp != KErrNone )
+        {
+        aMessage.Complete( retTemp );
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    TInt retVal = iMetadata->GetNextSpecialCommand( aMessage,
+                                                    firstSearchPckgBuf() );
+    aMessage.Complete( retVal );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Reads a string from a message
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::ReadStringFromMessage( RBuf8& aBuffer,
+                                           TInt aDataSlot,
+                                           const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    TInt retVal = KErrNone;
+    TInt desLength = aMessage.GetDesLength( aDataSlot );
+    if ( desLength <= 0 )
+        {
+        TRACE_FUNC_EXIT
+        return KErrArgument;
+        }
+    retVal = aBuffer.Create( desLength );
+    if ( retVal == KErrNone )
+        {
+        retVal = aMessage.Read( aDataSlot, aBuffer );
+        TRACE_INFO(( _L("Read returned %d"), retVal ));
+        }
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Reads a struct from a message
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::ReadStructFromMessage( TDes8& aBuffer,
+                                           TInt aDataSlot,
+                                           const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    TInt retVal = KErrNone;
+    TInt desLength = aMessage.GetDesLength( aDataSlot );
+    if ( desLength <= 0 )
+        {
+        TRACE_FUNC_EXIT
+        return KErrArgument;
+        }
+    retVal = aMessage.Read( aDataSlot, aBuffer );
+    TRACE_INFO(( _L("Read returned %d"), retVal ));
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructs objects/associations for the current session
+// ---------------------------------------------------------------------------
+//
+void CATExtSession::Destruct( TBool aSyncClose )
+    {
+    TRACE_FUNC_ENTRY
+    if ( iEcomStatusMessage.Handle() )
+        {
+        iEcomStatusMessage.Complete( KErrServerTerminated );
+        }
+    delete iListener;
+    iListener = NULL;
+    delete iMetadata;
+    iMetadata = NULL;
+    iEComSession.Close();
+    if ( !aSyncClose )
+        {
+        REComSession::FinalClose();
+        iServer.ClientClosed( *this );
+        }
+    TRACE_FUNC_EXIT
+    }
+
+// ---------------------------------------------------------------------------
+// From MATExtPluginObserver.
+// Called by extension plugins when there is an unsolicited result code
+// should be sent to destination.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::SendUnsolicitedResult( CATExtPluginBase* aPlugin,
+                                           const TDesC8& aAT )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    iMetadata->CompleteUrcMessage( aAT, aPlugin );
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// From MATExtPluginObserver.
+// Called by Extension Plugins to inform ATEXT that a command handling has
+// been completed or rejected.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::HandleCommandCompleted( CATExtPluginBase* aPlugin,
+                                            TInt aError,
+                                            TATExtensionReplyType aReplyType )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->CompleteCommandMessage( aPlugin,
+                                                     aError,
+                                                     EFalse,      // no error reply
+                                                     aReplyType,  // type of reply
+                                                     ETrue );     // multipart
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// From MATExtPluginObserver.
+// Called by concrete extension plugin to inform the array of supported
+// commands should be returned
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::GetSupportedCommands( CATExtPluginBase* aPlugin,
+                                          RPointerArray<HBufC8>& aCmds )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->GetSupportedCommands( aPlugin, aCmds );
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// From MATExtPluginObserver.
+// Called by the destructor of CATExtPluginBase. A concrete service provider
+// implementation should not touch this.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::ATExtPluginClosed( CATExtPluginBase* aPlugin )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    TInt retVal = iMetadata->RemoveImplementationInstance( aPlugin );
+    // "delete this" used in plugin. Plugin must cancel asynchronous
+    // operations in its destructor to complete iCommandMessage and
+    // iUnsolicitedMessage
+    TRACE_FUNC_EXIT
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MATExtListen.
+// Notifies about an installed plugin.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::NotifyPluginInstallation(
+    TUid& /*aIfUid*/,
+    CImplementationInformation* aImplInfo )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata || !aImplInfo )
+        {
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    // 1. Add the new UID to metadata.
+    TRAPD( retTrap, iMetadata->AddImplementationL( aImplInfo ) );
+    if ( retTrap != KErrNone )
+        {
+        TRACE_FUNC_EXIT
+        return retTrap;
+        }
+    // 2. Lock the entry in metadata.
+    TUid pluginUid = aImplInfo->ImplementationUid();
+    TInt retTemp = iMetadata->LockPluginAccess( pluginUid );
+    if ( retTemp != KErrNone )
+        {
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    // 3. Notify client of installation.
+    if ( iEcomStatusMessage.Handle() )
+        {
+        TPckg<TUid> pluginUidPckg( pluginUid );
+        retTemp = iEcomStatusMessage.Write(
+            EATExtReceiveEcomPluginChangeParamUid,
+            pluginUidPckg );
+        TRACE_INFO(( _L("Write returned %d"), retTemp ));
+        TPckg<TATExtensionEcomType> ecomType( EEcomTypeInstall );
+        retTemp = iEcomStatusMessage.Write(
+            EATExtReceiveEcomPluginChangeParamType,
+            ecomType );
+        TRACE_INFO(( _L("Write returned %d"), retTemp ));
+        iEcomStatusMessage.Complete( KErrNone );
+        }
+    // 4. When client notifies installation, remove the lock from metadata.
+    // See IpcReportListenerUpdateReady() for this.
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// From MATExtListen.
+// Notifies about an uninstalled plugin.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtSession::NotifyPluginUninstallation( TUid& /*aIfUid*/,
+                                                TUid& aPluginUid )
+    {
+    TRACE_FUNC_ENTRY
+    if ( !iMetadata )
+        {
+        TRACE_FUNC_EXIT
+        return KErrGeneral;
+        }
+    // 1. Lock the access to metadata from the responsible plugin UID.
+    TInt retTemp = iMetadata->LockPluginAccess( aPluginUid );
+    if ( retTemp != KErrNone )
+        {
+        TRACE_FUNC_EXIT
+        return retTemp;
+        }
+    // 2. Notify client of removal.
+    if ( iEcomStatusMessage.Handle() )
+        {
+        TPckg<TUid> pluginUid( aPluginUid );
+        retTemp = iEcomStatusMessage.Write(
+            EATExtReceiveEcomPluginChangeParamUid,
+            pluginUid );
+        TRACE_INFO(( _L("Write returned %d"), retTemp ));
+        TPckg<TATExtensionEcomType> ecomType( EEcomTypeUninstall );
+        retTemp = iEcomStatusMessage.Write(
+            EATExtReceiveEcomPluginChangeParamType,
+            ecomType );
+        TRACE_INFO(( _L("Write returned %d"), retTemp ));
+        iEcomStatusMessage.Complete( KErrNone );
+        }
+    // 3. When client notifies of removal, remove the locked entry from metadata.
+    // See IpcReportListenerUpdateReady() for this.
+    TRACE_FUNC_EXIT
+    return KErrNone;
+    }