From 475b34665cb7785ef04ea01d68255b513453a123 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 00:38:42 +0300 Subject: [PATCH] dpp-nfc: Improved version of HandoverServer::serve() Fix processing of the case where no handover select is sent out and add automatic (delayed) termination of the link on completing the handover successfully. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 59 ++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index d4a050a5e..3bec4573a 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -8,6 +8,7 @@ # See README for more details. import binascii +import errno import os import struct import sys @@ -493,6 +494,48 @@ class HandoverServer(nfc.handover.HandoverServer): self.llc = llc self.handover = handover + def serve(self, socket): + peer_sap = socket.getpeername() + summary("Serving handover client on remote sap {0}".format(peer_sap)) + send_miu = socket.getsockopt(nfc.llcp.SO_SNDMIU) + try: + while socket.poll("recv"): + req = bytearray() + while socket.poll("recv"): + r = socket.recv() + if r is None: + return None + summary("Received %d octets" % len(r)) + req += r + if len(req) == 0: + continue + try: + list(ndef.message_decoder(req, 'strict', {})) + except ndef.DecodeError: + continue + summary("Full message received") + resp = self._process_request_data(req) + if resp is None or len(resp) == 0: + summary("No handover select to send out - wait for a possible alternative handover request") + req = bytearray() + continue + + for offset in range(0, len(resp), send_miu): + if not socket.send(resp[offset:offset + send_miu]): + summary("Failed to send handover select - connection closed") + return + summary("Sent out full handover select") + if handover.terminate_on_hs_send_completion: + handover.delayed_exit() + + except nfc.llcp.Error as e: + global terminate_now + summary("HandoverServer exception: %s" % e, + color=None if e.errno == errno.EPIPE or terminate_now else C_RED) + finally: + socket.close() + summary("Handover serve thread exiting") + def process_handover_request_message(self, records): handover = self.handover self.ho_server_processing = True @@ -634,6 +677,7 @@ class HandoverServer(nfc.handover.HandoverServer): summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") + handover.terminate_on_hs_send_completion = True self.success = True handover.hs_sent = True elif handover.no_alt_proposal: @@ -848,6 +892,7 @@ class ConnectionHandover(): self.client = None self.client_thread = None self.reset() + self.exit_thread = None def reset(self): self.wait_connection = False @@ -859,6 +904,7 @@ class ConnectionHandover(): self.alt_proposal_used = False self.i_m_selector = False self.start_client_alt = False + self.terminate_on_hs_send_completion = False def start_handover_server(self, llc): summary("Start handover server") @@ -870,6 +916,19 @@ class ConnectionHandover(): self.client.close() self.client = None + def run_delayed_exit(self): + summary("Trying to exit (delayed)..") + time.sleep(0.25) + summary("Trying to exit (after wait)..") + global terminate_now + terminate_now = True + + def delayed_exit(self): + global only_one + if only_one: + self.exit_thread = threading.Thread(target=self.run_delayed_exit) + self.exit_thread.start() + def llcp_startup(llc): global handover handover.start_handover_server(llc)