3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-22 14:49:24 +01:00

auto-t: hostapd.py: use IO watch for hostapd events

With how fast UML is hostapd events were being sent out prior to
ever calling wait_for_event. Instead set an IO watch on the control
socket and cache all events as they come. Then, when wait_for_event
is called, it can reference this list. If the event is found any
older events are purged from the list.

The AP-ENABLED event needed a special case because hostapd gets
started before the IO watch can be registered. To fix this an
enabled property was added which queries the state directly. This
is checked first, and if not enabled wait_for_event continues normally.
This commit is contained in:
James Prestwood 2022-03-31 16:16:39 -07:00 committed by Denis Kenzior
parent dbd6ddfc95
commit 31b5275c1f
2 changed files with 48 additions and 23 deletions

View File

@ -81,27 +81,48 @@ class HostapdCLI(object):
self.ctrl_sock.connect(self.socket_path + '/' + self.ifname) self.ctrl_sock.connect(self.socket_path + '/' + self.ifname)
self.events = []
self.io_watch = GLib.io_add_watch(self.ctrl_sock, GLib.IO_IN, self._handle_data_in)
if 'OK' not in self._ctrl_request('ATTACH'): if 'OK' not in self._ctrl_request('ATTACH'):
raise Exception('ATTACH failed') raise Exception('ATTACH failed')
ctrl_count = ctrl_count + 1 ctrl_count = ctrl_count + 1
def _poll_event(self, event): def _handle_data_in(self, sock, *args):
if not self._data_available(0.25): newdata = sock.recv(4096)
return False
data = self.ctrl_sock.recv(4096).decode('utf-8') decoded = newdata.decode('utf-8')
if event in data: if len(decoded) >= 3 and decoded[0] == '<' and decoded[2] == '>':
return data decoded = decoded[3:]
while len(decoded) and decoded[-1] == '\n':
decoded = decoded[:-1]
self.events.insert(0, decoded)
return True
def _poll_event(self, event):
# Look through the list (most recent is first) until the even is found.
# Once found consume this event and any older ones as to not
# accidentally trigger a false positive later on.
for idx, e in enumerate(self.events):
if event in e:
self.events = self.events[:idx]
return e
return False return False
def wait_for_event(self, event, timeout=10): def wait_for_event(self, event, timeout=10):
if event == 'AP-ENABLED':
if self.enabled:
return 'AP-ENABLED'
return ctx.non_block_wait(self._poll_event, timeout, event, return ctx.non_block_wait(self._poll_event, timeout, event,
exception=TimeoutError("waiting for event")) exception=TimeoutError("waiting for event"))
def _data_available(self, timeout=2): def _data_available(self):
[r, w, e] = select.select([self.ctrl_sock], [], [], timeout) [r, w, e] = select.select([self.ctrl_sock], [], [])
if r: if r:
return True return True
return False return False
@ -228,25 +249,28 @@ class HostapdCLI(object):
ctx.start_process(cmd).wait() ctx.start_process(cmd).wait()
self.wait_for_event('AP-CSA-FINISHED') self.wait_for_event('AP-CSA-FINISHED')
@property def _get_status(self):
def bssid(self): ret = {}
cmd = self.cmdline + ['status'] cmd = self.cmdline + ['status']
proc = ctx.start_process(cmd) proc = ctx.start_process(cmd)
proc.wait() proc.wait()
status = proc.out.split('\n') status = proc.out.strip().split('\n')
bssid = [x for x in status if x.startswith('bssid')] for kv in status:
bssid = bssid[0].split('=') k, v = kv.split('=')
return bssid[1] ret[k] = v
return ret
@property
def bssid(self):
return self._get_status()['bssid[0]']
@property @property
def frequency(self): def frequency(self):
cmd = self.cmdline + ['status'] return int(self._get_status()['freq'])
proc = ctx.start_process(cmd)
proc.wait()
status = proc.out.split('\n')
frequency = [x for x in status if x.startswith('freq')][0] @property
frequency = frequency.split('=')[1] def enabled(self):
return self._get_status()['state'] == 'ENABLED'
return int(frequency)

View File

@ -540,7 +540,8 @@ class Hostapd:
except: except:
print("Failed to remove %s" % self.global_ctrl_iface) print("Failed to remove %s" % self.global_ctrl_iface)
self.instances = None for hapd in self.instances:
GLib.source_remove(hapd.cli.io_watch)
# Hostapd may have already been stopped # Hostapd may have already been stopped
if self.process: if self.process: