|
1 /* |
|
2 * Copyright (c) 2005-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 a frame received from drivers |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "core_operation_handle_frame.h" |
|
20 #include "core_operation_ibss_merge.h" |
|
21 #include "core_operation_handle_delete_ts.h" |
|
22 #include "core_operation_update_power_mode.h" |
|
23 #include "core_operation_handle_measurement_request.h" |
|
24 #include "core_operation_handle_neighbor_response.h" |
|
25 #include "core_frame_radio_measurement_action.h" |
|
26 #include "core_frame_action_wmm.h" |
|
27 #include "core_frame_wmm_ie_tspec.h" |
|
28 #include "core_frame_action_rm.h" |
|
29 #include "core_frame_action_nr.h" |
|
30 #include "core_frame_tim_ie.h" |
|
31 #include "core_frame_dot11.h" |
|
32 #include "core_server.h" |
|
33 #include "core_tools.h" |
|
34 #include "am_debug.h" |
|
35 |
|
36 // ======== MEMBER FUNCTIONS ======== |
|
37 |
|
38 // --------------------------------------------------------------------------- |
|
39 // --------------------------------------------------------------------------- |
|
40 // |
|
41 core_operation_handle_frame_c::core_operation_handle_frame_c( |
|
42 u32_t request_id, |
|
43 core_server_c* server, |
|
44 abs_core_driverif_c* drivers, |
|
45 abs_core_server_callback_c* adaptation, |
|
46 core_frame_type_e frame_type, |
|
47 u16_t data_length, |
|
48 const u8_t* data ) : |
|
49 core_operation_base_c( core_operation_handle_frame, request_id, server, drivers, adaptation, |
|
50 core_base_flag_drivers_needed | core_base_flag_connection_needed ), |
|
51 type_m( frame_type ), |
|
52 data_length_m( data_length ), |
|
53 data_m( NULL ), |
|
54 frame_m( NULL ) |
|
55 { |
|
56 DEBUG( "core_operation_handle_frame_c::core_operation_handle_frame_c()" ); |
|
57 |
|
58 data_m = new u8_t[data_length_m]; |
|
59 if ( data_m ) |
|
60 { |
|
61 core_tools_c::copy( |
|
62 data_m, |
|
63 data, |
|
64 data_length ); |
|
65 } |
|
66 } |
|
67 |
|
68 // --------------------------------------------------------------------------- |
|
69 // --------------------------------------------------------------------------- |
|
70 // |
|
71 core_operation_handle_frame_c::~core_operation_handle_frame_c() |
|
72 { |
|
73 DEBUG( "core_operation_handle_frame_c::~core_operation_handle_frame_c()" ); |
|
74 |
|
75 delete frame_m; |
|
76 frame_m = NULL; |
|
77 delete[] data_m; |
|
78 data_m = NULL; |
|
79 } |
|
80 |
|
81 // --------------------------------------------------------------------------- |
|
82 // --------------------------------------------------------------------------- |
|
83 // |
|
84 core_error_e core_operation_handle_frame_c::next_state() |
|
85 { |
|
86 DEBUG( "core_operation_handle_frame_c::next_state()" ); |
|
87 |
|
88 switch ( operation_state_m ) |
|
89 { |
|
90 case core_state_init: |
|
91 { |
|
92 if ( !data_m ) |
|
93 { |
|
94 DEBUG( "core_operation_handle_frame_c::next_state() - no frame, aborting" ); |
|
95 failure_reason_m = core_error_no_memory; |
|
96 |
|
97 return cancel(); |
|
98 } |
|
99 |
|
100 if ( !server_m->get_core_settings().is_connected() ) |
|
101 { |
|
102 DEBUG( "core_operation_handle_frame_c::next_state() - not connected, discarding frame" ); |
|
103 |
|
104 return core_error_ok; |
|
105 } |
|
106 |
|
107 switch ( type_m ) |
|
108 { |
|
109 case core_frame_type_dot11: |
|
110 { |
|
111 DEBUG( "core_operation_handle_frame_c::next_state() - core_frame_type_dot11" ); |
|
112 frame_m = core_frame_dot11_c::instance( |
|
113 data_length_m, |
|
114 data_m, |
|
115 false_t ); |
|
116 if ( !frame_m ) |
|
117 { |
|
118 DEBUG( "core_operation_handle_frame_c::next_state() - unable to create parser" ); |
|
119 failure_reason_m = core_error_general; |
|
120 |
|
121 return cancel(); |
|
122 } |
|
123 |
|
124 #ifdef _DEBUG |
|
125 DEBUG1( "core_operation_handle_frame_c::next_state() - frame control: %04X", |
|
126 frame_m->frame_control() ); |
|
127 if ( frame_m->frame_control() & core_frame_dot11_c::core_dot11_frame_control_to_ds_mask ) |
|
128 { |
|
129 DEBUG( "core_operation_handle_frame_c::next_state() - frame control ToDS: enabled" ); |
|
130 } |
|
131 else |
|
132 { |
|
133 DEBUG( "core_operation_handle_frame_c::next_state() - frame control ToDS: disabled" ); |
|
134 } |
|
135 if ( frame_m->frame_control() & core_frame_dot11_c::core_dot11_frame_control_from_ds_mask ) |
|
136 { |
|
137 DEBUG( "core_operation_handle_frame_c::next_state() - frame control FromDS: enabled" ); |
|
138 } |
|
139 else |
|
140 { |
|
141 DEBUG( "core_operation_handle_frame_c::next_state() - frame control FromDS: disabled" ); |
|
142 } |
|
143 DEBUG1( "core_operation_handle_frame_c::next_state() - duration: %04X", |
|
144 frame_m->duration() ); |
|
145 |
|
146 core_mac_address_s mac( ZERO_MAC_ADDR ); |
|
147 mac = frame_m->destination(); |
|
148 DEBUG6( "core_operation_handle_frame_c::next_state() - destination: %02X:%02X:%02X:%02X:%02X:%02X", |
|
149 mac.addr[0], mac.addr[1], mac.addr[2], |
|
150 mac.addr[3], mac.addr[4], mac.addr[5] ); |
|
151 |
|
152 mac = frame_m->source(); |
|
153 DEBUG6( "core_operation_handle_frame_c::next_state() - source: %02X:%02X:%02X:%02X:%02X:%02X", |
|
154 mac.addr[0], mac.addr[1], mac.addr[2], |
|
155 mac.addr[3], mac.addr[4], mac.addr[5] ); |
|
156 |
|
157 mac = frame_m->bssid(); |
|
158 DEBUG6( "core_operation_handle_frame_c::next_state() - bssid: %02X:%02X:%02X:%02X:%02X:%02X", |
|
159 mac.addr[0], mac.addr[1], mac.addr[2], |
|
160 mac.addr[3], mac.addr[4], mac.addr[5] ); |
|
161 #endif // _DEBUG |
|
162 |
|
163 if ( frame_m->type() == core_frame_dot11_c::core_dot11_type_beacon && |
|
164 server_m->get_core_settings().is_connected() ) |
|
165 { |
|
166 if ( server_m->get_connection_data()->iap_data().operating_mode() == core_operating_mode_ibss ) |
|
167 { |
|
168 operation_state_m = core_state_done; |
|
169 |
|
170 DEBUG( "core_operation_handle_frame_c::next_state() - beacon received in IBSS mode" ); |
|
171 |
|
172 /** |
|
173 * Beacons received in IBSS mode are an indication that a merge |
|
174 * is needed. |
|
175 */ |
|
176 core_operation_base_c* operation = new core_operation_ibss_merge_c( |
|
177 request_id_m, |
|
178 server_m, |
|
179 drivers_m, |
|
180 adaptation_m, |
|
181 frame_m ); |
|
182 |
|
183 return run_sub_operation( operation ); |
|
184 } |
|
185 else |
|
186 { |
|
187 DEBUG( "core_operation_handle_frame_c::next_state() - beacon received in infrastructure mode" ); |
|
188 |
|
189 /** |
|
190 * Beacons received in infrastructure mode happen after an association. |
|
191 * |
|
192 * They are used to update the current AP data since beacons contain |
|
193 * fields not present in probe responses. |
|
194 */ |
|
195 if ( server_m->get_connection_data() && |
|
196 server_m->get_connection_data()->current_ap_data() && |
|
197 server_m->get_connection_data()->current_ap_data()->bssid() == frame_m->bssid() ) |
|
198 { |
|
199 core_frame_beacon_c* beacon = core_frame_beacon_c::instance( |
|
200 *frame_m ); |
|
201 if ( beacon ) |
|
202 { |
|
203 for( core_frame_dot11_ie_c* ie = beacon->first_ie(); ie; ie = beacon->next_ie() ) |
|
204 { |
|
205 if ( ie->element_id() == core_frame_dot11_ie_c::core_frame_dot11_ie_element_id_tim ) |
|
206 { |
|
207 core_frame_tim_ie_c* tim_ie = core_frame_tim_ie_c::instance( *ie ); |
|
208 if ( tim_ie && |
|
209 tim_ie->dtim_period() ) |
|
210 { |
|
211 DEBUG1( "core_operation_handle_frame_c::next_state() - updating AP DTIM period to %u", |
|
212 tim_ie->dtim_period() ); |
|
213 |
|
214 server_m->get_connection_data()->current_ap_data()->set_dtim_period( |
|
215 tim_ie->dtim_period() ); |
|
216 |
|
217 /** |
|
218 * Schedule a power mode update since we may have to adjust the wakeup interval |
|
219 * if DTIM skipping is used. |
|
220 * |
|
221 * We should avoid changing power mode if DHCP timer is active. |
|
222 */ |
|
223 if( !server_m->is_dhcp_timer_active() ) |
|
224 { |
|
225 DEBUG( "core_operation_handle_frame_c::next_state() - scheduling a power save update" ); |
|
226 |
|
227 core_operation_base_c* operation = new core_operation_update_power_mode_c( |
|
228 request_id_m, |
|
229 server_m, |
|
230 drivers_m, |
|
231 adaptation_m ); |
|
232 |
|
233 server_m->queue_int_operation( operation ); |
|
234 } |
|
235 else |
|
236 { |
|
237 DEBUG( "core_operation_handle_frame_c::next_state() - DHCP timer active, no power mode update" ); |
|
238 } |
|
239 } |
|
240 |
|
241 delete tim_ie; |
|
242 tim_ie = NULL; |
|
243 } |
|
244 |
|
245 delete ie; |
|
246 ie = NULL; |
|
247 } |
|
248 |
|
249 delete beacon; |
|
250 beacon = NULL; |
|
251 } |
|
252 } |
|
253 } |
|
254 } |
|
255 else if ( frame_m->type() == core_frame_dot11_c::core_dot11_type_action ) |
|
256 { |
|
257 core_frame_action_c* action = core_frame_action_c::instance( |
|
258 *frame_m ); |
|
259 if ( action ) |
|
260 { |
|
261 DEBUG( "core_operation_handle_frame_c::next_state() - 802.11 action frame found" ); |
|
262 DEBUG1( "core_operation_handle_frame_c::next_state() - 802.11 action category: 0x%02X", |
|
263 action->category() ); |
|
264 if ( action->category() == core_frame_action_c::core_dot11_action_category_wmm_qos ) |
|
265 { |
|
266 core_frame_action_wmm_c* wmm_action = core_frame_action_wmm_c::instance( *action ); |
|
267 if ( wmm_action ) |
|
268 { |
|
269 DEBUG( "core_operation_handle_frame_c::next_state() - 802.11 WMM action frame found" ); |
|
270 DEBUG1( "core_operation_handle_frame_c::next_state() - 802.11 WMM action type: 0x%02X", |
|
271 wmm_action->action_type() ); |
|
272 DEBUG1( "core_operation_handle_frame_c::next_state() - 802.11 WMM action dialog token: 0x%02X", |
|
273 wmm_action->dialog_token() ); |
|
274 DEBUG1( "core_operation_handle_frame_c::next_state() - 802.11 WMM action status: 0x%02X", |
|
275 wmm_action->status() ); |
|
276 |
|
277 if ( wmm_action->action_type() == core_frame_action_wmm_c::core_dot11_action_wmm_type_delts ) |
|
278 { |
|
279 for( core_frame_dot11_ie_c* ie = wmm_action->first_ie(); ie; ie = wmm_action->next_ie() ) |
|
280 { |
|
281 DEBUG1( "core_operation_handle_frame_c::next_state() - 802.11 WMM action IE ID: 0x%02X", |
|
282 ie->element_id() ); |
|
283 DEBUG1( "core_operation_handle_frame_c::next_state() - 802.11 WMM action IE length: 0x%02X", |
|
284 ie->length() ); |
|
285 |
|
286 if ( ie->element_id() == core_frame_dot11_ie_c::core_frame_dot11_ie_element_id_wmm_tspec ) |
|
287 { |
|
288 core_frame_wmm_ie_tspec_c* tspec_ie = core_frame_wmm_ie_tspec_c::instance( *ie ); |
|
289 if ( tspec_ie ) |
|
290 { |
|
291 core_operation_base_c* operation = new core_operation_handle_delete_ts_c( |
|
292 request_id_m, |
|
293 server_m, |
|
294 drivers_m, |
|
295 adaptation_m, |
|
296 tspec_ie->tid() ); |
|
297 |
|
298 server_m->queue_int_operation( operation ); |
|
299 |
|
300 delete tspec_ie; |
|
301 tspec_ie = NULL; |
|
302 } |
|
303 } |
|
304 |
|
305 delete ie; |
|
306 ie = NULL; |
|
307 } |
|
308 } |
|
309 |
|
310 delete wmm_action; |
|
311 wmm_action = NULL; |
|
312 } |
|
313 } |
|
314 else if ( action->category() == core_frame_action_c::core_dot11_action_category_rm ) |
|
315 { |
|
316 core_frame_radio_measurement_action_c* radio_measurement_action = core_frame_radio_measurement_action_c::instance( *action, true_t ); |
|
317 if ( radio_measurement_action ) |
|
318 { |
|
319 DEBUG( "core_operation_handle_frame_c::next_state() - 802.11 RM action frame found" ); |
|
320 DEBUG1( "core_operation_handle_frame_c::next_state() - 802.11 RM action type: 0x%02X", |
|
321 radio_measurement_action->action_type() ); |
|
322 |
|
323 if ( radio_measurement_action->action_type() == core_frame_radio_measurement_action_c::core_dot11_action_rm_type_meas_req ) |
|
324 { |
|
325 DEBUG( "core_operation_handle_frame_c::next_state() - Measurement Request received -> create operation to handle it" ); |
|
326 |
|
327 // copy received frame to a new memory location, rm_action will have the ownership of the new data |
|
328 core_frame_action_rm_c* rm_action = core_frame_action_rm_c::instance( *action, true_t ); |
|
329 if ( rm_action ) |
|
330 { |
|
331 // operation will deallocate rm_action when finished |
|
332 core_operation_base_c* operation = new core_operation_handle_measurement_request_c( |
|
333 request_id_m, |
|
334 server_m, |
|
335 drivers_m, |
|
336 adaptation_m, |
|
337 rm_action ); |
|
338 |
|
339 server_m->queue_int_operation( operation ); |
|
340 } |
|
341 } |
|
342 else if ( radio_measurement_action->action_type() == core_frame_radio_measurement_action_c::core_dot11_action_rm_type_neighbor_resp ) |
|
343 { |
|
344 DEBUG( "core_operation_handle_frame_c::next_state() - Neighbor Report Response received -> create operation to handle it" ); |
|
345 |
|
346 // copy received frame to a new memory location, nr_action will have the ownership of the new data |
|
347 core_frame_action_nr_c* nr_action = core_frame_action_nr_c::instance( *action, true_t ); |
|
348 if ( nr_action ) |
|
349 { |
|
350 // operation will deallocate nr_action when finished |
|
351 core_operation_base_c* operation = new core_operation_handle_neighbor_response_c( |
|
352 request_id_m, |
|
353 server_m, |
|
354 drivers_m, |
|
355 adaptation_m, |
|
356 nr_action ); |
|
357 |
|
358 server_m->queue_int_operation( operation ); |
|
359 } |
|
360 } |
|
361 else |
|
362 { |
|
363 DEBUG( "core_operation_handle_frame_c::next_state() - 802.11 RM action type not supported, ignoring..." ); |
|
364 } |
|
365 |
|
366 delete radio_measurement_action; |
|
367 radio_measurement_action = NULL; |
|
368 } |
|
369 } |
|
370 |
|
371 delete action; |
|
372 action = NULL; |
|
373 } |
|
374 } |
|
375 else |
|
376 { |
|
377 DEBUG( "core_operation_handle_frame_c::next_state() - unknown frame, discarding" ); |
|
378 } |
|
379 |
|
380 return core_error_ok; |
|
381 } |
|
382 case core_frame_type_snap: |
|
383 { |
|
384 DEBUG( "core_operation_handle_frame_c::next_state() - core_frame_type_snap, discarding" ); |
|
385 |
|
386 return core_error_ok; |
|
387 } |
|
388 default: |
|
389 { |
|
390 DEBUG( "core_operation_handle_frame_c::next_state() - unknown frame type, discarding" ); |
|
391 |
|
392 return core_error_ok; |
|
393 } |
|
394 } |
|
395 } |
|
396 case core_state_done: |
|
397 { |
|
398 DEBUG( "core_operation_handle_frame_c::next_state() - frame processing done" ); |
|
399 |
|
400 return core_error_ok; |
|
401 } |
|
402 default: |
|
403 { |
|
404 ASSERT( false_t ); |
|
405 } |
|
406 } |
|
407 |
|
408 return core_error_request_pending; |
|
409 } |