Skip to content

Commit

Permalink
Merge pull request #191 from rtobar/pcap-user-filter
Browse files Browse the repository at this point in the history
Add support for user-provided libpcap filter
  • Loading branch information
bmerry committed Jul 20, 2022
2 parents 0ffd2cc + 6fce080 commit 3097b10
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 10 deletions.
10 changes: 7 additions & 3 deletions doc/py-recv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,15 @@ it, or repeatedly call :py:meth:`~spead2.recv.Stream.get`.
:param socket.socket acceptor: Listening socket
:param int max_size: Largest packet size that will be accepted.

.. py:method:: add_udp_pcap_file_reader(filename)
.. py:method:: add_udp_pcap_file_reader(filename, filter='')
Feed data from a pcap file (for example, captured with :program:`tcpdump`
or :ref:`mcdump`). This is only available if libpcap development files
were found at compile time.
or :ref:`mcdump`). An optional filter selects a subset of the packets from
the capture file. This is only available if libpcap development files were
found at compile time.

:param str filename: Filename of the capture file
:param str filter: Filter to apply to packets from the capture file

.. py:method:: add_inproc_reader(queue)
Expand Down
5 changes: 4 additions & 1 deletion include/spead2/recv_udp_pcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ namespace recv

/**
* Reader class that feeds data from a pcap file to a stream.
*
* An optional filter selects a subset of the packets in the capture file.
*/
class udp_pcap_file_reader : public udp_reader_base
{
Expand All @@ -55,10 +57,11 @@ class udp_pcap_file_reader : public udp_reader_base
*
* @param owner Owning stream
* @param filename Filename of the capture file
* @param filter Filter to apply to packets from the capture file
*
* @throws std::runtime_error if @a filename could not read
*/
udp_pcap_file_reader(stream &owner, const std::string &filename);
udp_pcap_file_reader(stream &owner, const std::string &filename, const std::string &filter = "");
virtual ~udp_pcap_file_reader();

virtual void stop() override;
Expand Down
6 changes: 3 additions & 3 deletions src/py_recv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,10 @@ static void add_udp_ibv_reader_new(stream &s, const udp_ibv_config_wrapper &conf
#endif // SPEAD2_USE_IBV

#if SPEAD2_USE_PCAP
static void add_udp_pcap_file_reader(stream &s, const std::string &filename)
static void add_udp_pcap_file_reader(stream &s, const std::string &filename, const std::string &filter)
{
py::gil_scoped_release gil;
s.emplace_reader<udp_pcap_file_reader>(filename);
s.emplace_reader<udp_pcap_file_reader>(filename, filter);
}
#endif

Expand Down Expand Up @@ -773,7 +773,7 @@ py::module register_module(py::module &parent)
#endif
#if SPEAD2_USE_PCAP
.def("add_udp_pcap_file_reader", add_udp_pcap_file_reader,
"filename"_a)
"filename"_a, "filter"_a = "")
#endif
.def("add_inproc_reader", add_inproc_reader,
"queue"_a)
Expand Down
7 changes: 5 additions & 2 deletions src/recv_udp_pcap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void udp_pcap_file_reader::run()
stopped();
}

udp_pcap_file_reader::udp_pcap_file_reader(stream &owner, const std::string &filename)
udp_pcap_file_reader::udp_pcap_file_reader(stream &owner, const std::string &filename, const std::string &user_filter)
: udp_reader_base(owner)
{
// Open the file
Expand All @@ -108,8 +108,11 @@ udp_pcap_file_reader::udp_pcap_file_reader(stream &owner, const std::string &fil
throw std::runtime_error(errbuf);
// Set a filter to ensure that we only get UDP4 packets with no fragmentation
bpf_program filter;
std::string filter_expression = "ip proto \\udp and ip[6:2] & 0x3fff = 0";
if (!user_filter.empty())
filter_expression += " and (" + user_filter + ')';
if (pcap_compile(handle, &filter,
"ip proto \\udp and ip[6:2] & 0x3fff = 0",
filter_expression.c_str(),
1, PCAP_NETMASK_UNKNOWN) != 0)
throw std::runtime_error(pcap_geterr(handle));
if (pcap_setfilter(handle, &filter) != 0)
Expand Down
2 changes: 1 addition & 1 deletion src/spead2/recv/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class _Stream:
comp_vector: int = ..., max_poll: int = ...) -> None: ...
@overload
def add_udp_ibv_reader(self, config: UdpIbvConfig) -> None: ...
def add_udp_pcap_file_reader(self, filename: str) -> None: ...
def add_udp_pcap_file_reader(self, filename: str, filter: str = ...) -> None: ...
def add_inproc_reader(self, queue: spead2.InprocQueue) -> None: ...
def stop(self) -> None: ...
@property
Expand Down

0 comments on commit 3097b10

Please sign in to comment.