wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_handle_measurement_request.cpp
changeset 0 c40eb8fe8501
equal deleted inserted replaced
-1:000000000000 0:c40eb8fe8501
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "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:  Statemachine for handling received measurement request.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "core_operation_handle_measurement_request.h"
       
    20 #include "core_frame_dot11_ie.h"
       
    21 #include "core_frame_mgmt_ie.h"
       
    22 #include "core_frame_rm_ie.h"
       
    23 #include "core_frame_rm_ie_beacon_report.h"
       
    24 #include "core_frame_rm_ie_beacon_report_ie.h"
       
    25 #include "core_frame_rm_ie_beacon_report_frame_body_ie.h"
       
    26 #include "core_frame_rm_ie_beacon_request.h"
       
    27 #include "core_frame_rm_ie_beacon_request_ie.h"
       
    28 #include "core_frame_rm_ie_beacon_request_detail_ie.h"
       
    29 #include "core_frame_action_rm.h"
       
    30 #include "core_tools.h"
       
    31 #include "core_server.h"
       
    32 #include "am_debug.h"
       
    33 #include "core_am_tools.h"
       
    34 
       
    35 const u16_t PARSED_NONE                 = 0;
       
    36 const u16_t MEASUREMENT_REQUEST_PARSED  = 1;
       
    37 const u16_t BEACON_REQUEST_PARSED       = 2;
       
    38 const u16_t SSID_IE_PARSED              = 4;
       
    39 const u16_t BRI_IE_PARSED               = 8;
       
    40 const u16_t BRD_IE_PARSED               = 16;
       
    41 const u16_t AP_CH_REP_IE_PARSED         = 32;
       
    42 const u16_t REQUEST_IE_PARSED           = 64;
       
    43 const u16_t SSID_IE_PARSING_FAILED      = 128;
       
    44 const u16_t BRI_IE_PARSING_FAILED       = 256;
       
    45 const u16_t BRD_IE_PARSING_FAILED       = 512;
       
    46 const u16_t AP_CH_REP_IE_PARSING_FAILED = 1024;
       
    47 const u16_t REQUEST_IE_PARSING_FAILED   = 2048;
       
    48 const u16_t CATEGORY_ERROR_IND          = 128;
       
    49 
       
    50 const u8_t BEACON_TABLE_REPORTED_FRAME_INFORMATION      = 0xFF;
       
    51 const u8_t ANTENNA_ID                                   = 0x00;
       
    52 const u8_t BEACON_TABLE_REGULATORY_CLASS                = 0xFF;
       
    53 const u16_t BEACON_TABLE_MEASUREMENT_DURATION           = 0x0000;
       
    54 const u8_t MEASUREMENT_REPORT_MODE_OK                   = 0x00;
       
    55 const u8_t MEASUREMENT_REPORT_MODE_INCAPABLE            = 0x02;
       
    56 const u8_t MEASUREMENT_REPORT_MODE_REFUSED              = 0x04;
       
    57 const u8_t DURATION_MANDATORY                           = 0x10;
       
    58 
       
    59 const u8_t SCAN_ALL_CHANNELS_IN_REGULATORY_CLASS        = 0x00;
       
    60 const u8_t SCAN_ALL_CHANNELS_IN_AP_CH_REPORT            = 0xFF;
       
    61 
       
    62 const u8_t REQUEST_IE_MAX_LENGTH = 237;
       
    63 
       
    64 // ======== MEMBER FUNCTIONS ========
       
    65 
       
    66 // ---------------------------------------------------------------------------
       
    67 // ---------------------------------------------------------------------------
       
    68 //
       
    69 core_operation_handle_measurement_request_c::core_operation_handle_measurement_request_c(
       
    70     u32_t request_id,
       
    71     core_server_c* server,
       
    72     abs_core_driverif_c* drivers,
       
    73     abs_core_server_callback_c* adaptation,
       
    74     core_frame_action_rm_c* measurement_request ) :
       
    75     core_operation_base_c( core_operation_handle_measurement_request, request_id, server, drivers, adaptation, 
       
    76         core_base_flag_none ),
       
    77     measurement_request_m( measurement_request ),
       
    78     parsed_mask_m( PARSED_NONE ),
       
    79     current_ie_m( NULL ),
       
    80     report_m ( NULL ),
       
    81     meas_req_parser_m ( NULL ),
       
    82     beacon_req_parser_m ( NULL ),
       
    83     ssid_parser_m ( NULL ),
       
    84     bri_parser_m ( NULL ),
       
    85     brd_parser_m ( NULL ),
       
    86     ap_ch_rep_parser_m ( NULL ),
       
    87     request_ie_parser_m ( NULL ),
       
    88     actual_measurement_duration_m ( 0 )
       
    89     {
       
    90     DEBUG( "core_operation_handle_measurement_request_c::core_operation_handle_measurement_request_c()" );
       
    91     }
       
    92 
       
    93 // ---------------------------------------------------------------------------
       
    94 // ---------------------------------------------------------------------------
       
    95 //
       
    96 core_operation_handle_measurement_request_c::~core_operation_handle_measurement_request_c()
       
    97     {
       
    98     DEBUG( "core_operation_handle_measurement_request_c::~core_operation_handle_measurement_request_c()" );
       
    99 
       
   100     server_m->unregister_event_handler( this );
       
   101     server_m->unregister_frame_handler( this );
       
   102     
       
   103     ie_list_m.clear();
       
   104         
       
   105     if ( measurement_request_m )
       
   106         {
       
   107         delete measurement_request_m;
       
   108         measurement_request_m = NULL;
       
   109         }
       
   110 
       
   111     if ( current_ie_m )
       
   112         {
       
   113         delete current_ie_m;
       
   114         current_ie_m = NULL;
       
   115         }
       
   116     
       
   117     if ( beacon_req_parser_m )
       
   118         {
       
   119         delete beacon_req_parser_m;
       
   120         beacon_req_parser_m = NULL;
       
   121         }
       
   122     
       
   123     if ( meas_req_parser_m )
       
   124         {
       
   125         delete meas_req_parser_m;
       
   126         meas_req_parser_m = NULL;
       
   127         }
       
   128     
       
   129     if ( ssid_parser_m )
       
   130         {
       
   131         delete ssid_parser_m;
       
   132         ssid_parser_m = NULL;
       
   133         }
       
   134     
       
   135     if ( bri_parser_m )
       
   136         {
       
   137         delete bri_parser_m;
       
   138         bri_parser_m = NULL;
       
   139         }
       
   140     
       
   141     if ( brd_parser_m )
       
   142         {
       
   143         delete brd_parser_m;
       
   144         brd_parser_m = NULL;
       
   145         }
       
   146     
       
   147     if ( ap_ch_rep_parser_m )
       
   148         {
       
   149         delete ap_ch_rep_parser_m;
       
   150         ap_ch_rep_parser_m = NULL;
       
   151         }
       
   152 
       
   153     if ( request_ie_parser_m )
       
   154         {
       
   155         delete request_ie_parser_m;
       
   156         request_ie_parser_m = NULL;
       
   157         }
       
   158 
       
   159     if ( report_m )
       
   160         {
       
   161         delete report_m;
       
   162         report_m = NULL;
       
   163         }
       
   164 
       
   165     }
       
   166     
       
   167 // ---------------------------------------------------------------------------
       
   168 // ---------------------------------------------------------------------------
       
   169 //
       
   170 core_error_e core_operation_handle_measurement_request_c::next_state()
       
   171     {
       
   172     DEBUG( "core_operation_handle_measurement_request_c::next_state()" );
       
   173 
       
   174     switch ( operation_state_m )
       
   175         {
       
   176         case core_state_init:
       
   177             {
       
   178             DEBUG( "core_operation_handle_measurement_request_c::next_state() - core_state_init" );
       
   179             
       
   180             if ( !server_m->get_core_settings().is_connected() )
       
   181                 {
       
   182                 DEBUG( "core_operation_handle_measurement_request_c::next_state() - not connected, nothing to do" );
       
   183 
       
   184                 return core_error_general;
       
   185                 }
       
   186 
       
   187             status_m.set_da( measurement_request_m->source() );
       
   188             status_m.set_sa( server_m->own_mac_addr() );
       
   189 
       
   190             DEBUG( "core_operation_handle_measurement_request_c::next_state() - Request data layout" );
       
   191             DEBUG_BUFFER( measurement_request_m->data_length(), measurement_request_m->data() );
       
   192                         
       
   193             DEBUG1( "core_operation_handle_measurement_request_c::next_state() - Dialog token: 0x%02X",
       
   194                     measurement_request_m->dialog_token() );
       
   195             DEBUG1( "core_operation_handle_measurement_request_c::next_state() - Number of repetitions: 0x%04X",
       
   196                     measurement_request_m->nbr_of_repetitions() );
       
   197             
       
   198             // validate measurement interval
       
   199             if ( !validate_measurement_interval() )
       
   200                 {
       
   201                 DEBUG( "core_operation_handle_measurement_request_c::next_state() - Measurement Request coming too often, refusing request" );
       
   202                 status_m.set_too_short_interval( true_t );
       
   203                 }
       
   204             
       
   205             // loop through IEs
       
   206             for ( core_frame_dot11_ie_c* ie = measurement_request_m->first_ie(); ie; ie = measurement_request_m->next_ie() )
       
   207                 {
       
   208                 DEBUG( "core_operation_handle_measurement_request_c::next_state() - Found IE:" );
       
   209                 DEBUG1( "core_operation_handle_measurement_request_c::next_state() - ID: 0x%02X",
       
   210                     ie->element_id() );
       
   211                 DEBUG1( "core_operation_handle_measurement_request_c::next_state() - Length: 0x%02X",
       
   212                     ie->length() );
       
   213                 
       
   214                 ie_list_m.append( ie );
       
   215                 }
       
   216             
       
   217             if ( ie_list_m.count() == 0 )
       
   218                 {
       
   219                 DEBUG( "core_operation_handle_measurement_request_c::next_state() - Measurement request didn't contain any IEs -> sending frame back" );
       
   220                  
       
   221                 status_m.set_error_in_request( true_t );
       
   222                                 
       
   223                 return goto_state( core_state_create_negative_response );
       
   224                 }
       
   225             
       
   226             return goto_state( core_state_get_next_ie );
       
   227             }
       
   228         case core_state_get_next_ie:
       
   229             {
       
   230             DEBUG( "core_operation_handle_measurement_request_c::next_state() - state core_state_get_next_ie" );
       
   231 
       
   232             initialise_beacon_request_data();
       
   233 
       
   234             if ( current_ie_m != NULL )
       
   235                 {
       
   236                 // deallocate IE
       
   237                 delete current_ie_m;
       
   238                 current_ie_m = NULL;
       
   239                 }
       
   240 
       
   241             current_ie_m = ie_list_m.first();
       
   242             
       
   243             if ( current_ie_m == NULL )
       
   244                 {
       
   245                 DEBUG( "core_operation_handle_measurement_request_c::next_state() - All IEs processed" );
       
   246                 
       
   247                 if ( report_m != NULL )
       
   248                     {
       
   249                     // send created response
       
   250                     return goto_state( core_state_send_response );
       
   251                     }
       
   252                 else
       
   253                     {
       
   254                     return goto_state( core_state_operation_finished );
       
   255                     }
       
   256                 }
       
   257             
       
   258             // remove ie from list, it is now owned by current_ie_m
       
   259             ie_list_m.remove ( current_ie_m );
       
   260             
       
   261             return asynch_goto( core_state_process_current_ie );
       
   262             }
       
   263         case core_state_process_current_ie:
       
   264             {
       
   265             if ( current_ie_m->element_id() == core_frame_dot11_ie_c::core_frame_dot11_ie_element_id_measurement_req )
       
   266                 {
       
   267                 // parse IE
       
   268                 parse( current_ie_m, parsed_mask_m );
       
   269                 
       
   270                 // deallocate IE
       
   271                 delete current_ie_m;
       
   272                 current_ie_m = NULL;
       
   273 
       
   274                 if ( status_m.error_in_request() == true_t )
       
   275                     {
       
   276                     DEBUG( "core_operation_handle_measurement_request_c::next_state() - Error in request, send frame back and stop further processing." );
       
   277                     return goto_state( core_state_create_negative_response );
       
   278                     }
       
   279                 
       
   280                 if ( status_m.refuse_request() == true_t )
       
   281                     {
       
   282                     DEBUG( "core_operation_handle_measurement_request_c::next_state() - Refusing request." );                  
       
   283                     return goto_state( core_state_create_negative_response );
       
   284                     }
       
   285                 
       
   286                 if ( status_m.too_short_interval() == true_t )
       
   287                     {
       
   288                     DEBUG( "core_operation_handle_measurement_request_c::next_state() - Too short request interval, refusing request." );
       
   289                     status_m.set_refuse_request( true_t );
       
   290                     return goto_state( core_state_create_negative_response );
       
   291                     }
       
   292                 
       
   293                 DEBUG( "core_operation_handle_measurement_request_c::next_state() - Going to core_state_make_measurement." );
       
   294                 
       
   295                 return asynch_goto( core_state_make_measurement, get_random_delay() );
       
   296                 }
       
   297 
       
   298             DEBUG( "core_operation_handle_measurement_request_c::next_state() - Non-supported measurement request IE received, ignoring." );
       
   299             DEBUG( "core_operation_handle_measurement_request_c::next_state() - Going to core_state_get_next_ie." );
       
   300             
       
   301             return goto_state( core_state_get_next_ie );
       
   302             }
       
   303         case core_state_make_measurement:
       
   304             {
       
   305             ASSERT( beacon_req_parser_m );
       
   306             
       
   307             core_scan_mode_e scan_mode( core_scan_mode_active );
       
   308             actual_measurement_duration_m = get_channel_time( core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_active );
       
   309             core_ssid_s scan_ssid = get_ssid();
       
   310 
       
   311             if ( ap_ch_rep_parser_m )
       
   312                 {
       
   313                 core_scan_channels_c scan_channels = get_channels();
       
   314                 status_m.set_scan_channels( scan_channels.channels() );
       
   315                 }
       
   316 
       
   317             switch ( beacon_req_parser_m->measurement_mode() )
       
   318                 {
       
   319                 case core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon:
       
   320                     {                    
       
   321                     DEBUG( "core_operation_handle_measurement_request_c::next_state() - beacon table measurement" );
       
   322                     actual_measurement_duration_m = get_channel_time( core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon );
       
   323                     return asynch_goto( core_state_create_response );
       
   324                     }
       
   325                 case core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_active:
       
   326                     {
       
   327                     DEBUG( "core_operation_handle_measurement_request_c::next_state() - issuing active scan request" );
       
   328                     break;
       
   329                     }
       
   330                 case core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_passive:
       
   331                     {
       
   332                     DEBUG( "core_operation_handle_measurement_request_c::next_state() - issuing passive scan request" );
       
   333                     scan_mode = core_scan_mode_passive;
       
   334                     actual_measurement_duration_m = get_channel_time( core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_passive );
       
   335                     break;
       
   336                     }
       
   337                 default:
       
   338                     {
       
   339                     // by default perform active mode measurement
       
   340                     break;
       
   341                     }
       
   342                 }
       
   343 
       
   344             u32_t ch_time( actual_measurement_duration_m );
       
   345             
       
   346             DEBUG( "core_operation_handle_measurement_request_c::next_state() - issuing scan request:" );
       
   347             DEBUG1S( "core_operation_handle_measurement_request_c::next_state() - SSID: ", scan_ssid.length, &scan_ssid.ssid[0] );
       
   348 #ifdef _DEBUG
       
   349             u16_t mask( 0 );
       
   350             core_tools_c::copy(
       
   351                 reinterpret_cast<u8_t*>( &mask ),
       
   352                 &status_m.get_scan_channels().channels2dot4ghz[0],            
       
   353                 sizeof( status_m.get_scan_channels().channels2dot4ghz ) );
       
   354 #endif // _DEBUG
       
   355             DEBUG1( "core_operation_handle_measurement_request_c::next_state() - channel mask: %013b", mask );
       
   356             DEBUG1( "core_operation_handle_measurement_request_c::next_state() - min ch time: %u", ch_time );
       
   357             DEBUG1( "core_operation_handle_measurement_request_c::next_state() - max ch time: %u", ch_time );
       
   358             
       
   359             server_m->get_scan_list().remove_entries_by_age(
       
   360                 server_m->get_device_settings().scan_list_expiration_time );
       
   361 
       
   362             server_m->get_scan_list().set_tag(
       
   363                 core_scan_list_tag_scan );
       
   364 
       
   365             server_m->register_event_handler( this );
       
   366             server_m->register_frame_handler( this );
       
   367 
       
   368             drivers_m->scan(
       
   369                 request_id_m,
       
   370                 scan_mode,
       
   371                 scan_ssid,
       
   372                 server_m->get_device_settings().scan_rate,
       
   373                 status_m.get_scan_channels(),
       
   374                 ch_time,
       
   375                 ch_time,
       
   376                 false_t );
       
   377             
       
   378             operation_state_m = core_state_scan_start;
       
   379 
       
   380             return core_error_request_pending;
       
   381             }
       
   382         case core_state_scan_start:
       
   383             {
       
   384             DEBUG( "core_operation_handle_measurement_request_c::next_state() - scan request completed, waiting for scan completion" );
       
   385 
       
   386             break;
       
   387             }
       
   388         case core_state_create_response:
       
   389             {
       
   390             core_scan_list_tag_e tag( core_scan_list_tag_scan );
       
   391             if ( beacon_req_parser_m->measurement_mode() == core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon )
       
   392                 {
       
   393                 tag = core_scan_list_tag_none;
       
   394                 }
       
   395 #ifdef _DEBUG
       
   396             server_m->get_scan_list().print_contents();      
       
   397 #endif
       
   398             core_scan_list_iterator_by_tag_c iter(
       
   399                 server_m->get_scan_list(),
       
   400                 tag );
       
   401             
       
   402             bool_t no_match( true_t );
       
   403             
       
   404             // loop through the scan list
       
   405             for ( core_ap_data_c* ap_data = iter.first(); ap_data; ap_data = iter.next() )
       
   406                 {
       
   407                 if ( !match_found( *ap_data ) )
       
   408                     {
       
   409                     // no match found, proceed to the next beacon/probe
       
   410                     continue;
       
   411                     }
       
   412                 
       
   413                 no_match = false_t;
       
   414                 
       
   415                 if ( !create_response( *ap_data ) )
       
   416                     {
       
   417                     // create_response returns false_t only in out-of-memory situation
       
   418                     return core_error_no_memory;
       
   419                     }
       
   420                 }
       
   421             
       
   422             if ( no_match )
       
   423                 {
       
   424                 create_negative_response_based_on_meas_report_mode( MEASUREMENT_REPORT_MODE_OK );
       
   425                 }
       
   426             
       
   427             // check if more IEs need to be added to the report
       
   428             DEBUG( "core_operation_handle_measurement_request_c::next_state() - Going to core_state_get_next_ie." );
       
   429             
       
   430             return goto_state( core_state_get_next_ie );
       
   431             }
       
   432         case core_state_create_negative_response:
       
   433             {
       
   434             if ( !create_negative_response() )
       
   435                 {
       
   436                 DEBUG( "core_operation_handle_measurement_request_c::next_state() - Unable to create response to request" );
       
   437                 
       
   438                 // create_response returns false only in out-of-memory situation
       
   439                 return core_error_no_memory;
       
   440                 }
       
   441             
       
   442             return goto_state( core_state_send_response );
       
   443             }
       
   444         case core_state_send_response:
       
   445             {
       
   446             DEBUG1( "core_operation_handle_measurement_request_c::next_state() - sending frame (%u bytes): ",
       
   447                 report_m->data_length() );
       
   448             DEBUG_BUFFER(
       
   449                 report_m->data_length(),
       
   450                 report_m->data() );
       
   451             
       
   452             server_m->send_management_frame(
       
   453                 core_frame_type_dot11,
       
   454                 report_m->data_length(),
       
   455                 report_m->data(),
       
   456                 status_m.da() );
       
   457             
       
   458             return goto_state( core_state_operation_finished );
       
   459             }
       
   460         case core_state_operation_finished:
       
   461             {
       
   462             DEBUG( "core_operation_handle_measurement_request_c::next_state() - state core_state_operation_finished" );
       
   463             
       
   464             return core_error_ok;
       
   465             }
       
   466         default:
       
   467             {
       
   468             ASSERT( false_t );
       
   469             }
       
   470         }
       
   471 
       
   472     return core_error_request_pending;
       
   473     }
       
   474     
       
   475 // ---------------------------------------------------------------------------
       
   476 // ---------------------------------------------------------------------------
       
   477 //
       
   478 bool_t core_operation_handle_measurement_request_c::add_to_report(
       
   479         const core_frame_rm_ie_c* ie ) 
       
   480     {
       
   481     DEBUG( "core_operation_handle_measurement_request_c::add_to_report()" );
       
   482     
       
   483     if ( report_m == NULL )
       
   484         {
       
   485         // instantiate response
       
   486         report_m = core_frame_action_rm_c::instance(
       
   487                                             0,                          // Duration
       
   488                                             status_m.da(),              // Destination
       
   489                                             status_m.sa(),              // Source
       
   490                                             status_m.da(),              // BSSID
       
   491                                             0,                          // Sequence Control
       
   492                                             core_frame_action_rm_c::core_dot11_action_rm_type_meas_resp, // Action Type
       
   493                                             measurement_request_m->dialog_token(),     // Dialog Token
       
   494                                             ie );                       // RM IE
       
   495         
       
   496         if ( report_m == NULL )
       
   497             {
       
   498             // unable to instantiate response
       
   499             return false_t;
       
   500             }
       
   501         }
       
   502     else
       
   503         {
       
   504         report_m->append_ie( ie );
       
   505         }
       
   506     
       
   507     return true_t;
       
   508     }
       
   509 
       
   510 // ---------------------------------------------------------------------------
       
   511 // ---------------------------------------------------------------------------
       
   512 //
       
   513 void core_operation_handle_measurement_request_c::parse(
       
   514         core_frame_dot11_ie_c* ie,
       
   515         u16_t& parsed_mask )
       
   516     {
       
   517     DEBUG( "core_operation_handle_measurement_request_c::parse() - * Measurement Request IE received *" );
       
   518     
       
   519     // refuse repetitive measurements
       
   520     if ( measurement_request_m->nbr_of_repetitions() )
       
   521         {
       
   522         DEBUG( "core_operation_handle_measurement_request_c::parse() - refusing repeated measurement" );
       
   523         status_m.set_refuse_request( true_t );
       
   524         }
       
   525     
       
   526     if ( meas_req_parser_m != NULL )
       
   527         {
       
   528         delete meas_req_parser_m;
       
   529         meas_req_parser_m = NULL;
       
   530         }
       
   531     
       
   532     meas_req_parser_m = core_frame_rm_ie_c::instance( *ie );
       
   533     
       
   534     if ( meas_req_parser_m )
       
   535         {
       
   536         parsed_mask |= MEASUREMENT_REQUEST_PARSED;
       
   537 
       
   538         validate_measurement_request();
       
   539         
       
   540         if ( meas_req_parser_m->measurement_type() == core_frame_rm_ie_c::core_frame_rm_ie_action_type_beacon_request )
       
   541             {
       
   542             // instantiate a parser for beacon request
       
   543             if ( beacon_req_parser_m != NULL )
       
   544                 {
       
   545                 delete beacon_req_parser_m;
       
   546                 beacon_req_parser_m = NULL;
       
   547                 }
       
   548             beacon_req_parser_m = core_frame_rm_ie_beacon_request_c::instance( *meas_req_parser_m );
       
   549             
       
   550             validate_beacon_request();
       
   551             
       
   552             if ( beacon_req_parser_m )
       
   553                 {
       
   554                 parsed_mask |= BEACON_REQUEST_PARSED;
       
   555 
       
   556                 // loop through IEs
       
   557                 for ( core_frame_dot11_ie_c* beacon_req_ie = beacon_req_parser_m->first_ie(); beacon_req_ie; beacon_req_ie = beacon_req_parser_m->next_ie() )
       
   558                     {
       
   559                     DEBUG1( "core_operation_handle_measurement_request_c::parse() - 802.11k Beacon Request IE ID: 0x%02X",
       
   560                         beacon_req_ie->element_id() );
       
   561                     DEBUG1( "core_operation_handle_measurement_request_c::parse() - 802.11k Beacon Request IE length: 0x%02X",
       
   562                         beacon_req_ie->length() );
       
   563                     
       
   564                     if ( beacon_req_ie->element_id() == core_frame_dot11_ie_c::core_frame_dot11_ie_element_id_ssid )
       
   565                         {
       
   566                         // instantiate a parser for ssid
       
   567                         if ( ssid_parser_m != NULL )
       
   568                             {
       
   569                             delete ssid_parser_m;
       
   570                             ssid_parser_m = NULL;
       
   571                             }
       
   572                         DEBUG( "core_operation_handle_measurement_request_c::parse() - *** SSID Sub-element ***" );
       
   573                         
       
   574                         ssid_parser_m = core_frame_mgmt_ie_ssid_c::instance( *beacon_req_ie );
       
   575                         if ( ssid_parser_m )
       
   576                             {
       
   577                             parsed_mask |= SSID_IE_PARSED;
       
   578                             const core_ssid_s ssid = ssid_parser_m->ssid();
       
   579                             if ( ssid.length != 0 )
       
   580                                 {
       
   581                                 DEBUG1S( "core_operation_handle_measurement_request_c::parse() - SSID: ", ssid.length, &ssid.ssid[0] );
       
   582                                 }
       
   583                             else
       
   584                                 {
       
   585                                 DEBUG( "core_operation_handle_measurement_request_c::parse() - SSID: <zero length ssid>" );
       
   586                                 }
       
   587                             }
       
   588                         else
       
   589                             {
       
   590                             parsed_mask |= SSID_IE_PARSING_FAILED;
       
   591                             status_m.set_error_in_request( true_t );
       
   592                             }
       
   593                         }
       
   594                     else if ( beacon_req_ie->element_id() == core_frame_rm_ie_beacon_request_c::core_frame_rm_ie_beacon_request_element_id_beacon_reporting_information )
       
   595                         {
       
   596                         DEBUG( "core_operation_handle_measurement_request_c::parse() - *** Beacon Reporting Information Sub-element ***" );
       
   597                         // instantiate a parser for BRI
       
   598                         if ( bri_parser_m != NULL )
       
   599                             {
       
   600                             delete bri_parser_m;
       
   601                             bri_parser_m = NULL;
       
   602                             }
       
   603                         bri_parser_m = core_frame_rm_ie_beacon_request_ie_c::instance( *beacon_req_ie );
       
   604                         if ( bri_parser_m )
       
   605                             {
       
   606                             validate_beacon_reporting_information();
       
   607                             parsed_mask |= BRI_IE_PARSED;
       
   608                             }
       
   609                         else
       
   610                             {
       
   611                             parsed_mask |= BRI_IE_PARSING_FAILED;
       
   612                             status_m.set_error_in_request( true_t );
       
   613                             }
       
   614                         }
       
   615                     else if ( beacon_req_ie->element_id() == core_frame_rm_ie_beacon_request_c::core_frame_rm_ie_beacon_request_element_id_beacon_reporting_detail )
       
   616                         {
       
   617                         DEBUG( "core_operation_handle_measurement_request_c::parse() - *** Beacon Reporting Detail Sub-element ***" );
       
   618                         // instantiate a parser for BRD
       
   619                         if ( brd_parser_m != NULL )
       
   620                             {
       
   621                             delete brd_parser_m;
       
   622                             brd_parser_m = NULL;
       
   623                             }
       
   624                         brd_parser_m = core_frame_rm_ie_beacon_request_detail_ie_c::instance( *beacon_req_ie );
       
   625                         if ( brd_parser_m )
       
   626                             {
       
   627                             validate_beacon_reporting_detail();
       
   628                             parsed_mask |= BRD_IE_PARSED;
       
   629                             }
       
   630                         else
       
   631                             {
       
   632                             parsed_mask |= BRD_IE_PARSING_FAILED;
       
   633                             status_m.set_error_in_request( true_t );
       
   634                             }
       
   635                         }
       
   636                     else if ( beacon_req_ie->element_id() == core_frame_dot11_ie_c::core_frame_dot11_ie_element_id_request )
       
   637                         {
       
   638                         // instantiate a parser for request information element
       
   639                         if ( request_ie_parser_m != NULL )
       
   640                             {
       
   641                             delete request_ie_parser_m;
       
   642                             request_ie_parser_m = NULL;
       
   643                             }
       
   644                         DEBUG( "core_operation_handle_measurement_request_c::parse() - *** Request Sub-element ***" );
       
   645                         
       
   646                         request_ie_parser_m = core_frame_mgmt_ie_request_ie_c::instance( *beacon_req_ie );
       
   647                         if ( request_ie_parser_m )
       
   648                             {
       
   649                             parsed_mask |= REQUEST_IE_PARSED;
       
   650                             }
       
   651                         else
       
   652                             {
       
   653                             parsed_mask |= REQUEST_IE_PARSING_FAILED;
       
   654                             status_m.set_error_in_request( true_t );
       
   655                             }
       
   656                         }
       
   657                     else if ( beacon_req_ie->element_id() == core_frame_dot11_ie_c::core_frame_dot11_ie_element_id_ap_channel_report )
       
   658                         {
       
   659                         // instantiate a parser for ap channel report
       
   660                         if ( ap_ch_rep_parser_m != NULL )
       
   661                             {
       
   662                             delete ap_ch_rep_parser_m;
       
   663                             ap_ch_rep_parser_m = NULL;
       
   664                             }
       
   665                         DEBUG( "core_operation_handle_measurement_request_c::parse() - *** AP Channel Report Sub-element ***" );
       
   666                         
       
   667                         ap_ch_rep_parser_m = core_frame_mgmt_ie_ap_channel_report_c::instance( *beacon_req_ie );
       
   668                         if ( ap_ch_rep_parser_m )
       
   669                             {
       
   670                             parsed_mask |= AP_CH_REP_IE_PARSED;
       
   671                             }
       
   672                         else
       
   673                             {
       
   674                             parsed_mask |= AP_CH_REP_IE_PARSING_FAILED;
       
   675                             status_m.set_error_in_request( true_t );
       
   676                             }
       
   677                         }
       
   678 
       
   679                     delete beacon_req_ie;
       
   680                     beacon_req_ie = NULL;
       
   681                     }
       
   682                 }
       
   683             }
       
   684         else
       
   685             {
       
   686             // Incapable measurement request
       
   687             create_negative_response_based_on_meas_report_mode( MEASUREMENT_REPORT_MODE_INCAPABLE );
       
   688             }
       
   689         }
       
   690     else
       
   691         {
       
   692         status_m.set_error_in_request( true_t );
       
   693         }
       
   694     
       
   695     DEBUG( "core_operation_handle_measurement_request_c::parse() - parsed_mask:" );
       
   696     DEBUG1( "core_operation_handle_measurement_request_c::parse() - %012b", parsed_mask );
       
   697     DEBUG( "core_operation_handle_measurement_request_c::parse() - ||||||||||||" );
       
   698     DEBUG( "core_operation_handle_measurement_request_c::parse() - |||||||||||+--MEASUREMENT_REQUEST_PARSED");
       
   699     DEBUG( "core_operation_handle_measurement_request_c::parse() - ||||||||||+---BEACON_REQUEST_PARSED");
       
   700     DEBUG( "core_operation_handle_measurement_request_c::parse() - |||||||||+----SSID_IE_PARSED");
       
   701     DEBUG( "core_operation_handle_measurement_request_c::parse() - ||||||||+-----BRI_IE_PARSED");
       
   702     DEBUG( "core_operation_handle_measurement_request_c::parse() - |||||||+------BRD_IE_PARSED");
       
   703     DEBUG( "core_operation_handle_measurement_request_c::parse() - ||||||+-------AP_CH_REP_IE_PARSED");
       
   704     DEBUG( "core_operation_handle_measurement_request_c::parse() - |||||+--------REQUEST_IE_PARSED");
       
   705     DEBUG( "core_operation_handle_measurement_request_c::parse() - ||||+---------SSID_IE_PARSING_FAILED");
       
   706     DEBUG( "core_operation_handle_measurement_request_c::parse() - |||+----------BRI_IE_PARSING_FAILED");
       
   707     DEBUG( "core_operation_handle_measurement_request_c::parse() - ||+-----------BRD_IE_PARSING_FAILED");
       
   708     DEBUG( "core_operation_handle_measurement_request_c::parse() - |+------------AP_CH_REP_IE_PARSING_FAILED");
       
   709     DEBUG( "core_operation_handle_measurement_request_c::parse() - +-------------REQUEST_IE_PARSING_FAILED");
       
   710             
       
   711     }
       
   712 
       
   713 // ---------------------------------------------------------------------------
       
   714 // ---------------------------------------------------------------------------
       
   715 //
       
   716 bool_t core_operation_handle_measurement_request_c::create_negative_response()
       
   717     {
       
   718     DEBUG( "core_operation_handle_measurement_request_c::create_negative_response()" );
       
   719     
       
   720     bool_t result( false_t );
       
   721     
       
   722     if ( status_m.error_in_request() )
       
   723         {        
       
   724         DEBUG( "core_operation_handle_measurement_request_c::create_negative_response() - Error in request, send it back and stop further processing." );
       
   725         
       
   726         result = create_response_to_invalid_request();
       
   727         }
       
   728     else if ( status_m.refuse_request() )
       
   729         {
       
   730         DEBUG( "core_operation_handle_measurement_request_c::create_negative_response() - Refusing to make the requested measurement" );
       
   731         
       
   732         result = create_negative_response_based_on_meas_report_mode( MEASUREMENT_REPORT_MODE_REFUSED );
       
   733         }
       
   734     else
       
   735         {
       
   736         ASSERT( 0 );
       
   737         }
       
   738     
       
   739     return result;
       
   740     }
       
   741 
       
   742 // ---------------------------------------------------------------------------
       
   743 // ---------------------------------------------------------------------------
       
   744 //
       
   745 bool_t core_operation_handle_measurement_request_c::create_negative_response_based_on_meas_report_mode(
       
   746     u8_t measurement_report_mode )
       
   747     {
       
   748     DEBUG( "core_operation_handle_measurement_request_c::create_negative_response_based_on_meas_report_mode()" );
       
   749 
       
   750     bool_t result( false_t );
       
   751         
       
   752     // create IE with no sub-elements
       
   753     core_frame_rm_ie_c* rm_report = core_frame_rm_ie_c::instance(
       
   754                                                                 meas_req_parser_m->measurement_token(),
       
   755                                                                 measurement_report_mode,
       
   756                                                                 meas_req_parser_m->measurement_type() );
       
   757     if ( rm_report )
       
   758         {
       
   759         result = add_to_report( rm_report );
       
   760         
       
   761         delete rm_report;
       
   762         rm_report = NULL;
       
   763         
       
   764         return result;
       
   765         }
       
   766 
       
   767     if ( measurement_report_mode == MEASUREMENT_REPORT_MODE_REFUSED )
       
   768         {
       
   769         DEBUG( "core_operation_handle_measurement_request_c::create_negative_response_based_on_meas_report_mode() - Unable to instantiate core_frame_rm_ie_parameter_c" );
       
   770         }
       
   771     else if ( measurement_report_mode == MEASUREMENT_REPORT_MODE_OK )
       
   772         {
       
   773         DEBUG( "core_operation_handle_measurement_request_c::create_negative_response_based_on_meas_report_mode() - Unable to instantiate core_frame_rm_ie_parameter_c" );
       
   774         }
       
   775     else if ( measurement_report_mode == MEASUREMENT_REPORT_MODE_INCAPABLE )
       
   776         {
       
   777         DEBUG( "core_operation_handle_measurement_request_c::create_negative_response_based_on_meas_report_mode() - Incapable measurement request, unable to instantiate core_frame_rm_ie_parameter_c" );
       
   778         }
       
   779 
       
   780     return result;
       
   781     }
       
   782 
       
   783 // ---------------------------------------------------------------------------
       
   784 // ---------------------------------------------------------------------------
       
   785 //
       
   786 bool_t core_operation_handle_measurement_request_c::create_response_to_invalid_request()
       
   787     {
       
   788     DEBUG( "core_operation_handle_measurement_request_c::create_response_to_invalid_request()" );
       
   789 
       
   790     ASSERT( !report_m );
       
   791     
       
   792     // send the received frame back
       
   793     report_m = core_frame_action_c::instance( *measurement_request_m );
       
   794         
       
   795     if ( report_m )
       
   796         {
       
   797         // set the MSB of the Category field to 1 to indicate error situation
       
   798         // Ref. 7.3.1.11 Action field
       
   799         report_m->set_category( report_m->category() + CATEGORY_ERROR_IND );
       
   800 
       
   801         // switch DA and SA
       
   802         report_m->set_source( status_m.da() );
       
   803         report_m->set_destination( status_m.sa() );
       
   804         
       
   805         return true_t;
       
   806         }
       
   807    
       
   808     return false_t;      
       
   809     }
       
   810 
       
   811 // ---------------------------------------------------------------------------
       
   812 // ---------------------------------------------------------------------------
       
   813 //
       
   814 void core_operation_handle_measurement_request_c::validate_beacon_request() 
       
   815     {
       
   816     if ( !beacon_req_parser_m )
       
   817         {
       
   818         DEBUG( "core_operation_handle_measurement_request_c::validate_beacon_request() - no beacon request element present, refusing measurement" );
       
   819         status_m.set_refuse_request( true_t );
       
   820         return;
       
   821         }
       
   822         
       
   823     if ( beacon_req_parser_m->measurement_mode() > core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon )
       
   824         {
       
   825         DEBUG1( "core_operation_handle_measurement_request_c::validate_beacon_request() - unknown Measurement Mode %u",
       
   826                 beacon_req_parser_m->measurement_mode() );
       
   827         status_m.set_error_in_request( true_t );
       
   828         }
       
   829     
       
   830     if ( beacon_req_parser_m->measurement_mode() != core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon &&
       
   831          ( meas_req_parser_m->measurement_request_mode() & DURATION_MANDATORY ) &&
       
   832          ( ( beacon_req_parser_m->measurement_mode() == core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_active &&
       
   833              beacon_req_parser_m->measurement_duration() > server_m->get_device_settings().active_scan_max_ch_time ) ||
       
   834            ( beacon_req_parser_m->measurement_mode() == core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_passive &&
       
   835              beacon_req_parser_m->measurement_duration() > server_m->get_device_settings().passive_scan_max_ch_time ) ) )
       
   836         {
       
   837         DEBUG( "core_operation_handle_measurement_request_c::validate_beacon_request() - too big measurement duration requested, refusing request" );
       
   838         status_m.set_refuse_request( true_t );
       
   839         }
       
   840     
       
   841     if ( beacon_req_parser_m->measurement_mode() != core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon &&
       
   842          server_m->get_connection_data()->voice_call_state() == true_t )
       
   843         {
       
   844         DEBUG( "core_operation_handle_measurement_request_c::validate_beacon_request() - non-Beacon Table Mode requested and voice call on, refusing request" );
       
   845         status_m.set_refuse_request( true_t );
       
   846         }
       
   847     
       
   848     if ( !validate_scan_channels() )
       
   849         {
       
   850         DEBUG( "core_operation_handle_measurement_request_c::validate_beacon_request() - invalid scan channels, refusing request" );
       
   851         status_m.set_refuse_request( true_t );
       
   852         }
       
   853         
       
   854     }
       
   855 
       
   856 // ---------------------------------------------------------------------------
       
   857 // ---------------------------------------------------------------------------
       
   858 //
       
   859 void core_operation_handle_measurement_request_c::validate_beacon_reporting_information() 
       
   860     {
       
   861     if ( bri_parser_m->reporting_condition() != core_frame_rm_ie_beacon_request_ie_c::core_frame_rm_ie_bri_reporting_condition_default )
       
   862         {
       
   863         DEBUG1( "core_operation_handle_measurement_request_c::validate_beacon_reporting_information() - reporting condition 0x%02X not supported",
       
   864                 bri_parser_m->reporting_condition() );
       
   865         status_m.set_refuse_request( true_t );
       
   866         }    
       
   867     }
       
   868 
       
   869 // ---------------------------------------------------------------------------
       
   870 // ---------------------------------------------------------------------------
       
   871 //
       
   872 void core_operation_handle_measurement_request_c::validate_beacon_reporting_detail() 
       
   873     {
       
   874     if ( brd_parser_m->reporting_detail() != core_frame_rm_ie_beacon_request_detail_ie_c::core_frame_rm_ie_brd_reporting_detail_no_fields_or_elements &&
       
   875          brd_parser_m->reporting_detail() != core_frame_rm_ie_beacon_request_detail_ie_c::core_frame_rm_ie_brd_reporting_detail_fields_and_requested_elements &&
       
   876          brd_parser_m->reporting_detail() != core_frame_rm_ie_beacon_request_detail_ie_c::core_frame_rm_ie_brd_reporting_detail_default )
       
   877         {
       
   878         DEBUG1( "core_operation_handle_measurement_request_c::validate_beacon_reporting_detail() - reporting detail 0x%02X not supported",
       
   879                 brd_parser_m->reporting_detail() );
       
   880         status_m.set_refuse_request( true_t );
       
   881         }    
       
   882     }
       
   883 
       
   884 // ---------------------------------------------------------------------------
       
   885 // ---------------------------------------------------------------------------
       
   886 //
       
   887 bool_t core_operation_handle_measurement_request_c::validate_measurement_interval() 
       
   888     {
       
   889     u64_t previous_timestamp = server_m->get_connection_data()->get_previous_rrm_measurement_request_time();
       
   890     u64_t current_timestamp = core_am_tools_c::timestamp();
       
   891     
       
   892     if ( previous_timestamp )
       
   893         {
       
   894         u32_t min_interval = server_m->get_device_settings().rrm_min_measurement_interval;
       
   895         
       
   896         DEBUG1( "core_operation_handle_measurement_request_c::validate_measurement_interval() - min. interval in seconds: %u", 
       
   897                 server_m->get_device_settings().rrm_min_measurement_interval / SECONDS_FROM_MICROSECONDS );
       
   898         
       
   899         DEBUG1( "core_operation_handle_measurement_request_c::validate_measurement_interval() - seconds since previous request: %u", 
       
   900                 static_cast<u32_t> ( ( current_timestamp - previous_timestamp ) / SECONDS_FROM_MICROSECONDS ) );
       
   901         
       
   902         if ( min_interval && ( previous_timestamp + min_interval >= current_timestamp ) )
       
   903             {
       
   904             // interval is too short
       
   905             return false_t;
       
   906             }
       
   907         }
       
   908         
       
   909     server_m->get_connection_data()->set_previous_rrm_measurement_request_time( current_timestamp );
       
   910     
       
   911     return true_t;   
       
   912     }
       
   913 
       
   914 // ---------------------------------------------------------------------------
       
   915 // ---------------------------------------------------------------------------
       
   916 //
       
   917 void core_operation_handle_measurement_request_c::validate_measurement_request() 
       
   918     {
       
   919     if ( meas_req_parser_m->measurement_type() != core_frame_rm_ie_c::core_frame_rm_ie_action_type_beacon_request )
       
   920         {
       
   921         DEBUG1( "core_operation_handle_measurement_request_c::validate_measurement_request() - non-supported Measurement Type 0x%02X",
       
   922                 meas_req_parser_m->measurement_type() );
       
   923         status_m.set_refuse_request( true_t );
       
   924         }
       
   925     }
       
   926 
       
   927 // ---------------------------------------------------------------------------
       
   928 // ---------------------------------------------------------------------------
       
   929 //    
       
   930 bool_t core_operation_handle_measurement_request_c::receive_frame(
       
   931     const core_frame_dot11_c* frame,
       
   932     u8_t rcpi )
       
   933     {   
       
   934     if ( frame->type() != core_frame_dot11_c::core_dot11_type_beacon &&
       
   935          frame->type() != core_frame_dot11_c::core_dot11_type_probe_resp )
       
   936         {
       
   937         DEBUG( "core_operation_handle_measurement_request_c::receive_frame() - not a beacon or a probe" );        
       
   938         return false_t;
       
   939         }
       
   940 
       
   941     core_ap_data_c* ap_data = core_ap_data_c::instance(
       
   942         server_m->get_wpx_adaptation_instance(),
       
   943         frame,
       
   944         rcpi,
       
   945         false_t );
       
   946     
       
   947     if ( ap_data )
       
   948         {        
       
   949         const core_ssid_s ssid = ap_data->ssid();
       
   950         DEBUG1S( "core_operation_handle_measurement_request_c::receive_frame() - SSID: ",
       
   951             ssid.length, &ssid.ssid[0] );
       
   952 
       
   953         core_mac_address_s bssid(
       
   954             ap_data->bssid() );
       
   955         DEBUG6( "core_operation_handle_measurement_request_c::receive_frame() - BSSID: %02X:%02X:%02X:%02X:%02X:%02X",
       
   956             bssid.addr[0], bssid.addr[1], bssid.addr[2], 
       
   957             bssid.addr[3], bssid.addr[4], bssid.addr[5] ); 
       
   958        
       
   959         server_m->get_scan_list().update_entry( *ap_data );
       
   960 
       
   961         delete ap_data;
       
   962         ap_data = NULL;            
       
   963         }
       
   964 
       
   965     return true_t;
       
   966     }
       
   967 
       
   968 // ---------------------------------------------------------------------------
       
   969 // ---------------------------------------------------------------------------
       
   970 //
       
   971 bool_t core_operation_handle_measurement_request_c::notify(
       
   972     core_am_indication_e indication )
       
   973     {
       
   974     if ( operation_state_m == core_state_scan_start &&
       
   975          indication == core_am_indication_wlan_scan_complete )
       
   976         {
       
   977         server_m->unregister_event_handler( this );
       
   978         server_m->unregister_frame_handler( this );
       
   979 
       
   980         DEBUG( "core_operation_handle_measurement_request_c::notify() - scan complete" );
       
   981 
       
   982         asynch_goto( core_state_create_response, CORE_TIMER_IMMEDIATELY );
       
   983 
       
   984         return true_t;
       
   985         }
       
   986 
       
   987     return false_t;
       
   988     }
       
   989 
       
   990 // ---------------------------------------------------------------------------
       
   991 // ---------------------------------------------------------------------------
       
   992 //
       
   993 bool_t core_operation_handle_measurement_request_c::validate_scan_channels()
       
   994     {
       
   995     core_scan_channels_c scan_channels;
       
   996     
       
   997     switch ( beacon_req_parser_m->channel_number() )
       
   998         {
       
   999         case SCAN_ALL_CHANNELS_IN_REGULATORY_CLASS:
       
  1000             {
       
  1001             DEBUG( "core_operation_handle_measurement_request_c::validate_scan_channels() - scan all channels in Regulatory Class" );
       
  1002             scan_channels.set( SCAN_CHANNELS_2DOT4GHZ_ETSI );
       
  1003             break;
       
  1004             }
       
  1005         case SCAN_ALL_CHANNELS_IN_AP_CH_REPORT:
       
  1006             {
       
  1007             DEBUG( "core_operation_handle_measurement_request_c::validate_scan_channels() - scan all channels from the AP Channel report" );
       
  1008             scan_channels.set( server_m->get_connection_data()->current_ap_data()->ap_channel_report() );
       
  1009             
       
  1010             if ( scan_channels.is_empty( SCAN_BAND_2DOT4GHZ ) )
       
  1011                 {
       
  1012                 DEBUG( "core_operation_handle_measurement_request_c::validate_scan_channels() - No AP Channel report available, using full mask" );
       
  1013                 scan_channels.set( SCAN_CHANNELS_2DOT4GHZ_ETSI );
       
  1014                 }
       
  1015             break;
       
  1016             }
       
  1017         default:
       
  1018             {
       
  1019             DEBUG1( "core_operation_handle_measurement_request_c::validate_scan_channels() - scan channel %u",
       
  1020                     beacon_req_parser_m->channel_number() );
       
  1021             scan_channels.add( SCAN_BAND_2DOT4GHZ, beacon_req_parser_m->channel_number() );
       
  1022             break;
       
  1023             }
       
  1024         }
       
  1025 
       
  1026     scan_channels.set( server_m->get_core_settings().valid_scan_channels( scan_channels.channels() ) );
       
  1027     
       
  1028     if ( scan_channels.is_empty( SCAN_BAND_2DOT4GHZ ) )
       
  1029         {
       
  1030         DEBUG( "core_operation_handle_measurement_request_c::validate_scan_channels() - no valid channels after check" );
       
  1031         return false_t;
       
  1032         }
       
  1033     
       
  1034     status_m.set_scan_channels( scan_channels.channels() );
       
  1035 
       
  1036     return true_t;
       
  1037     }
       
  1038 
       
  1039 // ---------------------------------------------------------------------------
       
  1040 // ---------------------------------------------------------------------------
       
  1041 //
       
  1042 u16_t core_operation_handle_measurement_request_c::get_channel_time(
       
  1043                                 core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_e measurement_mode )
       
  1044     {
       
  1045     u16_t ch_time( static_cast<u16_t> ( server_m->get_device_settings().active_scan_max_ch_time ) );
       
  1046     u16_t min_ch_time( static_cast<u16_t> ( server_m->get_device_settings().active_scan_min_ch_time ) );
       
  1047     
       
  1048     switch( measurement_mode )
       
  1049         {
       
  1050         case core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_passive:
       
  1051             {
       
  1052             ch_time = static_cast<u16_t> ( server_m->get_device_settings().passive_scan_max_ch_time );
       
  1053             min_ch_time = static_cast<u16_t> ( server_m->get_device_settings().passive_scan_min_ch_time );
       
  1054             break;
       
  1055             }
       
  1056         case core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon:
       
  1057             {
       
  1058             ch_time = BEACON_TABLE_MEASUREMENT_DURATION;
       
  1059             min_ch_time = BEACON_TABLE_MEASUREMENT_DURATION;
       
  1060             break;
       
  1061             }
       
  1062         case core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_active: // flow-through on purpose
       
  1063         default:
       
  1064             {
       
  1065             // active mode set above by default
       
  1066             }
       
  1067         }
       
  1068 
       
  1069     if ( beacon_req_parser_m )
       
  1070         {
       
  1071         if ( beacon_req_parser_m->measurement_duration() > min_ch_time &&
       
  1072              beacon_req_parser_m->measurement_duration() < ch_time )
       
  1073             {
       
  1074             ch_time = beacon_req_parser_m->measurement_duration();
       
  1075             }
       
  1076         }
       
  1077     
       
  1078     return ch_time;
       
  1079     }
       
  1080 
       
  1081 // ---------------------------------------------------------------------------
       
  1082 // ---------------------------------------------------------------------------
       
  1083 //
       
  1084 core_ssid_s core_operation_handle_measurement_request_c::get_ssid()
       
  1085     {
       
  1086     core_ssid_s ssid = BROADCAST_SSID;
       
  1087     if ( ssid_parser_m )
       
  1088         {
       
  1089         ssid = ssid_parser_m->ssid();
       
  1090         }
       
  1091     return ssid;
       
  1092     }
       
  1093 
       
  1094 // ---------------------------------------------------------------------------
       
  1095 // ---------------------------------------------------------------------------
       
  1096 //
       
  1097 core_scan_channels_c core_operation_handle_measurement_request_c::get_channels()
       
  1098     {
       
  1099     core_scan_channels_c channels;
       
  1100     u8_t channel( 0 );
       
  1101 
       
  1102     if ( ap_ch_rep_parser_m )
       
  1103         {
       
  1104         for( u16_t i=0; i < (ap_ch_rep_parser_m->data_length() - CORE_FRAME_MGMT_IE_AP_CHANNEL_REPORT_CHANNEL_OFFSET); i++ )
       
  1105             {
       
  1106             channel = ap_ch_rep_parser_m->ap_channel_report_channel( i );
       
  1107             channels.add( SCAN_BAND_2DOT4GHZ, channel );
       
  1108             }
       
  1109         }
       
  1110     return channels;
       
  1111     }
       
  1112 
       
  1113 // ---------------------------------------------------------------------------
       
  1114 // ---------------------------------------------------------------------------
       
  1115 //
       
  1116 bool_t core_operation_handle_measurement_request_c::match_found( core_ap_data_c& ap_data )
       
  1117     {
       
  1118     bool_t ssid_match_found( false_t );
       
  1119     bool_t bssid_match_found( false_t );
       
  1120 
       
  1121     if ( ssid_parser_m )
       
  1122         {
       
  1123         const core_ssid_s ap_ssid = ap_data.ssid();
       
  1124         const core_ssid_s request_ssid = ssid_parser_m->ssid();
       
  1125         
       
  1126         if ( request_ssid == ap_ssid )
       
  1127             {
       
  1128             DEBUG( "core_operation_handle_measurement_request_c::match_found() - ssid matches" );
       
  1129             ssid_match_found = true_t;
       
  1130             }
       
  1131         }
       
  1132     else
       
  1133         {
       
  1134         ssid_match_found = true_t;
       
  1135         }
       
  1136 
       
  1137     ASSERT( beacon_req_parser_m );
       
  1138     
       
  1139     const core_mac_address_s request_bssid = beacon_req_parser_m->bssid();
       
  1140     const core_mac_address_s ap_bssid = ap_data.bssid();
       
  1141     
       
  1142     const core_mac_address_s broadcast_bssid = BROADCAST_MAC_ADDR;
       
  1143     
       
  1144     if ( broadcast_bssid != request_bssid )
       
  1145         {
       
  1146         if ( request_bssid == ap_bssid )
       
  1147             {
       
  1148             DEBUG( "core_operation_handle_measurement_request_c::match_found() - bssid matches" );
       
  1149             bssid_match_found = true_t;
       
  1150             }
       
  1151         }
       
  1152     else
       
  1153         {
       
  1154         bssid_match_found = true_t;
       
  1155         }
       
  1156 
       
  1157     return ( ssid_match_found && bssid_match_found );
       
  1158     }
       
  1159 
       
  1160 // ---------------------------------------------------------------------------
       
  1161 // ---------------------------------------------------------------------------
       
  1162 //
       
  1163 bool_t core_operation_handle_measurement_request_c::create_response(
       
  1164     core_ap_data_c& ap_data )
       
  1165     {
       
  1166     core_frame_rm_ie_beacon_report_frame_body_ie_c* frame_body_ie = NULL;
       
  1167     
       
  1168     if ( brd_parser_m )
       
  1169         {
       
  1170         if ( brd_parser_m->reporting_detail() == core_frame_rm_ie_beacon_request_detail_ie_c::core_frame_rm_ie_brd_reporting_detail_fields_and_requested_elements )
       
  1171             {
       
  1172             if ( request_ie_parser_m )
       
  1173                 {
       
  1174                 u8_t ie_id_list[REQUEST_IE_MAX_LENGTH] = { 0 };
       
  1175                 u8_t ie_id_list_length = request_ie_parser_m->element_list( ie_id_list );
       
  1176 
       
  1177                 frame_body_ie = core_frame_rm_ie_beacon_report_frame_body_ie_c::instance(
       
  1178                     ap_data,
       
  1179                     ie_id_list,
       
  1180                     ie_id_list_length );
       
  1181                 }
       
  1182 
       
  1183             if ( frame_body_ie == NULL )
       
  1184                 {
       
  1185                 DEBUG( "core_operation_handle_measurement_request_c::create_response() - Unable to instantiate core_frame_rm_ie_beacon_report_frame_body_ie_c" );
       
  1186                 return false_t;
       
  1187                 }
       
  1188                 
       
  1189             DEBUG( "core_operation_handle_measurement_request_c::create_response() - Reported Frame Body data layout" );
       
  1190             DEBUG_BUFFER( frame_body_ie->data_length(), frame_body_ie->data() );
       
  1191 
       
  1192             }
       
  1193         else if ( brd_parser_m->reporting_detail() == core_frame_rm_ie_beacon_request_detail_ie_c::core_frame_rm_ie_brd_reporting_detail_default )
       
  1194             {
       
  1195             frame_body_ie = core_frame_rm_ie_beacon_report_frame_body_ie_c::instance(
       
  1196                 ap_data );
       
  1197 
       
  1198             if ( frame_body_ie == NULL )
       
  1199                 {
       
  1200                 DEBUG( "core_operation_handle_measurement_request_c::create_response() - Unable to instantiate core_frame_rm_ie_beacon_report_frame_body_ie_c" );
       
  1201                 return false_t;
       
  1202                 }
       
  1203                 
       
  1204             DEBUG( "core_operation_handle_measurement_request_c::create_response() - Reported Frame Body data layout" );
       
  1205             DEBUG_BUFFER( frame_body_ie->data_length(), frame_body_ie->data() );
       
  1206             }
       
  1207         }
       
  1208     else
       
  1209         {
       
  1210         frame_body_ie = core_frame_rm_ie_beacon_report_frame_body_ie_c::instance(
       
  1211             ap_data );
       
  1212 
       
  1213         if ( frame_body_ie == NULL )
       
  1214             {
       
  1215             DEBUG( "core_operation_handle_measurement_request_c::create_response() - Unable to instantiate core_frame_rm_ie_beacon_report_frame_body_ie_c" );
       
  1216             return false_t;
       
  1217             }
       
  1218             
       
  1219         DEBUG( "core_operation_handle_measurement_request_c::create_response() - Reported Frame Body data layout" );
       
  1220         DEBUG_BUFFER( frame_body_ie->data_length(), frame_body_ie->data() );
       
  1221         }
       
  1222 
       
  1223     core_frame_rm_ie_beacon_report_ie_c* ie = core_frame_rm_ie_beacon_report_ie_c::instance(
       
  1224                 BEACON_TABLE_REGULATORY_CLASS,
       
  1225                 actual_measurement_duration_m,
       
  1226                 BEACON_TABLE_REPORTED_FRAME_INFORMATION,
       
  1227                 ANTENNA_ID,
       
  1228                 ap_data );
       
  1229     
       
  1230     if ( ie == NULL )
       
  1231         {
       
  1232         DEBUG( "core_operation_handle_measurement_request_c::create_response() - Unable to instantiate core_frame_rm_ie_beacon_report_ie_c" );
       
  1233         return false_t;
       
  1234         }
       
  1235         
       
  1236     DEBUG( "core_operation_handle_measurement_request_c::create_response() - Beacon Report data layout" );
       
  1237     DEBUG_BUFFER( ie->length(), ie->data() );
       
  1238 
       
  1239     // create beacon report ie
       
  1240     core_frame_rm_ie_beacon_report_c* beacon_report_ie = NULL;
       
  1241 
       
  1242     if ( frame_body_ie != NULL )
       
  1243         {
       
  1244         beacon_report_ie = core_frame_rm_ie_beacon_report_c::instance(
       
  1245                 beacon_req_parser_m->measurement_token(),
       
  1246                 MEASUREMENT_REPORT_MODE_OK,
       
  1247                 ie,
       
  1248                 frame_body_ie );
       
  1249         }
       
  1250     else
       
  1251         {
       
  1252         beacon_report_ie = core_frame_rm_ie_beacon_report_c::instance(
       
  1253                 beacon_req_parser_m->measurement_token(),
       
  1254                 MEASUREMENT_REPORT_MODE_OK,
       
  1255                 ie );
       
  1256         }
       
  1257     
       
  1258     delete ie;
       
  1259     ie = NULL;
       
  1260 
       
  1261     if ( frame_body_ie )
       
  1262         {
       
  1263         delete frame_body_ie;
       
  1264         frame_body_ie = NULL;
       
  1265         }
       
  1266     
       
  1267     if ( beacon_report_ie == NULL )
       
  1268         {
       
  1269         DEBUG( "core_operation_handle_measurement_request_c::create_response() - Unable to instantiate core_frame_rm_ie_beacon_report_c" );
       
  1270         return false_t;
       
  1271         }
       
  1272     
       
  1273     DEBUG( "core_operation_handle_measurement_request_c::create_response() - Measurement Report data layout" );
       
  1274     DEBUG_BUFFER( beacon_report_ie->data_length(), beacon_report_ie->data() );
       
  1275 
       
  1276     if ( !add_to_report( beacon_report_ie ) )
       
  1277         {
       
  1278         // add_to_report returns NULL only in out-of-memory situation
       
  1279         DEBUG( "core_operation_handle_measurement_request_c::create_response() - Unable to create response to request" );
       
  1280         
       
  1281         // deallocate IE
       
  1282         delete beacon_report_ie;
       
  1283         beacon_report_ie = NULL;
       
  1284         
       
  1285         return false_t;
       
  1286         }
       
  1287 
       
  1288     DEBUG( "core_operation_handle_measurement_request_c::create_response() - dot11 frame data layout" );
       
  1289     DEBUG_BUFFER( report_m->data_length(), report_m->data() );
       
  1290     
       
  1291     // deallocate IE
       
  1292     delete beacon_report_ie;
       
  1293     beacon_report_ie = NULL;
       
  1294     
       
  1295     return true_t;
       
  1296     }
       
  1297 
       
  1298 // ---------------------------------------------------------------------------
       
  1299 // ---------------------------------------------------------------------------
       
  1300 //
       
  1301 void core_operation_handle_measurement_request_c::initialise_beacon_request_data()
       
  1302     {
       
  1303     DEBUG( "core_operation_handle_measurement_request_c::initialise_beacon_request_data()" );
       
  1304     
       
  1305     parsed_mask_m = MEASUREMENT_REQUEST_PARSED;
       
  1306     actual_measurement_duration_m = 0;
       
  1307     status_m.set_error_in_request( false_t );
       
  1308     status_m.set_refuse_request( false_t );
       
  1309 
       
  1310     }
       
  1311 
       
  1312 // ---------------------------------------------------------------------------
       
  1313 // ---------------------------------------------------------------------------
       
  1314 //
       
  1315 u32_t core_operation_handle_measurement_request_c::get_random_delay()
       
  1316     {
       
  1317     u32_t delay_in_us( 0 );
       
  1318     
       
  1319     if ( beacon_req_parser_m != NULL &&
       
  1320          beacon_req_parser_m->randomization_interval() != 0 &&
       
  1321          beacon_req_parser_m->measurement_mode() != core_frame_rm_ie_beacon_request_c::core_beacon_request_scan_mode_beacon )
       
  1322         {
       
  1323         u32_t delay_in_tus = core_am_tools_c::random() % beacon_req_parser_m->randomization_interval();
       
  1324         DEBUG1( "core_operation_handle_measurement_request_c::get_random_delay() - random delay in TUs: %u", delay_in_tus );
       
  1325         delay_in_us = delay_in_tus * TIMEUNITS_FROM_MICROSECONDS;  
       
  1326         }
       
  1327 
       
  1328     DEBUG1( "core_operation_handle_measurement_request_c::get_random_delay() - random delay in us: %u", delay_in_us );
       
  1329     
       
  1330     return delay_in_us;
       
  1331     }
       
  1332 
       
  1333 // ---------------------------------------------------------------------------
       
  1334 // ---------------------------------------------------------------------------
       
  1335 //
       
  1336 void core_operation_handle_measurement_request_c::user_cancel(
       
  1337     bool_t do_graceful_cancel )
       
  1338     {
       
  1339     DEBUG1( "core_operation_handle_measurement_request_c::user_cancel(do_graceful_cancel=%d)", do_graceful_cancel );
       
  1340     
       
  1341     if ( !do_graceful_cancel )
       
  1342         {
       
  1343         /**
       
  1344          * If we are in a middle of a scan, we have to schedule our own
       
  1345          * event.
       
  1346          */
       
  1347         if ( operation_state_m == core_operation_handle_measurement_request_c::core_state_scan_start &&
       
  1348              server_m->event_handler() == this &&
       
  1349              server_m->frame_handler() == this )
       
  1350             {
       
  1351             asynch_default_user_cancel();
       
  1352     
       
  1353             return;
       
  1354             }
       
  1355     
       
  1356         /**
       
  1357          * Everything else is handled by the default implementation.
       
  1358          */
       
  1359         core_operation_base_c::user_cancel( do_graceful_cancel );
       
  1360         }
       
  1361     }
       
  1362 
       
  1363