From d3a692f5c63d0620a65c300acaba351cdca6d71b Mon Sep 17 00:00:00 2001 From: Pierre LALET <pierre.lalet@cea.fr> Date: Thu, 24 Aug 2017 23:14:16 +0200 Subject: [PATCH] sndrcv(): move architecture tests outside of the receive loop --- scapy/sendrecv.py | 73 +++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py index 699221ab..8ac6ed46 100644 --- a/scapy/sendrecv.py +++ b/scapy/sendrecv.py @@ -70,6 +70,14 @@ def _sndrcv_snd(pks, timeout, inter, verbose, tobesent, all_stimuli, stopevent): stopevent.set() +class _BreakException(Exception): + """A dummy exception used in _get_pkt() to get out of the infinite +loop + + """ + pass + + def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, retry=0, multi=False): if conf.use_bpf: @@ -103,49 +111,50 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, timeout = None stopevent = threading.Event() + if WINDOWS: + def _get_pkt(): + return pks.recv(MTU) + elif conf.use_bpf: + def _get_pkt(): + if bpf_select([pks]): + return pks.recv() + elif conf.use_pcap or (not isinstance(pks, StreamSocket) + and (DARWIN or FREEBSD or OPENBSD)): + def _get_pkt(): + res = pks.nonblock_recv() + if res is None: + time.sleep(0.05) + return res + else: + def _get_pkt(): + try: + inp, _, _ = select([pks], [], [], 0.05) + except (IOError, select_error) as exc: + # select.error has no .errno attribute + if exc.args[0] != errno.EINTR: + raise + else: + if inp: + return pks.recv(MTU) + if stopevent.is_set(): + raise _BreakException() + thread = threading.Thread( target=_sndrcv_snd, args=(pks, timeout, inter, verbose, tobesent, all_stimuli, stopevent), ) thread.start() + try: try: while True: - r = None - if WINDOWS: - r = pks.recv(MTU) - elif conf.use_bpf: - inp = bpf_select([pks]) - if pks in inp: - r = pks.recv() - elif conf.use_pcap: - r = pks.nonblock_recv() - if r is None: - time.sleep(0.05) - elif not isinstance(pks, StreamSocket) and ( - FREEBSD or DARWIN or OPENBSD - ): - inp, _, _ = select([pks], [], [], 0.05) - if len(inp) == 0 or pks in inp: - r = pks.nonblock_recv() - else: - inp = [] - try: - inp, _, _ = select([pks], [], [], 0.05) - except (IOError, select_error) as exc: - # select.error has no .errno attribute - if exc.args[0] != errno.EINTR: - raise - if not inp and stopevent.is_set(): - break - if pks in inp: - r = pks.recv(MTU) + r = _get_pkt() if r is None: if stopevent.is_set(): break continue - ok = 0 + ok = False h = r.hashret() if h in hsent: hlst = hsent[h] @@ -154,7 +163,7 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, ans.append((sentpkt, r)) if verbose > 1: os.write(1, b"*") - ok = 1 + ok = True if not multi: del hlst[i] notans -= 1 @@ -174,6 +183,8 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, except KeyboardInterrupt: if chainCC: raise + except _BreakException: + pass finally: stopevent.set() thread.join() -- GitLab