bluetoothengine/bteng/btengdiscovery/src/btengsdpquery.cpp
changeset 0 f63038272f30
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Helper class for performing SDP queries.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <btsdp.h>
       
    21 
       
    22 #include "btengsdpquery.h"
       
    23 #include "btengdiscovery.h"
       
    24 #include "btengsdpattrparser.h"
       
    25 #include "debug.h"
       
    26 
       
    27 
       
    28 /**  Array granularity for storing SDP attribute values (the number 
       
    29   *  of attributes returned from an attribute search is expected 
       
    30   *  to be small).
       
    31   */
       
    32 const TInt KBTEngDefaultGranularity = 2;
       
    33 
       
    34 
       
    35 // ======== MEMBER FUNCTIONS ========
       
    36 
       
    37 // ---------------------------------------------------------------------------
       
    38 // C++ default constructor
       
    39 // ---------------------------------------------------------------------------
       
    40 //
       
    41 CBTEngSdpQuery::CBTEngSdpQuery( MBTEngSdpResultReceiver* aNotifier )
       
    42 :   iAttrValArray( KBTEngDefaultGranularity ),
       
    43     iResultNotifier( aNotifier )
       
    44     {
       
    45     }
       
    46 
       
    47 
       
    48 // ---------------------------------------------------------------------------
       
    49 // Symbian 2nd-phase constructor
       
    50 // ---------------------------------------------------------------------------
       
    51 //
       
    52 void CBTEngSdpQuery::ConstructL()
       
    53     {
       
    54     TRACE_FUNC_ENTRY
       
    55     iParser = CBTEngSdpAttrParser::NewL( &iAttrResArray );
       
    56     TRACE_FUNC_EXIT
       
    57     }
       
    58 
       
    59 
       
    60 // ---------------------------------------------------------------------------
       
    61 // NewL
       
    62 // ---------------------------------------------------------------------------
       
    63 //
       
    64 CBTEngSdpQuery* CBTEngSdpQuery::NewL( MBTEngSdpResultReceiver* aNotifier )
       
    65     {
       
    66     CBTEngSdpQuery* self = new( ELeave ) CBTEngSdpQuery( aNotifier );
       
    67     CleanupStack::PushL( self );
       
    68     self->ConstructL();
       
    69     CleanupStack::Pop( self );
       
    70     return self;
       
    71     }
       
    72 
       
    73 
       
    74 // ---------------------------------------------------------------------------
       
    75 // Destructor
       
    76 // ---------------------------------------------------------------------------
       
    77 //
       
    78 CBTEngSdpQuery::~CBTEngSdpQuery()
       
    79     {
       
    80     TRACE_FUNC_ENTRY
       
    81     Cancel();
       
    82     delete iSdpAgent;
       
    83     delete iParser;
       
    84     iResultNotifier = NULL;
       
    85     }
       
    86 
       
    87 
       
    88 // ---------------------------------------------------------------------------
       
    89 // ?implementation_description
       
    90 // ---------------------------------------------------------------------------
       
    91 //
       
    92 void CBTEngSdpQuery::Cancel()
       
    93     {
       
    94     TRACE_FUNC_ENTRY
       
    95     if( iQueryType != EQueryIdle )
       
    96         {
       
    97             // Only call the agent when a search is active, as it 
       
    98             // involves some cleanup which is not necessary for every call.
       
    99         iSdpAgent->Cancel();
       
   100         iQueryType = EQueryIdle;
       
   101         }
       
   102     iRecHandleArray.Close();
       
   103     iAttrResArray.Close();
       
   104     iAttrValArray.ResetAndDestroy();
       
   105     iRequestedAttrId = 0;
       
   106     }
       
   107 
       
   108 
       
   109 // ---------------------------------------------------------------------------
       
   110 // Service query
       
   111 // ---------------------------------------------------------------------------
       
   112 //
       
   113 void CBTEngSdpQuery::RemoteSdpQueryL( const TBTDevAddr& aAddr, const TUUID& aService )
       
   114     {
       
   115     TRACE_FUNC_ENTRY
       
   116     CheckSdpAgentL( aAddr );
       
   117     if( iQueryType == EQueryIdle )
       
   118         {
       
   119         iQueryType = EServiceQuery;
       
   120         iAttrResArray.Close();
       
   121         iAttrValArray.ResetAndDestroy();
       
   122         iRequestedAttrId = 0;
       
   123         }
       
   124     iRecHandleArray.Close();
       
   125     CSdpSearchPattern* searchPattern = CSdpSearchPattern::NewL();
       
   126     CleanupStack::PushL( searchPattern );
       
   127     searchPattern->AddL( aService );
       
   128     iSdpAgent->SetRecordFilterL( *searchPattern );  // Copies searchpattern.
       
   129     iSdpAgent->NextRecordRequestL();
       
   130     CleanupStack::PopAndDestroy( searchPattern );
       
   131     TRACE_FUNC_EXIT
       
   132     }
       
   133 
       
   134 
       
   135 // ---------------------------------------------------------------------------
       
   136 // Attribute query
       
   137 // ---------------------------------------------------------------------------
       
   138 //
       
   139 void CBTEngSdpQuery::RemoteSdpQueryL( const TBTDevAddr& aAddr, 
       
   140     const TSdpServRecordHandle aHandle, const TSdpAttributeID aAttrId )
       
   141     {
       
   142     TRACE_FUNC_ENTRY
       
   143     CheckSdpAgentL( aAddr );
       
   144         // this could be part of a ServiceSearchAttribute query.
       
   145     if( iQueryType == EQueryIdle )
       
   146         {
       
   147         iQueryType = EAttrQuery;
       
   148         iRecHandleArray.Close();
       
   149         }
       
   150     iRequestedAttrId = aAttrId;
       
   151     iAttrResArray.Close();
       
   152     iAttrValArray.ResetAndDestroy();
       
   153     iSdpAgent->AttributeRequestL( aHandle, aAttrId );
       
   154     TRACE_FUNC_EXIT
       
   155     }
       
   156 
       
   157 
       
   158 // ---------------------------------------------------------------------------
       
   159 // ServiceAttribute query
       
   160 // ---------------------------------------------------------------------------
       
   161 //
       
   162 void CBTEngSdpQuery::RemoteSdpQueryL( const TBTDevAddr& aAddr, const TUUID& aService, 
       
   163     const TSdpAttributeID aAttrId )
       
   164     {
       
   165     TRACE_FUNC_ENTRY
       
   166     if( iQueryType != EQueryIdle )
       
   167         {
       
   168         User::Leave( KErrInUse );
       
   169         }
       
   170     iQueryType = EServiceAttrQuery;
       
   171     iRequestedAttrId = aAttrId;
       
   172     iRecHandleArray.Close();
       
   173     iAttrResArray.Close();
       
   174     iAttrValArray.ResetAndDestroy();
       
   175         // First query for the requested service.
       
   176     RemoteSdpQueryL( aAddr, aService );
       
   177     TRACE_FUNC_EXIT
       
   178     }
       
   179 
       
   180 
       
   181 // ---------------------------------------------------------------------------
       
   182 // From class MSdpAgentNotifier.
       
   183 // ?implementation_description
       
   184 // ---------------------------------------------------------------------------
       
   185 //
       
   186 void CBTEngSdpQuery::NextRecordRequestComplete( TInt aError, 
       
   187     TSdpServRecordHandle aHandle, TInt aTotalRecordsCount )
       
   188     {
       
   189     TRACE_FUNC_ENTRY
       
   190     if( aError == KErrNone && aTotalRecordsCount > 0 )
       
   191         {
       
   192             // Store the result and wait for the next.
       
   193         iRecHandleArray.Append( aHandle );
       
   194         TRAP( aError, iSdpAgent->NextRecordRequestL() );
       
   195         }
       
   196     else if( aError == KErrEof )
       
   197         {
       
   198             // The last notification does not contain any result anymore.
       
   199         if( iQueryType == EServiceAttrQuery )
       
   200             {
       
   201             if( iRecHandleArray.Count() > 0 )
       
   202                 {
       
   203                     // Request the attribute for all matching service records.
       
   204                 TRAP( aError, RemoteSdpQueryL( iBDAddr, iRecHandleArray[ 0 ], 
       
   205                                                 iRequestedAttrId ) );
       
   206                 }
       
   207             else
       
   208                 {
       
   209                     // No matches, inform the client.
       
   210                 iQueryType = EQueryIdle;
       
   211                 iResultNotifier->ServiceAttributeSearchComplete( aHandle, 
       
   212                                                                   iAttrResArray, 
       
   213                                                                   aError );
       
   214                 }
       
   215             }
       
   216         else
       
   217             {
       
   218                 // This was a ServiceSearch, inform our client of the result.
       
   219             TInt recCount = iRecHandleArray.Count();
       
   220             if( recCount > 0 )
       
   221                 {
       
   222                     // KErrEof is used to indicate no matching records.
       
   223                 aError = KErrNone;
       
   224                 }
       
   225             iQueryType = EQueryIdle;
       
   226             iResultNotifier->ServiceSearchComplete( iRecHandleArray, recCount, 
       
   227                                                      aError );
       
   228             }
       
   229         }
       
   230     NotifyError( aError );
       
   231     TRACE_FUNC_EXIT
       
   232     }
       
   233 
       
   234 
       
   235 // ---------------------------------------------------------------------------
       
   236 // From class MSdpAgentNotifier.
       
   237 // ?implementation_description
       
   238 // ---------------------------------------------------------------------------
       
   239 //
       
   240 void CBTEngSdpQuery::AttributeRequestResult( TSdpServRecordHandle aHandle, 
       
   241     TSdpAttributeID aAttrID, CSdpAttrValue* aAttrValue )
       
   242     {
       
   243     TRACE_FUNC_ENTRY
       
   244         // Ownership of CSdpAttrValue is passed here. Store the object so 
       
   245         // that the result array can point to string values rather than 
       
   246         // copy them (the object is anyway already constructed).
       
   247     iAttrValArray.Append( aAttrValue );
       
   248     iParser->SetAttributeID( aAttrID );
       
   249         // Adds the attribute values synchronously to the result array.
       
   250     TRAP_IGNORE( aAttrValue->AcceptVisitorL( *iParser ) );
       
   251     (void) aHandle;
       
   252     TRACE_FUNC_EXIT
       
   253     }
       
   254 
       
   255 
       
   256 // ---------------------------------------------------------------------------
       
   257 // From class MSdpAgentNotifier.
       
   258 // ?implementation_description
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CBTEngSdpQuery::AttributeRequestComplete( TSdpServRecordHandle aHandle, 
       
   262     TInt aError )
       
   263     {
       
   264     TRACE_FUNC_ENTRY
       
   265     if( aError )
       
   266         {
       
   267         NotifyError( aError );
       
   268         return;
       
   269         }
       
   270 
       
   271     if( iQueryType == EAttrQuery )
       
   272         {
       
   273             // This was a AttributeSearch, inform our client of the result.
       
   274         iQueryType = EQueryIdle;
       
   275         iResultNotifier->AttributeSearchComplete( aHandle, iAttrResArray, aError );
       
   276         }
       
   277     else if( iQueryType == EServiceAttrQuery )
       
   278         {
       
   279         TInt index = iRecHandleArray.Find( aHandle );
       
   280         if( index <= KErrNotFound )
       
   281             {
       
   282             NotifyError( KErrCorrupt );
       
   283             return;
       
   284             }
       
   285             // Pop the handle, since we don't need it anymore.
       
   286         iRecHandleArray.Remove( index );
       
   287         if( iRecHandleArray.Count() == 0 )
       
   288             {
       
   289                 // This was the last result.
       
   290             aError = KErrEof;
       
   291             iQueryType = EQueryIdle;
       
   292             }
       
   293         iResultNotifier->ServiceAttributeSearchComplete( aHandle, iAttrResArray, 
       
   294                                                           aError );
       
   295         if( aError != KErrEof && iQueryType == EServiceAttrQuery )
       
   296             {
       
   297                 // Request the attribute from the next matching record (if 
       
   298                 // not cancelled in the callback, hence the check for the
       
   299                 // querytype) This will reset the attribute result array.
       
   300             TRAP( aError, RemoteSdpQueryL( iBDAddr, iRecHandleArray[ 0 ], 
       
   301                                             iRequestedAttrId ) );
       
   302             NotifyError( aError );  // Does nothing if there is no error.
       
   303             }
       
   304         }
       
   305     TRACE_FUNC_EXIT
       
   306     }
       
   307 
       
   308 
       
   309 // ---------------------------------------------------------------------------
       
   310 // ?implementation_description
       
   311 // ---------------------------------------------------------------------------
       
   312 //
       
   313 void CBTEngSdpQuery::NotifyError( TInt aError )
       
   314     {
       
   315     if( aError == KErrNone || aError == KErrEof || iResultNotifier == NULL )
       
   316         {
       
   317         return;
       
   318         }
       
   319     TSdpQueryType query = iQueryType;
       
   320     iQueryType = EQueryIdle;    // Need to set this before calling clients, 
       
   321                                 // as they may call us straight again.
       
   322     if( query == EServiceQuery )
       
   323         {
       
   324         iResultNotifier->ServiceSearchComplete( RSdpRecHandleArray(), 0, aError );
       
   325         }
       
   326     else if( query == EAttrQuery )
       
   327         {
       
   328         iResultNotifier->AttributeSearchComplete( 0, RSdpResultArray(), aError );
       
   329         }
       
   330     if( query == EServiceAttrQuery )
       
   331         {
       
   332         iResultNotifier->ServiceAttributeSearchComplete( 0, RSdpResultArray(), 
       
   333                                                           aError );
       
   334         }
       
   335     }
       
   336 
       
   337 
       
   338 // ---------------------------------------------------------------------------
       
   339 // ?implementation_description
       
   340 // ---------------------------------------------------------------------------
       
   341 //
       
   342 void CBTEngSdpQuery::CheckSdpAgentL( const TBTDevAddr& aAddr )
       
   343     {
       
   344     if( !iSdpAgent || aAddr != iBDAddr )
       
   345         {
       
   346         delete iSdpAgent;
       
   347         iSdpAgent = NULL;
       
   348         iBDAddr = aAddr;
       
   349         iSdpAgent = CSdpAgent::NewL( *this, iBDAddr );
       
   350         }
       
   351     else
       
   352         {
       
   353         iSdpAgent->Cancel();
       
   354         }
       
   355     if( iQueryType != EQueryIdle && iQueryType != EServiceAttrQuery )
       
   356         {
       
   357             // Another query is ongoing and has not been cancelled.
       
   358         User::Leave( KErrInUse );
       
   359         }
       
   360     }