def tcpdump(remote, args='', prefix=None, latency=2, lfilter=None):
"""Non-blocking context manager for run tcpdump on backgroud.
It yields path to pcap file.
Args:
remote (SshClient): instance of ssh client
args (str, optional): additional ``tcpdump`` args
prefix (str, optional): prefix for command. It can be useful for
executing tcpdump on ip namespace.
latency (int, optional): time to wait after tcpdump's starting and
before tcpdump's termination to guarantee that all packets will be
captured
lfilter (function, optional): function to filter returned packets. By
default all packets will be returned.
Yields:
str: path to pcap file
"""
pcap_file = tempfile.mktemp()
stdout_file = tempfile.mktemp()
cmd = "tcpdump -w{pcap_file} {args}".format(args=args, pcap_file=pcap_file)
if prefix:
cmd = "{} {}".format(prefix, cmd)
with remote.sudo():
pid = remote.background_call(cmd, stdout=stdout_file)
# wait tcpdump to start
remote.execute('while [ ! -f {} ]; do sleep 1; done'.format(pcap_file))
# tcpdump need some more time to start packets capturing
time.sleep(latency)
yield pcap_file
# wait some time to allow tcpdump to process all packets
time.sleep(latency)
with remote.sudo():
remote.execute('kill -SIGINT {}'.format(pid))
remote.wait_process_done(pid, timeout=latency)
with remote.open(pcap_file) as src:
with open(pcap_file, 'wb') as dst:
dst.write(src.read())
remote.execute('rm {}'.format(pcap_file))