1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Class to control the BuffaloAP router.""" 6 7import logging 8import time 9import urlparse 10 11import dynamic_ap_configurator 12import ap_spec 13from selenium.common.exceptions import TimeoutException as \ 14 SeleniumTimeoutException 15 16 17class BuffaloAPConfigurator( 18 dynamic_ap_configurator.DynamicAPConfigurator): 19 """Configurator for Buffalo AP.""" 20 21 22 def __init__(self, ap_config): 23 super(BuffaloAPConfigurator, self).__init__(ap_config) 24 self._dhcp_delay = 30 25 26 27 def get_number_of_pages(self): 28 return 2 29 30 31 def is_update_interval_supported(self): 32 """ 33 Returns True if setting the PSK refresh interval is supported. 34 35 @return True is supported; False otherwise 36 """ 37 return True 38 39 40 def get_supported_modes(self): 41 return [{'band':ap_spec.BAND_2GHZ, 42 'modes':[ap_spec.MODE_B, ap_spec.MODE_G, ap_spec.MODE_N, 43 ap_spec.MODE_B | ap_spec.MODE_G, 44 ap_spec.MODE_N | ap_spec.MODE_G]}] 45 46 47 def get_supported_bands(self): 48 return [{'band':ap_spec.BAND_2GHZ, 49 'channels':[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}] 50 51 52 def is_security_mode_supported(self, security_mode): 53 """ 54 Returns if a given security_type is supported. 55 56 @param security_mode: one security modes defined in the APSpec 57 58 @return True if the security mode is supported; False otherwise. 59 60 """ 61 return security_mode in (ap_spec.SECURITY_TYPE_DISABLED, 62 ap_spec.SECURITY_TYPE_WPAPSK, 63 ap_spec.SECURITY_TYPE_WPA2PSK, 64 ap_spec.SECURITY_TYPE_WEP) 65 66 67 def navigate_to_page(self, page_number): 68 """ 69 Navigates to the page corresponding to the given page number. 70 71 This method performs the translation between a page number and a url to 72 load. This is used internally by apply_settings. 73 74 @param page_number: page number of the page to load 75 76 """ 77 if page_number == 1: 78 page_url = urlparse.urljoin(self.admin_interface_url, 79 'Wireless_Basic.asp') 80 self.get_url(page_url, page_title='DD-WRT') 81 elif page_number == 2: 82 page_url = urlparse.urljoin(self.admin_interface_url, 83 'WL_WPATable.asp') 84 self.get_url(page_url, page_title='DD-WRT') 85 else: 86 raise RuntimeError('Invalid page number passed. Number of pages ' 87 '%d, page value sent was %d' % 88 (self.get_number_of_pages(), page_number)) 89 90 91 def save_page(self, page_number): 92 """ 93 Saves the given page. 94 95 @param page_number: Page number of the page to save. 96 97 """ 98 apply_set = '//input[@name="apply_button"]' 99 try: 100 self.wait_for_object_by_xpath(apply_set, wait_time=30) 101 except SeleniumTimeoutException as e: 102 self.driver.refresh() 103 self.wait_for_object_by_xpath(apply_set, wait_time=30) 104 self.click_button_by_xpath(apply_set) 105 timeout = 0 106 while self.object_by_xpath_exist("ddwrt_message") and timeout < 60: 107 time.sleep(1) 108 timeout = timeout + 1 109 self._retry_page(page_number) 110 111 112 def _retry_page(self, page_number): 113 """Sometimes the interface goes down, retry.""" 114 for i in range(3): 115 if self.driver.title.find('DD-WRT') == -1: 116 self.navigate_to_page(page_number) 117 else: 118 return 119 120 def _wait_for_item_in_popup(self, item, popup): 121 """Wait for the popup to be enumerated.""" 122 for i in range(3): 123 self.wait_for_object_by_xpath(popup) 124 if self.item_in_popup_by_xpath_exist(item, popup): 125 break 126 else: 127 time.sleep(1) 128 129 130 def set_mode(self, mode, band=None): 131 self.add_item_to_command_list(self._set_mode, (mode,), 1, 900) 132 133 134 def _set_mode(self, mode): 135 # Bands are not supported, so ignore. 136 # Create the mode to popup item mapping. 137 mode_mapping = {ap_spec.MODE_B:'B-Only', ap_spec.MODE_G: 'G-Only', 138 ap_spec.MODE_N:'N-Only (2.4 GHz)', 139 ap_spec.MODE_M:'Mixed', 140 ap_spec.MODE_B | ap_spec.MODE_G:'BG-Mixed', 141 ap_spec.MODE_N | ap_spec.MODE_G:'NG-Mixed'} 142 mode_name = '' 143 if mode in mode_mapping: 144 mode_name = mode_mapping[mode] 145 else: 146 raise RuntimeError('The mode %d not supported by router %s. ', 147 hex(mode), self.name) 148 xpath = '//select[@name="ath0_net_mode"]' 149 try: 150 self.select_item_from_popup_by_xpath(mode_name, xpath) 151 except SeleniumTimeoutException, e: 152 self.driver.refresh() 153 self.select_item_from_popup_by_xpath(mode_name, xpath) 154 155 156 def set_radio(self, enabled): 157 # We cannot turn off radio on Buffalo. 158 logging.debug('This router (%s) does not support radio.', self.name) 159 return None 160 161 162 def set_ssid(self, ssid): 163 self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 900) 164 165 166 def _set_ssid(self, ssid): 167 xpath = '//input[@maxlength="32" and @name="ath0_ssid"]' 168 self.set_content_of_text_field_by_xpath(ssid, xpath) 169 self._ssid = ssid 170 171 172 def set_channel(self, channel): 173 self.add_item_to_command_list(self._set_channel, (channel,), 1, 900) 174 175 176 def _set_channel(self, channel): 177 position = self._get_channel_popup_position(channel) 178 channel_choices = ['1 - 2412 MHz', '2 - 2417 MHz', '3 - 2422 MHz', 179 '4 - 2427 MHz', '5 - 2432 MHz', '6 - 2437 MHz', 180 '7 - 2442 MHz', '8 - 2447 MHz', '9 - 2452 MHz', 181 '10 - 2457 MHz', '11 - 2462 MHz'] 182 xpath = '//select[@name="ath0_channel"]' 183 if self.number_of_items_in_popup_by_xpath(xpath) == 0: 184 # If the popup is empty, refresh. 185 self.driver.refresh() 186 self.select_item_from_popup_by_xpath(channel_choices[position], xpath) 187 188 189 def set_ch_width(self, channel_width): 190 """ 191 Adjusts the channel channel width. 192 193 @param channel_width: the channel width 194 """ 195 self.add_item_to_command_list(self._set_ch_width,(channel_width,), 1, 196 900) 197 198 199 def _set_ch_width(self, channel_width): 200 channel_width_choice=['Full (20 MHz)', 'Half (10 MHz)', 201 'Quarter (5 MHz)'] 202 xpath = '//select[@name="ath0_channelbw"]' 203 self.select_item_from_popup_by_xpath( 204 channel_width_choice[channel_width], xpath) 205 206 207 def set_wireless_mode(self, wireless_mo): 208 """ 209 Queues a change to the wireless mode. 210 211 @param wireless_mo: the wireless mode. 212 """ 213 self.add_item_to_command_list(self._set_wireless_mode, 214 (wireless_mo,), 1, 900) 215 216 217 def _set_wireless_mode(self, wireless_mo): 218 """ 219 Sets the wireless mode. 220 221 @param wireless_mo: the wireless mode. 222 """ 223 wireless_mode_choices = ['AP', 'Client', 'Client Bridge', 224 'Adhoc', 'WDS Station', 'WDS AP'] 225 xpath = '//select[@name="ath0_mode"]' 226 self.select_item_from_popup_by_xpath(wireless_mode_choices[wireless_mo], 227 xpath) 228 229 230 def set_band(self, band): 231 logging.debug('This router (%s) does not support multiple bands.', 232 self.name) 233 return None 234 235 236 def set_security_disabled(self): 237 self.add_item_to_command_list(self._set_security_disabled, (), 2, 1000) 238 239 240 def _set_security_disabled(self): 241 self._retry_page(2) 242 243 popup = '//select[@name="ath0_security_mode"]' 244 disabled_item = 'Disabled' 245 246 self._wait_for_item_in_popup(disabled_item, popup) 247 248 self.select_item_from_popup_by_xpath(disabled_item, popup) 249 250 for i in range(3): 251 if (self.object_by_xpath_exist('//input[@name="ath0_passphrase"]') 252 or self.object_by_xpath_exist('//input[@name="ath0_wpa_psk"]')): 253 time.sleep(1) 254 else: 255 break 256 257 258 def set_security_wep(self, key_value, authentication): 259 self.add_item_to_command_list(self._set_security_wep, 260 (key_value, authentication), 2, 1000) 261 262 263 def _set_security_wep(self, key_value, authentication): 264 # Buffalo supports WEP with wireless network mode N. 265 # No exception is thrown for N-mode with WEP security. 266 self._retry_page(2) 267 268 popup = '//select[@name="ath0_security_mode"]' 269 text_field = '//input[@name="ath0_passphrase"]' 270 wep_item = 'WEP' 271 272 self._wait_for_item_in_popup(wep_item, popup) 273 274 self.select_item_from_popup_by_xpath('WEP', popup, 275 wait_for_xpath=text_field) 276 self.wait_for_object_by_xpath(text_field) 277 self.set_content_of_text_field_by_xpath(key_value, text_field, 278 abort_check=True) 279 self.click_button_by_xpath('//input[@value="Generate"]') 280 281 282 def set_security_wpapsk(self, security, shared_key, update_interval=3600): 283 self.add_item_to_command_list(self._set_security_wpapsk, 284 (security, shared_key, update_interval), 285 2, 900) 286 287 288 def _set_security_wpapsk(self, security, shared_key, update_interval=3600): 289 self._retry_page(2) 290 popup = '//select[@name="ath0_security_mode"]' 291 key_field = '//input[@name="ath0_wpa_psk"]' 292 interval_field = '//input[@name="ath0_wpa_gtk_rekey"]' 293 if security == ap_spec.SECURITY_TYPE_WPAPSK: 294 wpa_item = 'WPA Personal' 295 else: 296 wpa_item = 'WPA2 Personal' 297 self._wait_for_item_in_popup(wpa_item, popup) 298 self.select_item_from_popup_by_xpath(wpa_item, popup) 299 self.wait_for_object_by_xpath(key_field, wait_time=30) 300 self.set_content_of_text_field_by_xpath(shared_key, key_field) 301 self.wait_for_object_by_xpath(interval_field) 302 self.set_content_of_text_field_by_xpath(str(update_interval), 303 interval_field) 304 305 306 def set_visibility(self, visible=True): 307 self.add_item_to_command_list(self._set_visibility, (visible,), 1, 900) 308 309 310 def _set_visibility(self, visible=True): 311 int_value = 0 if visible else 1 312 xpath = '//input[@value="%d" and @name="ath0_closed"]' % int_value 313 self.click_button_by_xpath(xpath) 314