bluetoothengine/btnotif/btnotifsrv/src/btnotifsession.cpp
changeset 31 a0ea99b6fa53
parent 29 48ae3789ce00
child 40 997690c3397a
equal deleted inserted replaced
30:df7a93ede42e 31:a0ea99b6fa53
     1 /*
     1 /*
     2 * ============================================================================
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3 *  Name        : btnotifsession.cpp
     3 * All rights reserved.
     4 *  Part of     : bluetoothengine / btnotif
     4 * This component and the accompanying materials are made available
     5 *  Description : Session class for handling commands from clients.
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 *
     8 *
     7 *  Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies).
     9 * Initial Contributors:
     8 *  All rights reserved.
    10 * Nokia Corporation - initial contribution.
     9 *  This component and the accompanying materials are made available
       
    10 *  under the terms of "Eclipse Public License v1.0"
       
    11 *  which accompanies this distribution, and is available
       
    12 *  at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    13 *
    11 *
    14 *  Initial Contributors:
    12 * Contributors:
    15 *  Nokia Corporation - initial contribution.
       
    16 *
    13 *
    17 *  Contributors:
    14 * Description: Session class for handling commands from clients.
    18 *  Nokia Corporation
    15 *
    19 * ============================================================================
       
    20 * Template version: 4.1
       
    21 */
    16 */
    22 
    17 
    23 #include "btnotifsession.h"
    18 #include "btnotifsession.h"
    24 #include <btextnotifiers.h>
    19 #include <btextnotifiers.h>
       
    20 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    21 #include <btextnotifierspartner.h>
       
    22 #endif
    25 #include "btnotifclientserver.h"
    23 #include "btnotifclientserver.h"
    26 #include "btnotifsettingstracker.h"
    24 #include "btnotifsettingstracker.h"
    27 #include "btnotifconnectiontracker.h"
    25 #include "btnotifconnectiontracker.h"
    28 #include "btnotifdeviceselector.h"
    26 #include "btnotifdeviceselector.h"
    29 
    27 
    79 // Destructor
    77 // Destructor
    80 // ---------------------------------------------------------------------------
    78 // ---------------------------------------------------------------------------
    81 //
    79 //
    82 CBTNotifSession::~CBTNotifSession()
    80 CBTNotifSession::~CBTNotifSession()
    83     {
    81     {
    84     for( TInt i = 0; i < iMessageQ.Count(); i++ )
    82     // clients must complete the message they are responsible for
    85         {
    83     // we do not complete any message here
    86         // Complete all outstanding messages with error code
       
    87         iMessageQ[i].Complete( KErrSessionClosed );
       
    88         }
       
    89     iMessageQ.Close();  // Cleans up all message objects.
       
    90     Server()->RemoveSession();
    84     Server()->RemoveSession();
    91     }
    85     }
    92 
    86 
    93 // ---------------------------------------------------------------------------
    87 // ---------------------------------------------------------------------------
    94 // From class CSession2.
    88 // From class CSession2.
    95 // Receives a message from a client.
    89 // Receives a message from a client.
    96 // ---------------------------------------------------------------------------
    90 // ---------------------------------------------------------------------------
    97 //
    91 //
    98 void CBTNotifSession::ServiceL( const RMessage2& aMessage )
    92 void CBTNotifSession::ServiceL( const RMessage2& aMessage )
    99     {
    93     {
       
    94     CBTNotifConnectionTracker* connTracker = Server()->ConnectionTracker();
   100     TInt opCode = aMessage.Function();
    95     TInt opCode = aMessage.Function();
   101     if ( opCode == EBTNotifCancelNotifier || 
    96     TInt uid = aMessage.Int0();
   102          opCode == EBTNotifStartSyncNotifier ||
    97     TInt err( KErrNotReady );
   103          opCode == EBTNotifStartAsyncNotifier ||
    98     switch(opCode){
   104          opCode == EBTNotifUpdateNotifier )
    99         case EBTNotifCancelNotifier:
   105         {
   100         case EBTNotifStartSyncNotifier:
   106         TInt uid = aMessage.Int0();
   101         case EBTNotifStartAsyncNotifier:
   107         if( uid == KDeviceSelectionNotifierUid.iUid )
   102         case EBTNotifUpdateNotifier:
   108             {
   103             if( uid == KDeviceSelectionNotifierUid.iUid )
   109             // Note for implementers:
   104                 {
   110             // message queue is not used in this notifier handling (due
   105                 TRAP( err, {
   111             // to its drawbacks for exception handlings in various situations). 
   106                         CBTNotifDeviceSelector& selector = Server()->DeviceSelectorL();
   112             // implementations using message queue will be migrated step
   107                         selector.DispatchNotifierMessageL( aMessage ); }
   113             // by step.
   108                         );
   114         
   109                 if ( err )
   115             TRAPD( err, {
   110                     {
   116                 CBTNotifDeviceSelector& selector = Server()->DeviceSelectorL();
   111                     aMessage.Complete( err );
   117                 selector.DispatchNotifierMessageL( aMessage ); }
   112                     }
   118                 );
   113                     // deviceselector takes the ownership of aMessage.
       
   114                 }
       
   115             else
       
   116                 {
       
   117                 // PIN/ SSP pairing notifiers from BT stack:
       
   118                 // ***** Note for implementers:
       
   119                 // message queue is not used for this notifier handling.
       
   120                 if ( uid == KBTManAuthNotifierUid.iUid ||
       
   121                      uid == KBTManPinNotifierUid.iUid ||
       
   122                      uid == KBTPinCodeEntryNotifierUid.iUid ||
       
   123                      uid == KBTNumericComparisonNotifierUid.iUid ||
       
   124                      uid == KBTPasskeyDisplayNotifierUid.iUid ||
       
   125                      uid == KBTUserConfirmationNotifierUid.iUid )
       
   126                     {
       
   127                     if( connTracker )
       
   128                         {
       
   129                          // Pass it to the connection tracker.
       
   130                          TRAP( err, 
       
   131                                  connTracker->HandlePairingNotifierRequestL( aMessage ) );
       
   132                         }
       
   133                     if ( err )
       
   134                         {
       
   135                         // tracker not available, can't do this now.
       
   136                         aMessage.Complete( err );
       
   137                         }
       
   138                     }
       
   139                 }
       
   140             break;
       
   141         case EBTNotifPairDevice:
       
   142         case EBTNotifCancelPairDevice:
       
   143             // Pairing requests from clients:
       
   144             if ( connTracker )
       
   145                 {
       
   146                 TRAP( err, connTracker->HandleBondingRequestL( aMessage ) );
       
   147                 }
   119             if ( err )
   148             if ( err )
   120                 {
   149                 {
   121                 aMessage.Complete( err );
   150                 // tracker not available, can't do this now.
       
   151                 aMessage.Complete( err );            
   122                 }
   152                 }
   123             // deviceselector takes the ownership of aMessage.
   153             break;
   124             return;
   154         default:
   125             }
   155             aMessage.Complete( KErrNotSupported );
   126         }
   156             break;
   127 
       
   128     // Messages are completed by message handlers, not here.
       
   129     // Queue the message already so that handlers can find it from the queue.
       
   130     iMessageQ.AppendL( aMessage );
       
   131     // The position is assumed to not change during the execution of this function.
       
   132     TInt handle = aMessage.Handle();    // Store the handle for de-queueing
       
   133     TRAPD( err, DispatchMessageL( aMessage ) );
       
   134     if( err || ( aMessage.IsNull() && FindMessageFromHandle( handle ) ) )
       
   135         {
       
   136         // If the message has been completed by now (handle is null and the message 
       
   137         // still in the queue), we remove it again from the queue. Otherwise it 
       
   138         // will be completed by the handling handler when it has handled the handling.
       
   139         for( TInt i = 0; i < iMessageQ.Count(); i++ )
       
   140             {
       
   141             // This may be replaced by RArray::Find with appropriate key
       
   142             if( iMessageQ[i].Handle() == handle )
       
   143                 {
       
   144                 iMessageQ.Remove( i );
       
   145                 }
       
   146             }
       
   147         }
       
   148     if( err && !aMessage.IsNull() )
       
   149         {
       
   150         aMessage.Complete( err );
       
   151         }
       
   152     }
   157     }
       
   158 }
   153 
   159 
   154 
   160 
   155 // ---------------------------------------------------------------------------
   161 // ---------------------------------------------------------------------------
   156 // From class CSession2.
   162 // From class CSession2.
   157 // Completes construction of the session.
   163 // Completes construction of the session.
   160 void CBTNotifSession::CreateL()
   166 void CBTNotifSession::CreateL()
   161     {
   167     {
   162     Server()->AddSession();
   168     Server()->AddSession();
   163     }
   169     }
   164 
   170 
   165 // ---------------------------------------------------------------------------
       
   166 // Complete a client message from a message handle with given data.
       
   167 // If a zero-length descriptor is passed, no data will be written back.
       
   168 // ---------------------------------------------------------------------------
       
   169 //
       
   170 TInt CBTNotifSession::CompleteMessage( TInt aHandle, TInt aReason, const TDesC8& aReply )
       
   171     {
       
   172     TInt err = KErrNotFound;
       
   173     // This may be replaced by RArray::Find with appropriate key
       
   174     for( TInt i = 0; i < iMessageQ.Count(); i++ )
       
   175         {
       
   176         if( iMessageQ[i].Handle() == aHandle )
       
   177             {
       
   178             err = KErrNone;
       
   179             if( aReply.Length() )
       
   180                 {
       
   181                 // For now, assume a fixed index for the result.
       
   182                 // Change this if a the client can pass more arguments!
       
   183                 // ToDo: replace with constant!
       
   184                 err = iMessageQ[i].Write( EBTNotifSrvReplySlot, aReply );
       
   185                 // Should the result be passed back to the calller,
       
   186                 // or used to complete the message?
       
   187                 }
       
   188             iMessageQ[i].Complete( aReason );
       
   189             iMessageQ.Remove( i );
       
   190             break;
       
   191             }
       
   192         }
       
   193     return err;
       
   194     }
       
   195 
       
   196 
       
   197 // ---------------------------------------------------------------------------
       
   198 // Find a client message from an RMessage2 handle.
       
   199 // ---------------------------------------------------------------------------
       
   200 //
       
   201 const RMessage2* CBTNotifSession::FindMessageFromHandle( TInt aHandle ) const
       
   202     {
       
   203     // This may be replaced by RArray::Find with appropriate key
       
   204     for( TInt i = 0; i < iMessageQ.Count(); i++ )
       
   205         {
       
   206         if( iMessageQ[i].Handle() == aHandle )
       
   207             {
       
   208             return &iMessageQ[i];
       
   209             }
       
   210         }
       
   211     return NULL;
       
   212     }
       
   213 
       
   214 
       
   215 // ---------------------------------------------------------------------------
       
   216 // Process a client message.
       
   217 // The processing here relies on RNotifier backend server for queueing 
       
   218 // notifiers on the same channel. Therefore pairing (SSP and legacy) and 
       
   219 // authorization notifiers arrive in order, not simultaneously, even if 
       
   220 // they use arrive on different session instances.
       
   221 // ---------------------------------------------------------------------------
       
   222 //
       
   223 void CBTNotifSession::DispatchMessageL( const RMessage2& aMessage )
       
   224     {
       
   225     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aMessage.Function() );
       
   226     CBTNotifSettingsTracker* settTracker = Server()->SettingsTracker();
       
   227     CBTNotifConnectionTracker* connTracker = Server()->ConnectionTracker();
       
   228     LeaveIfNullL( settTracker, KErrNotReady );
       
   229     TInt opcode = aMessage.Function();
       
   230     if( opcode < EBTNotifMinValue )
       
   231         {
       
   232         User::Leave( KErrArgument );
       
   233         }
       
   234     switch( opcode )
       
   235         {
       
   236         case EBTNotifCancelNotifier:
       
   237         case EBTNotifStartSyncNotifier:
       
   238         case EBTNotifStartAsyncNotifier:
       
   239         case EBTNotifUpdateNotifier:
       
   240             {
       
   241             // All these messages get the same treatment: forward 
       
   242             // to settings and connection tracker, who will deal with it appropriately.
       
   243             // First the settings tracker handles the message.
       
   244             settTracker->DispatchNotifierMessageL( aMessage );
       
   245             if( connTracker && !aMessage.IsNull() )
       
   246                 {
       
   247                 // Pass it on to the connection tracker, if it hasn't been completed yet.
       
   248                 connTracker->DispatchNotifierMessageL( aMessage );
       
   249                 }
       
   250             else
       
   251                 {
       
   252                 // Power is off, can't do this now.
       
   253                 LeaveIfNullL( connTracker, KErrNotReady );
       
   254                 }
       
   255             if( opcode != EBTNotifStartAsyncNotifier && !aMessage.IsNull() )
       
   256                 {
       
   257                 // Nobody has yet completed the message, and it is a synchronous
       
   258                 // one so we'll do it here to allow the notifier to keep on going.
       
   259                 aMessage.Complete( KErrNone );
       
   260                 }
       
   261             }
       
   262             break;
       
   263         case EBTEngPrepareDiscovery:
       
   264             {
       
   265             // This is functionality only related to existing connections.
       
   266             // Can't do when power is off though.
       
   267             LeaveIfNullL( connTracker, KErrNotReady );
       
   268             //connTracker->HandlePairingRequestL( aMessage );
       
   269             }
       
   270             break;
       
   271         case EBTEngPairDevice:
       
   272         case EBTEngCancelPairDevice:
       
   273             {
       
   274             // This is functionality only related to connections.
       
   275             // Can't do when power is off though.
       
   276             LeaveIfNullL( connTracker, KErrNotReady );
       
   277             connTracker->HandleBondingRequestL( aMessage );
       
   278             }
       
   279             break;
       
   280         default:
       
   281             // Communicate result back.
       
   282             User::Leave( KErrNotSupported );
       
   283             break;
       
   284         }
       
   285     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   286     }
       
   287 
       
   288 
       
   289 // ---------------------------------------------------------------------------
       
   290 // Find a client message from an RNotifier UID.
       
   291 // ---------------------------------------------------------------------------
       
   292 //
       
   293 const RMessage2* CBTNotifSession::FindMessageFromUid( TInt aUid ) const
       
   294     {
       
   295     // This may be replaced by RArray::Find with appropriate key
       
   296     for( TInt i = 0; i < iMessageQ.Count(); i++ )
       
   297         {
       
   298         if( iMessageQ[i].Int0() == aUid )
       
   299             {
       
   300             return &iMessageQ[i];
       
   301             }
       
   302         }
       
   303     return NULL;
       
   304     }