summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnuradio-runtime/include/gnuradio/CMakeLists.txt1
-rw-r--r--gnuradio-runtime/include/gnuradio/pdu.h46
-rw-r--r--gnuradio-runtime/lib/CMakeLists.txt1
-rw-r--r--gnuradio-runtime/lib/pdu.cc119
-rw-r--r--gnuradio-runtime/python/gnuradio/__init__.py1
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/bindings/CMakeLists.txt3
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h51
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc94
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/bindings/python_bindings.cc2
-rw-r--r--gr-network/grc/CMakeLists.txt2
-rw-r--r--gr-network/grc/network_socket_pdu.block.yml57
-rw-r--r--gr-network/grc/network_tuntap_pdu.block.yml44
-rw-r--r--gr-network/include/gnuradio/network/CMakeLists.txt2
-rw-r--r--gr-network/include/gnuradio/network/socket_pdu.h48
-rw-r--r--gr-network/include/gnuradio/network/tuntap_pdu.h42
-rw-r--r--gr-network/lib/CMakeLists.txt4
-rw-r--r--gr-network/lib/socket_pdu_impl.cc271
-rw-r--r--gr-network/lib/socket_pdu_impl.h68
-rw-r--r--gr-network/lib/stream_pdu_base.cc110
-rw-r--r--gr-network/lib/stream_pdu_base.h52
-rw-r--r--gr-network/lib/tcp_connection.cc101
-rw-r--r--gr-network/lib/tcp_connection.h54
-rw-r--r--gr-network/lib/tuntap_pdu_impl.cc172
-rw-r--r--gr-network/lib/tuntap_pdu_impl.h41
-rw-r--r--gr-network/python/network/CMakeLists.txt16
-rw-r--r--gr-network/python/network/bindings/CMakeLists.txt6
-rw-r--r--gr-network/python/network/bindings/docstrings/socket_pdu_pydoc_template.h24
-rw-r--r--gr-network/python/network/bindings/docstrings/tuntap_pdu_pydoc_template.h24
-rw-r--r--gr-network/python/network/bindings/python_bindings.cc4
-rw-r--r--gr-network/python/network/bindings/socket_pdu_python.cc49
-rw-r--r--gr-network/python/network/bindings/tuntap_pdu_python.cc47
-rw-r--r--gr-network/python/network/qa_socket_pdu.py141
-rw-r--r--gr-pdu/grc/CMakeLists.txt8
-rw-r--r--gr-pdu/grc/pdu.tree.yml9
-rw-r--r--gr-pdu/grc/pdu_pdu_filter.block.yml41
-rw-r--r--gr-pdu/grc/pdu_pdu_remove.block.yml29
-rw-r--r--gr-pdu/grc/pdu_pdu_set.block.yml34
-rw-r--r--gr-pdu/grc/pdu_pdu_to_tagged_stream.block.yml37
-rw-r--r--gr-pdu/grc/pdu_random_pdu.block.yml39
-rw-r--r--gr-pdu/grc/pdu_tagged_stream_to_pdu.block.yml36
-rw-r--r--gr-pdu/include/gnuradio/pdu/CMakeLists.txt8
-rw-r--r--gr-pdu/include/gnuradio/pdu/pdu.h19
-rw-r--r--gr-pdu/include/gnuradio/pdu/pdu_filter.h43
-rw-r--r--gr-pdu/include/gnuradio/pdu/pdu_remove.h41
-rw-r--r--gr-pdu/include/gnuradio/pdu/pdu_set.h42
-rw-r--r--gr-pdu/include/gnuradio/pdu/pdu_to_tagged_stream.h44
-rw-r--r--gr-pdu/include/gnuradio/pdu/random_pdu.h41
-rw-r--r--gr-pdu/include/gnuradio/pdu/tagged_stream_to_pdu.h49
-rw-r--r--gr-pdu/lib/CMakeLists.txt8
-rw-r--r--gr-pdu/lib/pdu.cc55
-rw-r--r--gr-pdu/lib/pdu_filter_impl.cc59
-rw-r--r--gr-pdu/lib/pdu_filter_impl.h37
-rw-r--r--gr-pdu/lib/pdu_remove_impl.cc51
-rw-r--r--gr-pdu/lib/pdu_remove_impl.h33
-rw-r--r--gr-pdu/lib/pdu_set_impl.cc52
-rw-r--r--gr-pdu/lib/pdu_set_impl.h35
-rw-r--r--gr-pdu/lib/pdu_split_impl.cc14
-rw-r--r--gr-pdu/lib/pdu_split_impl.h12
-rw-r--r--gr-pdu/lib/pdu_to_tagged_stream_impl.cc98
-rw-r--r--gr-pdu/lib/pdu_to_tagged_stream_impl.h41
-rw-r--r--gr-pdu/lib/random_pdu_impl.cc74
-rw-r--r--gr-pdu/lib/random_pdu_impl.h46
-rw-r--r--gr-pdu/lib/tagged_stream_to_pdu_impl.cc66
-rw-r--r--gr-pdu/lib/tagged_stream_to_pdu_impl.h39
-rw-r--r--gr-pdu/python/pdu/bindings/CMakeLists.txt8
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/pdu_filter_pydoc_template.h36
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/pdu_pydoc_template.h12
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/pdu_remove_pydoc_template.h30
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/pdu_set_pydoc_template.h33
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/pdu_to_tagged_stream_pydoc_template.h24
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/random_pdu_pydoc_template.h24
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/tagged_stream_to_pdu_pydoc_template.h24
-rw-r--r--gr-pdu/python/pdu/bindings/pdu_filter_python.cc58
-rw-r--r--gr-pdu/python/pdu/bindings/pdu_python.cc35
-rw-r--r--gr-pdu/python/pdu/bindings/pdu_remove_python.cc45
-rw-r--r--gr-pdu/python/pdu/bindings/pdu_set_python.cc48
-rw-r--r--gr-pdu/python/pdu/bindings/pdu_to_tagged_stream_python.cc50
-rw-r--r--gr-pdu/python/pdu/bindings/python_bindings.cc16
-rw-r--r--gr-pdu/python/pdu/bindings/random_pdu_python.cc48
-rw-r--r--gr-pdu/python/pdu/bindings/tagged_stream_to_pdu_python.cc50
-rw-r--r--gr-pdu/python/pdu/qa_pdu.py131
-rw-r--r--gr-pdu/python/pdu/qa_pdu_split.py18
82 files changed, 3582 insertions, 45 deletions
diff --git a/gnuradio-runtime/include/gnuradio/CMakeLists.txt b/gnuradio-runtime/include/gnuradio/CMakeLists.txt
index 4789a71bbe..9f38af335a 100644
--- a/gnuradio-runtime/include/gnuradio/CMakeLists.txt
+++ b/gnuradio-runtime/include/gnuradio/CMakeLists.txt
@@ -40,6 +40,7 @@ install(FILES
msg_handler.h
msg_queue.h
nco.h
+ pdu.h
prefs.h
pycallback_object.h
random.h
diff --git a/gnuradio-runtime/include/gnuradio/pdu.h b/gnuradio-runtime/include/gnuradio/pdu.h
new file mode 100644
index 0000000000..f6957e5487
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/pdu.h
@@ -0,0 +1,46 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013,2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+
+#ifndef INCLUDED_GR_PDU_H
+#define INCLUDED_GR_PDU_H
+
+#include <gnuradio/api.h>
+#include <pmt/pmt.h>
+
+namespace gr {
+namespace msgport_names {
+// static const PMT interned string getters for standard port names
+GR_RUNTIME_API const pmt::pmt_t bpdu();
+GR_RUNTIME_API const pmt::pmt_t cpdu();
+GR_RUNTIME_API const pmt::pmt_t dict();
+GR_RUNTIME_API const pmt::pmt_t fpdu();
+GR_RUNTIME_API const pmt::pmt_t msg();
+GR_RUNTIME_API const pmt::pmt_t pdu();
+GR_RUNTIME_API const pmt::pmt_t pdus(); // compatibility, use of pdu() preferred
+GR_RUNTIME_API const pmt::pmt_t vec();
+} /* namespace ports */
+
+namespace types {
+enum vector_type { byte_t, float_t, complex_t };
+} /* namespace types */
+
+namespace pdu {
+// pdu functions
+GR_RUNTIME_API size_t itemsize(types::vector_type type);
+GR_RUNTIME_API bool type_matches(types::vector_type type, pmt::pmt_t v);
+GR_RUNTIME_API pmt::pmt_t
+make_pdu_vector(types::vector_type type, const uint8_t* buf, size_t items);
+GR_RUNTIME_API types::vector_type type_from_pmt(pmt::pmt_t vector);
+
+} // namespace pdu
+} // namespace gr
+
+#endif /* INCLUDED_GR_PDU_H */
diff --git a/gnuradio-runtime/lib/CMakeLists.txt b/gnuradio-runtime/lib/CMakeLists.txt
index 4cddb26fe0..9a6cd4488f 100644
--- a/gnuradio-runtime/lib/CMakeLists.txt
+++ b/gnuradio-runtime/lib/CMakeLists.txt
@@ -72,6 +72,7 @@ add_library(gnuradio-runtime
msg_handler.cc
msg_queue.cc
pagesize.cc
+ pdu.cc
prefs.cc
realtime.cc
realtime_impl.cc
diff --git a/gnuradio-runtime/lib/pdu.cc b/gnuradio-runtime/lib/pdu.cc
new file mode 100644
index 0000000000..e01092de20
--- /dev/null
+++ b/gnuradio-runtime/lib/pdu.cc
@@ -0,0 +1,119 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013,2021 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/gr_complex.h>
+#include <gnuradio/pdu.h>
+#include <pmt/pmt.h>
+
+namespace gr {
+namespace msgport_names {
+
+const pmt::pmt_t bpdu()
+{
+ static const pmt::pmt_t val = pmt::mp("bpdu");
+ return val;
+}
+const pmt::pmt_t cpdu()
+{
+ static const pmt::pmt_t val = pmt::mp("cpdu");
+ return val;
+}
+const pmt::pmt_t dict()
+{
+ static const pmt::pmt_t val = pmt::mp("dict");
+ return val;
+}
+const pmt::pmt_t fpdu()
+{
+ static const pmt::pmt_t val = pmt::mp("fpdu");
+ return val;
+}
+const pmt::pmt_t msg()
+{
+ static const pmt::pmt_t val = pmt::mp("msg");
+ return val;
+}
+const pmt::pmt_t pdu()
+{
+ static const pmt::pmt_t val = pmt::mp("pdu");
+ return val;
+}
+const pmt::pmt_t pdus()
+{
+ static const pmt::pmt_t val = pmt::mp("pdus");
+ return val;
+}
+const pmt::pmt_t vec()
+{
+ static const pmt::pmt_t val = pmt::mp("vec");
+ return val;
+}
+
+} /* namespace ports */
+
+namespace pdu {
+
+size_t itemsize(types::vector_type type)
+{
+ switch (type) {
+ case types::byte_t:
+ return sizeof(char);
+ case types::float_t:
+ return sizeof(float);
+ case types::complex_t:
+ return sizeof(gr_complex);
+ default:
+ throw std::runtime_error("bad PDU type");
+ }
+}
+
+bool type_matches(types::vector_type type, pmt::pmt_t v)
+{
+ switch (type) {
+ case types::byte_t:
+ return pmt::is_u8vector(v);
+ case types::float_t:
+ return pmt::is_f32vector(v);
+ case types::complex_t:
+ return pmt::is_c32vector(v);
+ default:
+ throw std::runtime_error("bad PDU type");
+ }
+}
+
+pmt::pmt_t make_pdu_vector(types::vector_type type, const uint8_t* buf, size_t items)
+{
+ switch (type) {
+ case types::byte_t:
+ return pmt::init_u8vector(items, buf);
+ case types::float_t:
+ return pmt::init_f32vector(items, (const float*)buf);
+ case types::complex_t:
+ return pmt::init_c32vector(items, (const gr_complex*)buf);
+ default:
+ throw std::runtime_error("bad PDU type");
+ }
+}
+
+types::vector_type type_from_pmt(pmt::pmt_t vector)
+{
+ if (pmt::is_u8vector(vector))
+ return types::byte_t;
+ if (pmt::is_f32vector(vector))
+ return types::float_t;
+ if (pmt::is_c32vector(vector))
+ return types::complex_t;
+ throw std::runtime_error("bad PDU type");
+}
+
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gnuradio-runtime/python/gnuradio/__init__.py b/gnuradio-runtime/python/gnuradio/__init__.py
index 2326c3ab89..45bc91bf4d 100644
--- a/gnuradio-runtime/python/gnuradio/__init__.py
+++ b/gnuradio-runtime/python/gnuradio/__init__.py
@@ -57,4 +57,5 @@ if path.endswith(path_ending):
__path__.append(os.path.join(build_path, 'gr-utils'))
__path__.append(os.path.join(build_path, 'gr-uhd', 'python'))
__path__.append(os.path.join(build_path, 'gr-pdu', 'python'))
+ __path__.append(os.path.join(build_path, 'gr-network', 'python'))
__path__.append(os.path.join(build_path, 'gr-zeromq', 'python'))
diff --git a/gnuradio-runtime/python/gnuradio/gr/bindings/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/gr/bindings/CMakeLists.txt
index 17b1a30590..ef8f1f10dd 100644
--- a/gnuradio-runtime/python/gnuradio/gr/bindings/CMakeLists.txt
+++ b/gnuradio-runtime/python/gnuradio/gr/bindings/CMakeLists.txt
@@ -42,6 +42,7 @@ messages/msg_queue_python.cc
msg_handler_python.cc
msg_queue_python.cc
nco_python.cc
+ pdu_python.cc
prefs_python.cc
# pycallback_object_python.cc
random_python.cc
@@ -81,7 +82,7 @@ messages/msg_queue_python.cc
# xoroshiro128p_python.cc
python_bindings.cc)
-GR_PYBIND_MAKE_CHECK_HASH(gr
+GR_PYBIND_MAKE_CHECK_HASH(gr
../../../..
gr::gr
"${gr_python_files}")
diff --git a/gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h b/gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h
new file mode 100644
index 0000000000..8ba6b5ddd0
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_msgport_names_bpdu = R"doc()doc";
+
+
+static const char* __doc_gr_msgport_names_cpdu = R"doc()doc";
+
+
+static const char* __doc_gr_msgport_names_dict = R"doc()doc";
+
+
+static const char* __doc_gr_msgport_names_fpdu = R"doc()doc";
+
+
+static const char* __doc_gr_msgport_names_msg = R"doc()doc";
+
+
+static const char* __doc_gr_msgport_names_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_msgport_names_pdus = R"doc()doc";
+
+
+static const char* __doc_gr_msgport_names_vec = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_itemsize = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_type_matches = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_make_pdu_vector = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_type_from_pmt = R"doc()doc";
diff --git a/gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc b/gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc
new file mode 100644
index 0000000000..98df9acd8c
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(pdu.h) */
+/* BINDTOOL_HEADER_FILE_HASH(2b56328d8782d0a1816df04928cd83c5) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu.h>
+// pydoc.h is automatically generated in the build directory
+#include <pdu_pydoc.h>
+
+void bind_pdu(py::module& m)
+{
+
+ py::module m_types = m.def_submodule("types");
+
+ py::enum_<::gr::types::vector_type>(m_types, "vector_type")
+ .value("byte_t", ::gr::types::byte_t) // 0
+ .value("float_t", ::gr::types::float_t) // 1
+ .value("complex_t", ::gr::types::complex_t) // 2
+ .export_values();
+
+ py::implicitly_convertible<int, ::gr::types::vector_type>();
+
+
+ py::module m_msgport_names = m.def_submodule("msgport_names");
+
+ m_msgport_names.def("bpdu", &::gr::msgport_names::bpdu, D(msgport_names, bpdu));
+
+
+ m_msgport_names.def("cpdu", &::gr::msgport_names::cpdu, D(msgport_names, cpdu));
+
+
+ m_msgport_names.def("dict", &::gr::msgport_names::dict, D(msgport_names, dict));
+
+
+ m_msgport_names.def("fpdu", &::gr::msgport_names::fpdu, D(msgport_names, fpdu));
+
+
+ m_msgport_names.def("msg", &::gr::msgport_names::msg, D(msgport_names, msg));
+
+
+ m_msgport_names.def("pdu", &::gr::msgport_names::pdu, D(msgport_names, pdu));
+
+
+ m_msgport_names.def("pdus", &::gr::msgport_names::pdus, D(msgport_names, pdus));
+
+
+ m_msgport_names.def("vec", &::gr::msgport_names::vec, D(msgport_names, vec));
+
+
+ py::module m_pdu = m.def_submodule("pdu");
+
+ m_pdu.def("itemsize", &::gr::pdu::itemsize, py::arg("type"), D(pdu, itemsize));
+
+
+ m_pdu.def("type_matches",
+ &::gr::pdu::type_matches,
+ py::arg("type"),
+ py::arg("v"),
+ D(pdu, type_matches));
+
+
+ m_pdu.def("make_pdu_vector",
+ &::gr::pdu::make_pdu_vector,
+ py::arg("type"),
+ py::arg("buf"),
+ py::arg("items"),
+ D(pdu, make_pdu_vector));
+
+
+ m_pdu.def("type_from_pmt",
+ &::gr::pdu::type_from_pmt,
+ py::arg("vector"),
+ D(pdu, type_from_pmt));
+}
diff --git a/gnuradio-runtime/python/gnuradio/gr/bindings/python_bindings.cc b/gnuradio-runtime/python/gnuradio/gr/bindings/python_bindings.cc
index 8307fa8790..c180116c80 100644
--- a/gnuradio-runtime/python/gnuradio/gr/bindings/python_bindings.cc
+++ b/gnuradio-runtime/python/gnuradio/gr/bindings/python_bindings.cc
@@ -52,6 +52,7 @@ void bind_msg_queue(py::module&);
void bind_msg_handler(py::module&);
void bind_msg_queue(py::module&);
void bind_nco(py::module&);
+void bind_pdu(py::module&);
void bind_prefs(py::module&);
// void bind_pycallback_object(py::module&);
void bind_random(py::module&);
@@ -152,6 +153,7 @@ PYBIND11_MODULE(gr_python, m)
bind_nco(m);
+ bind_pdu(m);
bind_prefs(m);
// // bind_pycallback_object(m);
bind_random(m);
diff --git a/gr-network/grc/CMakeLists.txt b/gr-network/grc/CMakeLists.txt
index 8ac8bb68c8..622624e4e1 100644
--- a/gr-network/grc/CMakeLists.txt
+++ b/gr-network/grc/CMakeLists.txt
@@ -7,8 +7,10 @@
#
install(FILES
+ network_socket_pdu.block.yml
network_tcp_sink.block.yml
network_tcp_source.block.yml
+ network_tuntap_pdu.block.yml
network_udp_sink.block.yml
network_udp_source.block.yml
DESTINATION share/gnuradio/grc/blocks
diff --git a/gr-network/grc/network_socket_pdu.block.yml b/gr-network/grc/network_socket_pdu.block.yml
new file mode 100644
index 0000000000..0033c769ef
--- /dev/null
+++ b/gr-network/grc/network_socket_pdu.block.yml
@@ -0,0 +1,57 @@
+id: network_socket_pdu
+label: Socket PDU
+category: '[Core]/Networking Tools'
+flags: [ python, cpp ]
+
+parameters:
+- id: type
+ label: Type
+ dtype: enum
+ default: TCP_SERVER
+ options: ["TCP_SERVER", "TCP_CLIENT", "UDP_SERVER", "UDP_CLIENT"]
+ option_labels: [TCP Server, TCP Client, UDP Server, UDP Client]
+- id: host
+ label: Host
+ dtype: string
+- id: port
+ label: Port
+ dtype: string
+ default: '52001'
+- id: mtu
+ label: MTU
+ dtype: int
+ default: '10000'
+- id: tcp_no_delay
+ label: TCP No Delay
+ dtype: enum
+ default: 'False'
+ options: ['True', 'False']
+ option_labels: [Enabled, Disabled]
+ hide: ${ (( 'part' if (str(tcp_no_delay) == 'False') else 'none') if ((type == 'TCP_CLIENT') or (type == 'TCP_SERVER')) else 'all') }
+
+inputs:
+- domain: message
+ id: pdus
+ optional: true
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+templates:
+ imports: from gnuradio import network
+ make: network.socket_pdu(${repr(type)}, ${host}, ${port}, ${mtu}, ${tcp_no_delay})
+
+cpp_templates:
+ includes: ['#include <gnuradio/network/socket_pdu.h>']
+ declarations: 'network::socket_pdu::sptr ${id};'
+ make: 'this->${id} = network::socket_pdu::make("${type}", ${host}, ${port}, ${mtu}, ${tcp_no_delay});'
+ translations:
+ 'True': 'true'
+ 'False': 'false'
+
+documentation: |-
+ For server modes, leave Host blank to bind to all interfaces (equivalent to 0.0.0.0).
+
+file_format: 1
diff --git a/gr-network/grc/network_tuntap_pdu.block.yml b/gr-network/grc/network_tuntap_pdu.block.yml
new file mode 100644
index 0000000000..1542b89a98
--- /dev/null
+++ b/gr-network/grc/network_tuntap_pdu.block.yml
@@ -0,0 +1,44 @@
+id: network_tuntap_pdu
+label: TUNTAP PDU
+category: '[Core]/Networking Tools'
+flags: [ python, cpp ]
+
+parameters:
+- id: ifn
+ label: Interface Name
+ dtype: string
+ default: tap0
+- id: mtu
+ label: MTU
+ dtype: int
+ default: '10000'
+- id: istunflag
+ label: Flag
+ dtype: enum
+ default: 'False'
+ options: ['True', 'False']
+ option_labels: [TUN(IP Packet), TAP(Ethernet Frame)]
+
+inputs:
+- domain: message
+ id: pdus
+ optional: true
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+templates:
+ imports: from gnuradio import network
+ make: network.tuntap_pdu(${ifn}, ${mtu}, ${istunflag})
+
+cpp_templates:
+ includes: ['#include <gnuradio/network/tuntap_pdu.h>']
+ declarations: 'network::tuntap_pdu::sptr ${id};'
+ make: 'this->${id} = network::tuntap_pdu::make(${ifn}, ${mtu}, ${istunflag});'
+ translations:
+ 'True': 'true'
+ 'False': 'false'
+
+file_format: 1
diff --git a/gr-network/include/gnuradio/network/CMakeLists.txt b/gr-network/include/gnuradio/network/CMakeLists.txt
index 8712ed00d2..36ff1b48a7 100644
--- a/gr-network/include/gnuradio/network/CMakeLists.txt
+++ b/gr-network/include/gnuradio/network/CMakeLists.txt
@@ -11,7 +11,9 @@
install(FILES
api.h
packet_headers.h
+ socket_pdu.h
tcp_sink.h
+ tuntap_pdu.h
udp_header_types.h
udp_sink.h
udp_source.h
diff --git a/gr-network/include/gnuradio/network/socket_pdu.h b/gr-network/include/gnuradio/network/socket_pdu.h
new file mode 100644
index 0000000000..dba2522fab
--- /dev/null
+++ b/gr-network/include/gnuradio/network/socket_pdu.h
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_NETWORK_SOCKET_PDU_H
+#define INCLUDED_NETWORK_SOCKET_PDU_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/network/api.h>
+
+namespace gr {
+namespace network {
+
+/*!
+ * \brief Creates socket interface and translates traffic to PDUs
+ * \ingroup networking_tools_blk
+ */
+class NETWORK_API socket_pdu : virtual public block
+{
+public:
+ // gr::network::socket_pdu::sptr
+ typedef std::shared_ptr<socket_pdu> sptr;
+
+ /*!
+ * \brief Construct a SOCKET PDU interface
+ * \param type "TCP_SERVER", "TCP_CLIENT", "UDP_SERVER", or "UDP_CLIENT"
+ * \param addr network address to use
+ * \param port network port to use
+ * \param MTU maximum transmission unit
+ * \param tcp_no_delay TCP No Delay option (set to True to disable Nagle algorithm)
+ */
+ static sptr make(std::string type,
+ std::string addr,
+ std::string port,
+ int MTU = 10000,
+ bool tcp_no_delay = false);
+};
+
+} /* namespace network */
+} /* namespace gr */
+
+#endif /* INCLUDED_NETWORK_SOCKET_PDU_H */
diff --git a/gr-network/include/gnuradio/network/tuntap_pdu.h b/gr-network/include/gnuradio/network/tuntap_pdu.h
new file mode 100644
index 0000000000..6ef34aeee2
--- /dev/null
+++ b/gr-network/include/gnuradio/network/tuntap_pdu.h
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_NETWORK_TUNTAP_PDU_H
+#define INCLUDED_NETWORK_TUNTAP_PDU_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/network/api.h>
+
+namespace gr {
+namespace network {
+
+/*!
+ * \brief Creates TUNTAP interface and translates traffic to PDUs
+ * \ingroup networking_tools_blk
+ */
+class NETWORK_API tuntap_pdu : virtual public block
+{
+public:
+ // gr::network::tuntap_pdu::sptr
+ typedef std::shared_ptr<tuntap_pdu> sptr;
+
+ /*!
+ * \brief Construct a TUNTAP PDU interface
+ * \param dev Device name to create
+ * \param MTU Maximum Transmission Unit size
+ * \param istunflag Flag to indicate TUN or Tap
+ */
+ static sptr make(std::string dev, int MTU = 10000, bool istunflag = false);
+};
+
+} /* namespace network */
+} /* namespace gr */
+
+#endif /* INCLUDED_NETWORK_TUNTAP_PDU_H */
diff --git a/gr-network/lib/CMakeLists.txt b/gr-network/lib/CMakeLists.txt
index 52a267079a..0eecda139f 100644
--- a/gr-network/lib/CMakeLists.txt
+++ b/gr-network/lib/CMakeLists.txt
@@ -13,7 +13,11 @@ include(GrPlatform)
#define LIB_SUFFIX
list(APPEND network_sources
+ socket_pdu_impl.cc
+ stream_pdu_base.cc
+ tcp_connection.cc
tcp_sink_impl.cc
+ tuntap_pdu_impl.cc
udp_sink_impl.cc
udp_source_impl.cc
)
diff --git a/gr-network/lib/socket_pdu_impl.cc b/gr-network/lib/socket_pdu_impl.cc
new file mode 100644
index 0000000000..a9e854447a
--- /dev/null
+++ b/gr-network/lib/socket_pdu_impl.cc
@@ -0,0 +1,271 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013,2019 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "socket_pdu_impl.h"
+#include "tcp_connection.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace network {
+
+socket_pdu::sptr socket_pdu::make(std::string type,
+ std::string addr,
+ std::string port,
+ int MTU /*= 10000*/,
+ bool tcp_no_delay /*= false*/)
+{
+ return gnuradio::make_block_sptr<socket_pdu_impl>(
+ type, addr, port, MTU, tcp_no_delay);
+}
+
+socket_pdu_impl::socket_pdu_impl(std::string type,
+ std::string addr,
+ std::string port,
+ int MTU /*= 10000*/,
+ bool tcp_no_delay /*= false*/)
+ : block("socket_pdu", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_tcp_no_delay(tcp_no_delay)
+{
+ d_rxbuf.resize(MTU);
+
+ message_port_register_in(msgport_names::pdus());
+ message_port_register_out(msgport_names::pdus());
+
+ if ((type == "TCP_SERVER") &&
+ ((addr.empty()) || (addr == "0.0.0.0"))) { // Bind on all interfaces
+ int port_num = atoi(port.c_str());
+ if (port_num == 0)
+ throw std::invalid_argument(
+ "gr::pdu:socket_pdu: invalid port for TCP_SERVER");
+ d_tcp_endpoint =
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port_num);
+ } else if ((type == "TCP_SERVER") || (type == "TCP_CLIENT")) {
+ boost::asio::ip::tcp::resolver resolver(d_io_service);
+ boost::asio::ip::tcp::resolver::query query(
+ boost::asio::ip::tcp::v4(),
+ addr,
+ port,
+ boost::asio::ip::resolver_query_base::passive);
+ d_tcp_endpoint = *resolver.resolve(query);
+ } else if ((type == "UDP_SERVER") &&
+ ((addr.empty()) || (addr == "0.0.0.0"))) { // Bind on all interfaces
+ int port_num = atoi(port.c_str());
+ if (port_num == 0)
+ throw std::invalid_argument(
+ "gr::pdu:socket_pdu: invalid port for UDP_SERVER");
+ d_udp_endpoint =
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port_num);
+ } else if ((type == "UDP_SERVER") || (type == "UDP_CLIENT")) {
+ boost::asio::ip::udp::resolver resolver(d_io_service);
+ boost::asio::ip::udp::resolver::query query(
+ boost::asio::ip::udp::v4(),
+ addr,
+ port,
+ boost::asio::ip::resolver_query_base::passive);
+
+ if (type == "UDP_SERVER")
+ d_udp_endpoint = *resolver.resolve(query);
+ else
+ d_udp_endpoint_other = *resolver.resolve(query);
+ }
+
+ if (type == "TCP_SERVER") {
+ d_acceptor_tcp = std::make_shared<boost::asio::ip::tcp::acceptor>(d_io_service,
+ d_tcp_endpoint);
+ d_acceptor_tcp->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+
+ start_tcp_accept();
+
+ set_msg_handler(msgport_names::pdus(),
+ [this](pmt::pmt_t msg) { this->tcp_server_send(msg); });
+ } else if (type == "TCP_CLIENT") {
+ boost::system::error_code error = boost::asio::error::host_not_found;
+ d_tcp_socket = std::make_shared<boost::asio::ip::tcp::socket>(d_io_service);
+ d_tcp_socket->connect(d_tcp_endpoint, error);
+ if (error)
+ throw boost::system::system_error(error);
+ d_tcp_socket->set_option(boost::asio::ip::tcp::no_delay(d_tcp_no_delay));
+
+ set_msg_handler(msgport_names::pdus(),
+ [this](pmt::pmt_t msg) { this->tcp_client_send(msg); });
+
+ d_tcp_socket->async_read_some(
+ boost::asio::buffer(d_rxbuf),
+ boost::bind(&socket_pdu_impl::handle_tcp_read,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ } else if (type == "UDP_SERVER") {
+ d_udp_socket =
+ std::make_shared<boost::asio::ip::udp::socket>(d_io_service, d_udp_endpoint);
+ d_udp_socket->async_receive_from(
+ boost::asio::buffer(d_rxbuf),
+ d_udp_endpoint_other,
+ boost::bind(&socket_pdu_impl::handle_udp_read,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+
+ set_msg_handler(msgport_names::pdus(),
+ [this](pmt::pmt_t msg) { this->udp_send(msg); });
+ } else if (type == "UDP_CLIENT") {
+ d_udp_socket =
+ std::make_shared<boost::asio::ip::udp::socket>(d_io_service, d_udp_endpoint);
+ d_udp_socket->async_receive_from(
+ boost::asio::buffer(d_rxbuf),
+ d_udp_endpoint_other,
+ boost::bind(&socket_pdu_impl::handle_udp_read,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+
+ set_msg_handler(msgport_names::pdus(),
+ [this](pmt::pmt_t msg) { this->udp_send(msg); });
+ } else
+ throw std::runtime_error("gr::pdu:socket_pdu: unknown socket type");
+
+ d_thread = gr::thread::thread(boost::bind(&socket_pdu_impl::run_io_service, this));
+ d_started = true;
+}
+
+socket_pdu_impl::~socket_pdu_impl() { stop(); }
+
+bool socket_pdu_impl::stop()
+{
+ if (d_started) {
+ d_io_service.stop();
+ d_thread.interrupt();
+ d_thread.join();
+ }
+ d_started = false;
+ return true;
+}
+
+void socket_pdu_impl::handle_tcp_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+{
+ if (!error) {
+ pmt::pmt_t vector =
+ pmt::init_u8vector(bytes_transferred, (const uint8_t*)&d_rxbuf[0]);
+ pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector);
+ message_port_pub(msgport_names::pdus(), pdu);
+
+ d_tcp_socket->async_read_some(
+ boost::asio::buffer(d_rxbuf),
+ boost::bind(&socket_pdu_impl::handle_tcp_read,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ } else
+ throw boost::system::system_error(error);
+}
+
+void socket_pdu_impl::start_tcp_accept()
+{
+#if (BOOST_VERSION >= 107000)
+ tcp_connection::sptr new_connection =
+ tcp_connection::make(d_io_service, d_rxbuf.size(), d_tcp_no_delay);
+#else
+ tcp_connection::sptr new_connection = tcp_connection::make(
+ d_acceptor_tcp->get_io_service(), d_rxbuf.size(), d_tcp_no_delay);
+#endif
+
+ d_acceptor_tcp->async_accept(new_connection->socket(),
+ boost::bind(&socket_pdu_impl::handle_tcp_accept,
+ this,
+ new_connection,
+ boost::asio::placeholders::error));
+}
+
+void socket_pdu_impl::tcp_server_send(pmt::pmt_t msg)
+{
+ pmt::pmt_t vector = pmt::cdr(msg);
+ for (size_t i = 0; i < d_tcp_connections.size(); i++)
+ d_tcp_connections[i]->send(vector);
+}
+
+void socket_pdu_impl::handle_tcp_accept(tcp_connection::sptr new_connection,
+ const boost::system::error_code& error)
+{
+ if (!error) {
+ // Garbage collect closed sockets
+ std::vector<tcp_connection::sptr>::iterator it = d_tcp_connections.begin();
+ while (it != d_tcp_connections.end()) {
+ if (!(**it).socket().is_open())
+ it = d_tcp_connections.erase(it);
+ else
+ ++it;
+ }
+
+ new_connection->start(this);
+ d_tcp_connections.push_back(new_connection);
+ start_tcp_accept();
+ } else
+ std::cout << error << std::endl;
+}
+
+void socket_pdu_impl::tcp_client_send(pmt::pmt_t msg)
+{
+ pmt::pmt_t vector = pmt::cdr(msg);
+ size_t len = pmt::blob_length(vector);
+ size_t offset = 0;
+ std::vector<char> txbuf(std::min(len, d_rxbuf.size()));
+ while (offset < len) {
+ size_t send_len = std::min((len - offset), txbuf.size());
+ memcpy(&txbuf[0], pmt::uniform_vector_elements(vector, offset), send_len);
+ offset += send_len;
+ d_tcp_socket->send(boost::asio::buffer(txbuf, send_len));
+ }
+}
+
+void socket_pdu_impl::udp_send(pmt::pmt_t msg)
+{
+ if (d_udp_endpoint_other.address().to_string() == "0.0.0.0")
+ return;
+
+ pmt::pmt_t vector = pmt::cdr(msg);
+ size_t len = pmt::blob_length(vector);
+ size_t offset = 0;
+ std::vector<char> txbuf(std::min(len, d_rxbuf.size()));
+ while (offset < len) {
+ size_t send_len = std::min((len - offset), txbuf.size());
+ memcpy(&txbuf[0], pmt::uniform_vector_elements(vector, offset), send_len);
+ offset += send_len;
+ d_udp_socket->send_to(boost::asio::buffer(txbuf, send_len), d_udp_endpoint_other);
+ }
+}
+
+void socket_pdu_impl::handle_udp_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+{
+ if (!error) {
+ pmt::pmt_t vector =
+ pmt::init_u8vector(bytes_transferred, (const uint8_t*)&d_rxbuf[0]);
+ pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector);
+
+ message_port_pub(msgport_names::pdus(), pdu);
+
+ d_udp_socket->async_receive_from(
+ boost::asio::buffer(d_rxbuf),
+ d_udp_endpoint_other,
+ boost::bind(&socket_pdu_impl::handle_udp_read,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+}
+
+} /* namespace network */
+} /* namespace gr */
diff --git a/gr-network/lib/socket_pdu_impl.h b/gr-network/lib/socket_pdu_impl.h
new file mode 100644
index 0000000000..9175290a4e
--- /dev/null
+++ b/gr-network/lib/socket_pdu_impl.h
@@ -0,0 +1,68 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_NETWORK_SOCKET_PDU_IMPL_H
+#define INCLUDED_NETWORK_SOCKET_PDU_IMPL_H
+
+#include "tcp_connection.h"
+#include <gnuradio/network/socket_pdu.h>
+
+namespace gr {
+namespace network {
+
+class socket_pdu_impl : public socket_pdu
+{
+private:
+ boost::asio::io_service d_io_service;
+ std::vector<char> d_rxbuf;
+ void run_io_service() { d_io_service.run(); }
+ gr::thread::thread d_thread;
+ bool d_started;
+
+ // TCP specific
+ boost::asio::ip::tcp::endpoint d_tcp_endpoint;
+ std::vector<tcp_connection::sptr> d_tcp_connections;
+ void handle_tcp_read(const boost::system::error_code& error,
+ size_t bytes_transferred);
+ const bool d_tcp_no_delay;
+
+ // TCP server specific
+ std::shared_ptr<boost::asio::ip::tcp::acceptor> d_acceptor_tcp;
+ void start_tcp_accept();
+ void tcp_server_send(pmt::pmt_t msg);
+ void handle_tcp_accept(tcp_connection::sptr new_connection,
+ const boost::system::error_code& error);
+
+ // TCP client specific
+ std::shared_ptr<boost::asio::ip::tcp::socket> d_tcp_socket;
+ void tcp_client_send(pmt::pmt_t msg);
+
+ // UDP specific
+ boost::asio::ip::udp::endpoint d_udp_endpoint;
+ boost::asio::ip::udp::endpoint d_udp_endpoint_other;
+ std::shared_ptr<boost::asio::ip::udp::socket> d_udp_socket;
+ void handle_udp_read(const boost::system::error_code& error,
+ size_t bytes_transferred);
+ void udp_send(pmt::pmt_t msg);
+
+public:
+ socket_pdu_impl(std::string type,
+ std::string addr,
+ std::string port,
+ int MTU = 10000,
+ bool tcp_no_delay = false);
+ ~socket_pdu_impl() override;
+ bool stop() override;
+};
+
+} /* namespace network */
+} /* namespace gr */
+
+#endif /* INCLUDED_NETWORK_SOCKET_PDU_IMPL_H */
diff --git a/gr-network/lib/stream_pdu_base.cc b/gr-network/lib/stream_pdu_base.cc
new file mode 100644
index 0000000000..a6519cedab
--- /dev/null
+++ b/gr-network/lib/stream_pdu_base.cc
@@ -0,0 +1,110 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#include <winsock2.h>
+#endif
+
+#include "stream_pdu_base.h"
+#include <gnuradio/basic_block.h>
+#include <gnuradio/logger.h>
+#include <gnuradio/pdu.h>
+#include <boost/format.hpp>
+
+static const long timeout_us = 100 * 1000; // 100ms
+
+namespace gr {
+namespace network {
+
+stream_pdu_base::stream_pdu_base(int MTU) : d_fd(-1), d_started(false), d_finished(false)
+{
+ gr::configure_default_loggers(d_pdu_logger, d_pdu_debug_logger, "stream_pdu_base");
+ // reserve space for rx buffer
+ d_rxbuf.resize(MTU, 0);
+}
+
+stream_pdu_base::~stream_pdu_base() { stop_rxthread(); }
+
+void stream_pdu_base::start_rxthread(basic_block* blk, pmt::pmt_t port)
+{
+ d_blk = blk;
+ d_port = port;
+ d_thread = gr::thread::thread(std::bind(&stream_pdu_base::run, this));
+ d_started = true;
+}
+
+void stream_pdu_base::stop_rxthread()
+{
+ d_finished = true;
+
+ if (d_started) {
+ d_thread.interrupt();
+ d_thread.join();
+ }
+}
+
+void stream_pdu_base::run()
+{
+ while (!d_finished) {
+ if (!wait_ready())
+ continue;
+
+ const int result = read(d_fd, &d_rxbuf[0], d_rxbuf.size());
+ if (result <= 0)
+ throw std::runtime_error("stream_pdu_base, bad socket read!");
+
+ pmt::pmt_t vector = pmt::init_u8vector(result, &d_rxbuf[0]);
+ pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector);
+
+ d_blk->message_port_pub(d_port, pdu);
+ }
+}
+
+bool stream_pdu_base::wait_ready()
+{
+ // setup timeval for timeout
+ timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout_us;
+
+ // setup rset for timeout
+ fd_set rset;
+ FD_ZERO(&rset);
+ FD_SET(d_fd, &rset);
+
+ // call select with timeout on receive socket
+ return ::select(d_fd + 1, &rset, NULL, NULL, &tv) > 0;
+}
+
+void stream_pdu_base::send(pmt::pmt_t msg)
+{
+ pmt::pmt_t vector = pmt::cdr(msg);
+ size_t offset(0);
+ size_t itemsize(pdu::itemsize(pdu::type_from_pmt(vector)));
+ int len(pmt::length(vector) * itemsize);
+
+ const int rv = write(d_fd, pmt::uniform_vector_elements(vector, offset), len);
+ if (rv != len) {
+ static auto msg = boost::format(
+ "stream_pdu_base::send(pdu) write failed! (d_fd=%d, len=%d, rv=%d)");
+ GR_LOG_WARN(d_pdu_logger, msg % d_fd % len % rv);
+ }
+}
+
+} /* namespace network */
+} /* namespace gr */
diff --git a/gr-network/lib/stream_pdu_base.h b/gr-network/lib/stream_pdu_base.h
new file mode 100644
index 0000000000..40940de7de
--- /dev/null
+++ b/gr-network/lib/stream_pdu_base.h
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_STREAM_PDU_BASE_H
+#define INCLUDED_STREAM_PDU_BASE_H
+
+#include <gnuradio/basic_block.h>
+#include <gnuradio/logger.h>
+#include <gnuradio/thread/thread.h>
+#include <pmt/pmt.h>
+
+class basic_block;
+
+namespace gr {
+namespace network {
+
+class stream_pdu_base
+{
+public:
+ stream_pdu_base(int MTU = 10000);
+ ~stream_pdu_base();
+
+protected:
+ int d_fd;
+ bool d_started;
+ bool d_finished;
+ std::vector<uint8_t> d_rxbuf;
+ gr::thread::thread d_thread;
+
+ pmt::pmt_t d_port;
+ basic_block* d_blk;
+
+ void run();
+ void send(pmt::pmt_t msg);
+ bool wait_ready();
+ void start_rxthread(basic_block* blk, pmt::pmt_t rxport);
+ void stop_rxthread();
+
+ gr::logger_ptr d_pdu_logger, d_pdu_debug_logger;
+};
+
+} /* namespace network */
+} /* namespace gr */
+
+#endif /* INCLUDED_STREAM_PDU_BASE_H */
diff --git a/gr-network/lib/tcp_connection.cc b/gr-network/lib/tcp_connection.cc
new file mode 100644
index 0000000000..dfb511e053
--- /dev/null
+++ b/gr-network/lib/tcp_connection.cc
@@ -0,0 +1,101 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tcp_connection.h"
+#include <gnuradio/basic_block.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace network {
+
+tcp_connection::sptr tcp_connection::make(boost::asio::io_service& io_service,
+ int MTU /*= 10000*/,
+ bool no_delay /*=false*/)
+{
+ return sptr(new tcp_connection(io_service, MTU, no_delay));
+}
+
+tcp_connection::tcp_connection(boost::asio::io_service& io_service,
+ int MTU /*= 10000*/,
+ bool no_delay /*=false*/)
+ : d_socket(io_service), d_buf(MTU), d_block(NULL), d_no_delay(no_delay)
+{
+ try {
+ d_socket.set_option(boost::asio::ip::tcp::no_delay(no_delay));
+ } catch (...) {
+ // Silently ignore failure (socket might be current in accept stage) and try again
+ // in 'start'
+ }
+}
+
+void tcp_connection::send(pmt::pmt_t vector)
+{
+ size_t len = pmt::blob_length(vector);
+
+ // Asio async_write() requires the buffer to remain valid until the handler is called.
+ auto txbuf = std::make_shared<std::vector<char>>(len);
+
+ size_t temp = 0;
+ memcpy(txbuf->data(), pmt::uniform_vector_elements(vector, temp), len);
+
+ size_t offset = 0;
+ while (offset < len) {
+ // Limit the size of each write() to the MTU.
+ // FIXME: Note that this has the effect of breaking a large PDU into several
+ // smaller PDUs, each containing <= MTU bytes. Is this the desired behavior?
+ size_t send_len = std::min((len - offset), d_buf.size());
+ boost::asio::async_write(
+ d_socket,
+ boost::asio::buffer(txbuf->data() + offset, send_len),
+ [txbuf](const boost::system::error_code& error, size_t bytes_transferred) {});
+ offset += send_len;
+ }
+}
+
+void tcp_connection::start(gr::basic_block* block)
+{
+ d_block = block;
+ d_socket.set_option(boost::asio::ip::tcp::no_delay(d_no_delay));
+ d_socket.async_read_some(boost::asio::buffer(d_buf),
+ boost::bind(&tcp_connection::handle_read,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+}
+
+void tcp_connection::handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+{
+ if (!error) {
+ if (d_block) {
+ pmt::pmt_t vector =
+ pmt::init_u8vector(bytes_transferred, (const uint8_t*)&d_buf[0]);
+ pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector);
+
+ d_block->message_port_pub(msgport_names::pdus(), pdu);
+ }
+
+ d_socket.async_read_some(
+ boost::asio::buffer(d_buf),
+ boost::bind(&tcp_connection::handle_read,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ } else {
+ d_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
+ d_socket.close();
+ }
+}
+} /* namespace network */
+} /* namespace gr */
diff --git a/gr-network/lib/tcp_connection.h b/gr-network/lib/tcp_connection.h
new file mode 100644
index 0000000000..29a2bd79fb
--- /dev/null
+++ b/gr-network/lib/tcp_connection.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_TCP_CONNECTION_H
+#define INCLUDED_TCP_CONNECTION_H
+
+#include <pmt/pmt.h>
+#include <boost/array.hpp>
+#include <boost/asio.hpp>
+#include <memory>
+
+namespace gr {
+
+class basic_block;
+
+namespace network {
+
+class tcp_connection
+{
+private:
+ boost::asio::ip::tcp::socket d_socket;
+ std::vector<char> d_buf;
+ basic_block* d_block;
+ bool d_no_delay;
+
+ tcp_connection(boost::asio::io_service& io_service,
+ int MTU = 10000,
+ bool no_delay = false);
+
+ void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
+
+public:
+ typedef std::shared_ptr<tcp_connection> sptr;
+
+ static sptr
+ make(boost::asio::io_service& io_service, int MTU = 10000, bool no_delay = false);
+
+ boost::asio::ip::tcp::socket& socket() { return d_socket; };
+
+ void start(gr::basic_block* block);
+ void send(pmt::pmt_t vector);
+};
+
+} /* namespace network */
+} /* namespace gr */
+
+#endif /* INCLUDED_TCP_CONNECTION_H */
diff --git a/gr-network/lib/tuntap_pdu_impl.cc b/gr-network/lib/tuntap_pdu_impl.cc
new file mode 100644
index 0000000000..87c3750fd9
--- /dev/null
+++ b/gr-network/lib/tuntap_pdu_impl.cc
@@ -0,0 +1,172 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tuntap_pdu_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+#include <boost/format.hpp>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+#include <arpa/inet.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#endif
+
+namespace gr {
+namespace network {
+
+tuntap_pdu::sptr tuntap_pdu::make(std::string dev, int MTU, bool istunflag)
+{
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+ return gnuradio::make_block_sptr<tuntap_pdu_impl>(dev, MTU, istunflag);
+#else
+ throw std::runtime_error("tuntap_pdu not implemented on this platform");
+#endif
+}
+
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+tuntap_pdu_impl::tuntap_pdu_impl(std::string dev, int MTU, bool istunflag)
+ : block("tuntap_pdu", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ stream_pdu_base(istunflag ? MTU : MTU + 14),
+ d_dev(dev),
+ d_istunflag(istunflag)
+{
+ // make the tuntap
+ char dev_cstr[IFNAMSIZ];
+ memset(dev_cstr, 0x00, IFNAMSIZ);
+ strncpy(dev_cstr, dev.c_str(), IFNAMSIZ);
+ dev_cstr[IFNAMSIZ - 1] = '\0';
+
+
+ bool istun = d_istunflag;
+ if (istun) {
+ d_fd = tun_alloc(dev_cstr, (IFF_TUN | IFF_NO_PI));
+ } else {
+ d_fd = tun_alloc(dev_cstr, (IFF_TAP | IFF_NO_PI));
+ }
+
+ if (d_fd <= 0)
+ throw std::runtime_error(
+ "gr::tuntap_pdu::make: tun_alloc failed (are you running as root?)");
+
+ int err = set_mtu(dev_cstr, MTU);
+ if (err < 0) {
+ std::ostringstream msg;
+ msg << boost::format("failed to set MTU to %d. You should use ifconfig to set "
+ "the MTU. E.g., `$ sudo ifconfig %s mtu %d`") %
+ MTU % dev % MTU;
+ GR_LOG_ERROR(d_logger, msg.str());
+ }
+
+
+ std::cout << boost::format("Allocated virtual ethernet interface: %s\n"
+ "You must now use ifconfig to set its IP address. E.g.,\n"
+ " $ sudo ifconfig %s 192.168.200.1\n"
+ "Be sure to use a different address in the same subnet "
+ "for each machine.\n") %
+ dev % dev
+ << std::endl;
+
+ // set up output message port
+ message_port_register_out(msgport_names::pdus());
+ start_rxthread(this, msgport_names::pdus());
+
+ // set up input message port
+ message_port_register_in(msgport_names::pdus());
+ set_msg_handler(msgport_names::pdus(), [this](pmt::pmt_t msg) { this->send(msg); });
+}
+
+int tuntap_pdu_impl::tun_alloc(char* dev, int flags)
+{
+ struct ifreq ifr;
+ int fd, err;
+ const char* clonedev = "/dev/net/tun";
+
+ /* Arguments taken by the function:
+ *
+ * char *dev: the name of an interface (or '\0'). MUST have enough
+ * space to hold the interface name if '\0' is passed
+ * int flags: interface flags (eg, IFF_TUN etc.)
+ */
+
+ /* open the clone device */
+ if ((fd = open(clonedev, O_RDWR)) < 0)
+ return fd;
+
+ /* preparation of the struct ifr, of type "struct ifreq" */
+ memset(&ifr, 0, sizeof(ifr));
+
+ ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */
+
+ /* if a device name was specified, put it in the structure; otherwise,
+ * the kernel will try to allocate the "next" device of the
+ * specified type
+ */
+ if (*dev)
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ - 1);
+
+ /* try to create the device */
+ if ((err = ioctl(fd, TUNSETIFF, (void*)&ifr)) < 0) {
+ close(fd);
+ return err;
+ }
+
+ /* if the operation was successful, write back the name of the
+ * interface to the variable "dev", so the caller can know
+ * it. Note that the caller MUST reserve space in *dev (see calling
+ * code below)
+ */
+ strcpy(dev, ifr.ifr_name);
+
+ /* this is the special file descriptor that the caller will use to talk
+ * with the virtual interface
+ */
+ return fd;
+}
+
+int tuntap_pdu_impl::set_mtu(const char* dev, int MTU)
+{
+ struct ifreq ifr;
+ int sfd, err;
+
+ /* MTU must be set by passing a socket fd to ioctl;
+ * create an arbitrary socket for this purpose
+ */
+ if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return sfd;
+
+ /* preparation of the struct ifr, of type "struct ifreq" */
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+ ifr.ifr_name[IFNAMSIZ - 1] = '\0';
+ ifr.ifr_addr.sa_family = AF_INET; /* address family */
+ ifr.ifr_mtu = MTU;
+
+ /* try to set MTU */
+ if ((err = ioctl(sfd, SIOCSIFMTU, (void*)&ifr)) < 0) {
+ close(sfd);
+ return err;
+ }
+
+ close(sfd);
+ return MTU;
+}
+#endif
+
+} /* namespace network */
+} /* namespace gr */
diff --git a/gr-network/lib/tuntap_pdu_impl.h b/gr-network/lib/tuntap_pdu_impl.h
new file mode 100644
index 0000000000..6811712fe8
--- /dev/null
+++ b/gr-network/lib/tuntap_pdu_impl.h
@@ -0,0 +1,41 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_NETWORK_TUNTAP_PDU_IMPL_H
+#define INCLUDED_NETWORK_TUNTAP_PDU_IMPL_H
+
+#include "stream_pdu_base.h"
+#include <gnuradio/network/tuntap_pdu.h>
+
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+#include <linux/if_tun.h>
+#endif
+
+namespace gr {
+namespace network {
+
+class tuntap_pdu_impl : public tuntap_pdu, public stream_pdu_base
+{
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+private:
+ const std::string d_dev;
+ const bool d_istunflag;
+ int tun_alloc(char* dev, int flags);
+ int set_mtu(const char* dev, int MTU);
+
+public:
+ tuntap_pdu_impl(std::string dev, int MTU, bool istunflag);
+#endif
+};
+
+} /* namespace network */
+} /* namespace gr */
+
+#endif /* INCLUDED_NETWORK_TUNTAP_PDU_IMPL_H */
diff --git a/gr-network/python/network/CMakeLists.txt b/gr-network/python/network/CMakeLists.txt
index a524e6390f..c6feaffc22 100644
--- a/gr-network/python/network/CMakeLists.txt
+++ b/gr-network/python/network/CMakeLists.txt
@@ -27,8 +27,18 @@ GR_PYTHON_INSTALL(
########################################################################
# Handle the unit tests
########################################################################
-include(GrTest)
-
-set(GR_TEST_TARGET_DEPS gnuradio-network)
+if(ENABLE_TESTING)
+ set(GR_TEST_TARGET_DEPS "")
+ set(GR_TEST_LIBRARY_DIRS "")
+ set(GR_TEST_PYTHON_DIRS
+ ${CMAKE_BINARY_DIR}/gnuradio-runtime/python
+ )
+ include(GrTest)
+ file(GLOB py_qa_test_files "qa_*.py")
+ foreach(py_qa_test_file ${py_qa_test_files})
+ get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file})
+ endforeach(py_qa_test_file)
+endif(ENABLE_TESTING)
add_subdirectory(bindings)
diff --git a/gr-network/python/network/bindings/CMakeLists.txt b/gr-network/python/network/bindings/CMakeLists.txt
index 80f02c00b2..d87f644fd8 100644
--- a/gr-network/python/network/bindings/CMakeLists.txt
+++ b/gr-network/python/network/bindings/CMakeLists.txt
@@ -6,14 +6,16 @@ include(GrPybind)
list(APPEND network_python_files
# packet_headers_python.cc
+ socket_pdu_python.cc
tcp_sink_python.cc
+ tuntap_pdu_python.cc
# udp_header_types_python.cc
udp_sink_python.cc
udp_source_python.cc
python_bindings.cc)
-GR_PYBIND_MAKE_CHECK_HASH(network
- ../../..
+GR_PYBIND_MAKE_CHECK_HASH(network
+ ../../..
gr::network
"${network_python_files}")
diff --git a/gr-network/python/network/bindings/docstrings/socket_pdu_pydoc_template.h b/gr-network/python/network/bindings/docstrings/socket_pdu_pydoc_template.h
new file mode 100644
index 0000000000..f7b9cb72bf
--- /dev/null
+++ b/gr-network/python/network/bindings/docstrings/socket_pdu_pydoc_template.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, network, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_network_socket_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_network_socket_pdu_socket_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_network_socket_pdu_make = R"doc()doc";
diff --git a/gr-network/python/network/bindings/docstrings/tuntap_pdu_pydoc_template.h b/gr-network/python/network/bindings/docstrings/tuntap_pdu_pydoc_template.h
new file mode 100644
index 0000000000..ec5bf4be2e
--- /dev/null
+++ b/gr-network/python/network/bindings/docstrings/tuntap_pdu_pydoc_template.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, network, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_network_tuntap_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_network_tuntap_pdu_tuntap_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_network_tuntap_pdu_make = R"doc()doc";
diff --git a/gr-network/python/network/bindings/python_bindings.cc b/gr-network/python/network/bindings/python_bindings.cc
index 3de111aa79..cacd4a1bf7 100644
--- a/gr-network/python/network/bindings/python_bindings.cc
+++ b/gr-network/python/network/bindings/python_bindings.cc
@@ -16,7 +16,9 @@
namespace py = pybind11;
// void bind_packet_headers(py::module&);
+void bind_socket_pdu(py::module&);
void bind_tcp_sink(py::module&);
+void bind_tuntap_pdu(py::module&);
// void bind_udp_header_types(py::module&);
void bind_udp_sink(py::module&);
void bind_udp_source(py::module&);
@@ -41,7 +43,9 @@ PYBIND11_MODULE(network_python, m)
py::module::import("gnuradio.gr");
// bind_packet_headers(m);
+ bind_socket_pdu(m);
bind_tcp_sink(m);
+ bind_tuntap_pdu(m);
// bind_udp_header_types(m);
bind_udp_sink(m);
bind_udp_source(m);
diff --git a/gr-network/python/network/bindings/socket_pdu_python.cc b/gr-network/python/network/bindings/socket_pdu_python.cc
new file mode 100644
index 0000000000..a3fb134ec1
--- /dev/null
+++ b/gr-network/python/network/bindings/socket_pdu_python.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(socket_pdu.h) */
+/* BINDTOOL_HEADER_FILE_HASH(4c11b80b4561122125568a9ab76cea3a) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/network/socket_pdu.h>
+// pydoc.h is automatically generated in the build directory
+#include <socket_pdu_pydoc.h>
+
+void bind_socket_pdu(py::module& m)
+{
+
+ using socket_pdu = gr::network::socket_pdu;
+
+
+ py::class_<socket_pdu, gr::block, gr::basic_block, std::shared_ptr<socket_pdu>>(
+ m, "socket_pdu", D(socket_pdu))
+
+ .def(py::init(&socket_pdu::make),
+ py::arg("type"),
+ py::arg("addr"),
+ py::arg("port"),
+ py::arg("MTU") = 10000,
+ py::arg("tcp_no_delay") = false,
+ D(socket_pdu, make))
+
+
+ ;
+}
diff --git a/gr-network/python/network/bindings/tuntap_pdu_python.cc b/gr-network/python/network/bindings/tuntap_pdu_python.cc
new file mode 100644
index 0000000000..a5a09f2516
--- /dev/null
+++ b/gr-network/python/network/bindings/tuntap_pdu_python.cc
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(tuntap_pdu.h) */
+/* BINDTOOL_HEADER_FILE_HASH(26b7f31af528ff1bf62a965e6b0dd636) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/network/tuntap_pdu.h>
+// pydoc.h is automatically generated in the build directory
+#include <tuntap_pdu_pydoc.h>
+
+void bind_tuntap_pdu(py::module& m)
+{
+
+ using tuntap_pdu = gr::network::tuntap_pdu;
+
+
+ py::class_<tuntap_pdu, gr::block, gr::basic_block, std::shared_ptr<tuntap_pdu>>(
+ m, "tuntap_pdu", D(tuntap_pdu))
+
+ .def(py::init(&tuntap_pdu::make),
+ py::arg("dev"),
+ py::arg("MTU") = 10000,
+ py::arg("istunflag") = false,
+ D(tuntap_pdu, make))
+
+
+ ;
+}
diff --git a/gr-network/python/network/qa_socket_pdu.py b/gr-network/python/network/qa_socket_pdu.py
new file mode 100644
index 0000000000..136f7e4cc6
--- /dev/null
+++ b/gr-network/python/network/qa_socket_pdu.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+#
+
+
+from gnuradio import gr, gr_unittest, blocks, pdu
+from gnuradio import network
+import random
+import pmt
+import time
+
+
+class qa_socket_pdu (gr_unittest.TestCase):
+
+ def setUp(self):
+ random.seed(0)
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001(self):
+ # Test that blocks can be created and destroyed without hanging
+ port = str(random.Random().randint(0, 30000) + 10000)
+ self.pdu_send = network.socket_pdu("UDP_CLIENT", "localhost", port)
+ self.pdu_recv = network.socket_pdu("UDP_SERVER", "localhost", port)
+ self.pdu_send = None
+ self.pdu_recv = None
+
+ def test_002(self):
+ # Send a PDU through a pair of UDP sockets
+ port = str(random.Random().randint(0, 30000) + 10000)
+ srcdata = (0x64, 0x6f, 0x67, 0x65)
+ data = pmt.init_u8vector(srcdata.__len__(), srcdata)
+ pdu_msg = pmt.cons(pmt.PMT_NIL, data)
+
+ self.pdu_source = blocks.message_strobe(pdu_msg, 500)
+ self.pdu_recv = network.socket_pdu("UDP_SERVER", "localhost", port)
+ self.pdu_send = network.socket_pdu("UDP_CLIENT", "localhost", port)
+
+ self.dbg = blocks.message_debug()
+
+ self.tb.msg_connect(self.pdu_source, "strobe", self.pdu_send, "pdus")
+ self.tb.msg_connect(self.pdu_recv, "pdus", self.dbg, "store")
+
+ self.tb.start()
+ time.sleep(1)
+ self.tb.stop()
+ self.tb.wait()
+ self.pdu_send = None
+ self.pdu_recv = None
+
+ received = self.dbg.get_message(0)
+ received_data = pmt.cdr(received)
+ msg_data = []
+ for i in range(4):
+ msg_data.append(pmt.u8vector_ref(received_data, i))
+ self.assertEqual(srcdata, tuple(msg_data))
+
+ def test_003(self):
+ # Test that block stops when interacting with streaming interface
+ port = str(random.Random().randint(0, 30000) + 10000)
+ srcdata = (
+ 0x73,
+ 0x75,
+ 0x63,
+ 0x68,
+ 0x74,
+ 0x65,
+ 0x73,
+ 0x74,
+ 0x76,
+ 0x65,
+ 0x72,
+ 0x79,
+ 0x70,
+ 0x61,
+ 0x73,
+ 0x73)
+ tag_dict = {"offset": 0}
+ tag_dict["key"] = pmt.intern("len")
+ tag_dict["value"] = pmt.from_long(8)
+ tag1 = gr.python_to_tag(tag_dict)
+ tag_dict["offset"] = 8
+ tag2 = gr.python_to_tag(tag_dict)
+ tags = [tag1, tag2]
+
+ src = blocks.vector_source_b(srcdata, False, 1, tags)
+ ts_to_pdu = pdu.tagged_stream_to_pdu(gr.types.byte_t, "len")
+ pdu_send = network.socket_pdu("UDP_CLIENT", "localhost", "4141")
+ #pdu_recv = network.socket_pdu("UDP_SERVER", "localhost", port)
+ pdu_to_ts = pdu.pdu_to_tagged_stream(gr.types.byte_t, "len")
+ head = blocks.head(gr.sizeof_char, 10)
+ sink = blocks.vector_sink_b(1)
+
+ self.tb.connect(src, ts_to_pdu)
+ self.tb.msg_connect(ts_to_pdu, "pdus", pdu_send, "pdus")
+ # a UDP socket connects pdu_send to pdu_recv
+ # TODO: test that the recv socket can be destroyed from downstream
+ # that signals DONE. Also that we get the PDUs we sent
+ #self.tb.msg_connect(pdu_recv, "pdus", pdu_to_ts, "pdus")
+ #self.tb.connect(pdu_to_ts, head, sink)
+ self.tb.run()
+
+ def test_004(self):
+ # Test that the TCP server can stream PDUs <= the MTU size.
+ port = str(random.Random().randint(0, 30000) + 10000)
+ mtu = 10000
+ srcdata = tuple(x % 256 for x in range(mtu))
+ data = pmt.init_u8vector(srcdata.__len__(), srcdata)
+ pdu_msg = pmt.cons(pmt.PMT_NIL, data)
+
+ self.pdu_source = blocks.message_strobe(pdu_msg, 500)
+ self.pdu_send = network.socket_pdu("TCP_SERVER", "localhost", port, mtu)
+ self.pdu_recv = network.socket_pdu("TCP_CLIENT", "localhost", port, mtu)
+ self.pdu_sink = blocks.message_debug()
+
+ self.tb.msg_connect(self.pdu_source, "strobe", self.pdu_send, "pdus")
+ self.tb.msg_connect(self.pdu_recv, "pdus", self.pdu_sink, "store")
+
+ self.tb.start()
+ time.sleep(1)
+ self.tb.stop()
+ self.tb.wait()
+
+ received = self.pdu_sink.get_message(0)
+ received_data = pmt.cdr(received)
+ msg_data = []
+ for i in range(mtu):
+ msg_data.append(pmt.u8vector_ref(received_data, i))
+ self.assertEqual(srcdata, tuple(msg_data))
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_socket_pdu)
diff --git a/gr-pdu/grc/CMakeLists.txt b/gr-pdu/grc/CMakeLists.txt
index d6ac0115b0..fd0870c6cb 100644
--- a/gr-pdu/grc/CMakeLists.txt
+++ b/gr-pdu/grc/CMakeLists.txt
@@ -5,7 +5,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
-install(FILES
- pdu_pdu_split.block.yml
- DESTINATION ${GRC_BLOCKS_DIR}
-)
+########################################################################
+file(GLOB yml_files "*.yml")
+
+install(FILES ${yml_files} DESTINATION ${GRC_BLOCKS_DIR})
diff --git a/gr-pdu/grc/pdu.tree.yml b/gr-pdu/grc/pdu.tree.yml
new file mode 100644
index 0000000000..da988d007d
--- /dev/null
+++ b/gr-pdu/grc/pdu.tree.yml
@@ -0,0 +1,9 @@
+'[Core]':
+- Message Tools:
+ - pdu_pdu_filter
+ - pdu_pdu_remove
+ - pdu_pdu_set
+ - pdu_pdu_split
+ - pdu_pdu_to_tagged_stream
+ - pdu_tagged_stream_to_pdu
+ - pdu_random_pdu
diff --git a/gr-pdu/grc/pdu_pdu_filter.block.yml b/gr-pdu/grc/pdu_pdu_filter.block.yml
new file mode 100644
index 0000000000..292b7ab975
--- /dev/null
+++ b/gr-pdu/grc/pdu_pdu_filter.block.yml
@@ -0,0 +1,41 @@
+id: pdu_pdu_filter
+label: PDU Filter
+flags: [ python ]
+
+parameters:
+- id: k
+ label: Key
+ dtype: raw
+ default: pmt.intern("key")
+- id: v
+ label: Value
+ dtype: raw
+ default: pmt.intern("value")
+- id: invert
+ label: Invert Filter
+ dtype: bool
+ default: 'False'
+ options: ['False', 'True']
+ option_labels: ['No', 'Yes']
+
+inputs:
+- domain: message
+ id: pdus
+ optional: true
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+templates:
+ imports: |-
+ from gnuradio import pdu
+ import pmt
+ make: pdu.pdu_filter(${k}, ${v}, ${invert})
+ callbacks:
+ - set_key(${k})
+ - set_val(${v})
+ - set_inversion(${invert})
+
+file_format: 1
diff --git a/gr-pdu/grc/pdu_pdu_remove.block.yml b/gr-pdu/grc/pdu_pdu_remove.block.yml
new file mode 100644
index 0000000000..bcb582f0b4
--- /dev/null
+++ b/gr-pdu/grc/pdu_pdu_remove.block.yml
@@ -0,0 +1,29 @@
+id: pdu_pdu_remove
+label: PDU Remove
+flags: [ python ]
+
+parameters:
+- id: k
+ label: Key
+ dtype: raw
+ default: pmt.intern("key")
+
+inputs:
+- domain: message
+ id: pdus
+ optional: true
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+templates:
+ imports: |-
+ from gnuradio import pdu
+ import pmt
+ make: pdu.pdu_remove(${k})
+ callbacks:
+ - set_key(${k})
+
+file_format: 1
diff --git a/gr-pdu/grc/pdu_pdu_set.block.yml b/gr-pdu/grc/pdu_pdu_set.block.yml
new file mode 100644
index 0000000000..f3d3633d4d
--- /dev/null
+++ b/gr-pdu/grc/pdu_pdu_set.block.yml
@@ -0,0 +1,34 @@
+id: pdu_pdu_set
+label: PDU Set
+flags: [ python ]
+
+parameters:
+- id: k
+ label: Key
+ dtype: raw
+ default: pmt.intern("key")
+- id: v
+ label: Value
+ dtype: raw
+ default: pmt.intern("value")
+
+inputs:
+- domain: message
+ id: pdus
+ optional: true
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+templates:
+ imports: |-
+ from gnuradio import pdu
+ import pmt
+ make: pdu.pdu_set(${k}, ${v})
+ callbacks:
+ - set_key(${k})
+ - set_val(${v})
+
+file_format: 1
diff --git a/gr-pdu/grc/pdu_pdu_to_tagged_stream.block.yml b/gr-pdu/grc/pdu_pdu_to_tagged_stream.block.yml
new file mode 100644
index 0000000000..b1bb660151
--- /dev/null
+++ b/gr-pdu/grc/pdu_pdu_to_tagged_stream.block.yml
@@ -0,0 +1,37 @@
+id: pdu_pdu_to_tagged_stream
+label: PDU to Tagged Stream
+flags: [ python, cpp ]
+
+parameters:
+- id: type
+ label: Item Type
+ dtype: enum
+ options: [byte, complex, float]
+ option_attributes:
+ tv: [pdu.byte_t, pdu.complex_t, pdu.float_t]
+ hide: part
+- id: tag
+ label: Length tag name
+ dtype: string
+ default: packet_len
+
+inputs:
+- domain: message
+ id: pdus
+
+outputs:
+- domain: stream
+ dtype: ${ type }
+
+templates:
+ imports: from gnuradio import pdu
+ make: pdu.pdu_to_tagged_stream(${type.tv}, ${tag})
+
+cpp_templates:
+ includes: ['#include <gnuradio/pdu/pdu_to_tagged_stream.h>']
+ declarations: 'pdu::pdu_to_tagged_stream::sptr ${id};'
+ make: 'this->${id} = pdu::pdu_to_tagged_stream::make(${type.tv}, ${tag});'
+ translations:
+ pdu.: 'pdu::'
+
+file_format: 1
diff --git a/gr-pdu/grc/pdu_random_pdu.block.yml b/gr-pdu/grc/pdu_random_pdu.block.yml
new file mode 100644
index 0000000000..ec2bf72460
--- /dev/null
+++ b/gr-pdu/grc/pdu_random_pdu.block.yml
@@ -0,0 +1,39 @@
+id: pdu_random_pdu
+label: Random PDU Generator
+flags: [ python ]
+
+parameters:
+- id: minsize
+ label: Min Bytes
+ dtype: int
+ default: '50'
+- id: maxsize
+ label: Max Bytes
+ dtype: int
+ default: '2000'
+- id: mask
+ label: Byte Mask
+ dtype: int
+ default: '0xFF'
+- id: length_modulo
+ label: Length Modulo
+ dtype: int
+ default: '2'
+
+inputs:
+- domain: message
+ id: generate
+ optional: true
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+templates:
+ imports: |-
+ from gnuradio import pdu
+ import pmt
+ make: pdu.random_pdu(${minsize}, ${maxsize}, ${mask}, ${length_modulo})
+
+file_format: 1
diff --git a/gr-pdu/grc/pdu_tagged_stream_to_pdu.block.yml b/gr-pdu/grc/pdu_tagged_stream_to_pdu.block.yml
new file mode 100644
index 0000000000..2fc3071d91
--- /dev/null
+++ b/gr-pdu/grc/pdu_tagged_stream_to_pdu.block.yml
@@ -0,0 +1,36 @@
+id: pdu_tagged_stream_to_pdu
+label: Tagged Stream to PDU
+flags: [ python ]
+
+parameters:
+- id: type
+ label: Item Type
+ dtype: enum
+ options: [byte, complex, float]
+ option_attributes:
+ tv: [pdu.byte_t, pdu.complex_t, pdu.float_t]
+ hide: part
+- id: tag
+ label: Length tag name
+ dtype: string
+ default: packet_len
+
+inputs:
+- domain: stream
+ dtype: ${ type }
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+templates:
+ imports: from gnuradio import pdu
+ make: pdu.tagged_stream_to_pdu(${type.tv}, ${tag})
+
+cpp_templates:
+ includes: ['#include <gnuradio/pdu/tagged_stream_to_pdu.h>']
+ declarations: 'pdu::tagged_stream_to_pdu::sptr ${id};'
+ make: 'this->${id} = pdu::tagged_stream_to_pdu::make(${type.tv}, ${tag});'
+
+file_format: 1
diff --git a/gr-pdu/include/gnuradio/pdu/CMakeLists.txt b/gr-pdu/include/gnuradio/pdu/CMakeLists.txt
index b007685797..2daa248c19 100644
--- a/gr-pdu/include/gnuradio/pdu/CMakeLists.txt
+++ b/gr-pdu/include/gnuradio/pdu/CMakeLists.txt
@@ -10,8 +10,14 @@
########################################################################
install(FILES
api.h
- pdu_split.h
pdu.h
+ pdu_filter.h
+ pdu_remove.h
+ pdu_set.h
+ pdu_split.h
+ pdu_to_tagged_stream.h
+ random_pdu.h
+ tagged_stream_to_pdu.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/pdu
)
diff --git a/gr-pdu/include/gnuradio/pdu/pdu.h b/gr-pdu/include/gnuradio/pdu/pdu.h
index c6c0b4db3c..bb0ed72473 100644
--- a/gr-pdu/include/gnuradio/pdu/pdu.h
+++ b/gr-pdu/include/gnuradio/pdu/pdu.h
@@ -1,19 +1,24 @@
/* -*- c++ -*- */
/*
- * Copyright 2021 NTESS LLC.
+ * Copyright 2013,2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
*
* SPDX-License-Identifier: GPL-3.0-or-later
+ *
*/
-#ifndef INCLUDED_PDU_PORT_NAMES_H
-#define INCLUDED_PDU_PORT_NAMES_H
+#ifndef INCLUDED_PDU_PDU_H
+#define INCLUDED_PDU_PDU_H
+#include <gnuradio/gr_complex.h>
#include <gnuradio/pdu/api.h>
#include <pmt/pmt.h>
namespace gr {
namespace pdu {
+enum vector_type { byte_t, float_t, complex_t };
// static const PMT interned string getters
@@ -23,8 +28,14 @@ PDU_API const pmt::pmt_t PMTCONSTSTR__emit();
PDU_API const pmt::pmt_t PMTCONSTSTR__msg();
PDU_API const pmt::pmt_t PMTCONSTSTR__pdus();
+// pdu functions
+PDU_API size_t itemsize(vector_type type);
+PDU_API bool type_matches(vector_type type, pmt::pmt_t v);
+PDU_API pmt::pmt_t make_pdu_vector(vector_type type, const uint8_t* buf, size_t items);
+PDU_API vector_type type_from_pmt(pmt::pmt_t vector);
+
} // namespace pdu
} // namespace gr
-#endif /* INCLUDED_PDU_PORT_NAMES_H */
+#endif /* INCLUDED_PDU_PDU_H */
diff --git a/gr-pdu/include/gnuradio/pdu/pdu_filter.h b/gr-pdu/include/gnuradio/pdu/pdu_filter.h
new file mode 100644
index 0000000000..6437c04052
--- /dev/null
+++ b/gr-pdu/include/gnuradio/pdu/pdu_filter.h
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_PDU_FILTER_H
+#define INCLUDED_PDU_PDU_FILTER_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/pdu/api.h>
+
+namespace gr {
+namespace pdu {
+
+/*!
+ * \brief Propagates only pdus containing k=>v in meta
+ * \ingroup message_tools_blk
+ * \ingroup debug_tools_blk
+ */
+class PDU_API pdu_filter : virtual public block
+{
+public:
+ // gr::pdu::pdu_filter::sptr
+ typedef std::shared_ptr<pdu_filter> sptr;
+
+ /*!
+ * \brief Construct a PDU filter
+ */
+ static sptr make(pmt::pmt_t k, pmt::pmt_t v, bool invert = false);
+ virtual void set_key(pmt::pmt_t key) = 0;
+ virtual void set_val(pmt::pmt_t val) = 0;
+ virtual void set_inversion(bool invert) = 0;
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_PDU_FILTER_H */
diff --git a/gr-pdu/include/gnuradio/pdu/pdu_remove.h b/gr-pdu/include/gnuradio/pdu/pdu_remove.h
new file mode 100644
index 0000000000..22122b8a59
--- /dev/null
+++ b/gr-pdu/include/gnuradio/pdu/pdu_remove.h
@@ -0,0 +1,41 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_PDU_REMOVE_H
+#define INCLUDED_PDU_PDU_REMOVE_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/pdu/api.h>
+
+namespace gr {
+namespace pdu {
+
+/*!
+ * \brief remove key k in pdu's meta field and pass on
+ * \ingroup message_tools_blk
+ * \ingroup debug_tools_blk
+ */
+class PDU_API pdu_remove : virtual public block
+{
+public:
+ // gr::pdu::pdu_remove::sptr
+ typedef std::shared_ptr<pdu_remove> sptr;
+
+ /*!
+ * \brief Construct a PDU meta remove block
+ */
+ static sptr make(pmt::pmt_t k);
+ virtual void set_key(pmt::pmt_t key) = 0;
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_PDU_REMOVE_H */
diff --git a/gr-pdu/include/gnuradio/pdu/pdu_set.h b/gr-pdu/include/gnuradio/pdu/pdu_set.h
new file mode 100644
index 0000000000..1874cbe87e
--- /dev/null
+++ b/gr-pdu/include/gnuradio/pdu/pdu_set.h
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_PDU_SET_H
+#define INCLUDED_PDU_PDU_SET_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/pdu/api.h>
+
+namespace gr {
+namespace pdu {
+
+/*!
+ * \brief Set k=>v in pdu's meta field and pass on
+ * \ingroup message_tools_blk
+ * \ingroup debug_tools_blk
+ */
+class PDU_API pdu_set : virtual public block
+{
+public:
+ // gr::pdu::pdu_set::sptr
+ typedef std::shared_ptr<pdu_set> sptr;
+
+ /*!
+ * \brief Construct a PDU meta set block
+ */
+ static sptr make(pmt::pmt_t k, pmt::pmt_t v);
+ virtual void set_key(pmt::pmt_t key) = 0;
+ virtual void set_val(pmt::pmt_t val) = 0;
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_PDU_SET_H */
diff --git a/gr-pdu/include/gnuradio/pdu/pdu_to_tagged_stream.h b/gr-pdu/include/gnuradio/pdu/pdu_to_tagged_stream.h
new file mode 100644
index 0000000000..ed0c7b8064
--- /dev/null
+++ b/gr-pdu/include/gnuradio/pdu/pdu_to_tagged_stream.h
@@ -0,0 +1,44 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_PDU_TO_TAGGED_STREAM_H
+#define INCLUDED_PDU_PDU_TO_TAGGED_STREAM_H
+
+#include <gnuradio/pdu.h>
+#include <gnuradio/pdu/api.h>
+#include <gnuradio/tagged_stream_block.h>
+
+namespace gr {
+namespace pdu {
+
+/*!
+ * \brief Turns received PDUs into a tagged stream of items
+ * \ingroup message_tools_blk
+ */
+class PDU_API pdu_to_tagged_stream : virtual public tagged_stream_block
+{
+public:
+ // gr::pdu::pdu_to_tagged_stream::sptr
+ typedef std::shared_ptr<pdu_to_tagged_stream> sptr;
+
+ /*!
+ * \brief Construct a pdu_to_tagged_stream block
+ * \param type PDU type of gr::types::vector_type
+ * \param lengthtagname The name of the tag that specifies how long the packet is.
+ * Defaults to 'packet_len'.
+ */
+ static sptr make(gr::types::vector_type type,
+ const std::string& lengthtagname = "packet_len");
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_PDU_TO_TAGGED_STREAM_H */
diff --git a/gr-pdu/include/gnuradio/pdu/random_pdu.h b/gr-pdu/include/gnuradio/pdu/random_pdu.h
new file mode 100644
index 0000000000..a9b8b6ed78
--- /dev/null
+++ b/gr-pdu/include/gnuradio/pdu/random_pdu.h
@@ -0,0 +1,41 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_RANDOM_PDU_H
+#define INCLUDED_PDU_RANDOM_PDU_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/pdu/api.h>
+
+namespace gr {
+namespace pdu {
+
+/*!
+ * \brief Sends a random PDU at intervals
+ * \ingroup message_tools_blk
+ * \ingroup debug_tools_blk
+ */
+class PDU_API random_pdu : virtual public block
+{
+public:
+ // gr::pdu::random_pdu::sptr
+ typedef std::shared_ptr<random_pdu> sptr;
+
+ /*!
+ * \brief Construct a random PDU generator
+ */
+ static sptr
+ make(int mintime, int maxtime, unsigned char byte_mask = 0xFF, int length_modulo = 1);
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_RANDOM_PDU_H */
diff --git a/gr-pdu/include/gnuradio/pdu/tagged_stream_to_pdu.h b/gr-pdu/include/gnuradio/pdu/tagged_stream_to_pdu.h
new file mode 100644
index 0000000000..c46ac72982
--- /dev/null
+++ b/gr-pdu/include/gnuradio/pdu/tagged_stream_to_pdu.h
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013,2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_TAGGED_STREAM_TO_PDU_H
+#define INCLUDED_PDU_TAGGED_STREAM_TO_PDU_H
+
+#include <gnuradio/pdu.h>
+#include <gnuradio/pdu/api.h>
+#include <gnuradio/tagged_stream_block.h>
+
+namespace gr {
+namespace pdu {
+
+/*!
+ * \brief Turns received stream data and tags into PDUs and sends
+ * them through a message port.
+ * \ingroup message_tools_blk
+ *
+ * The sent message is a PMT-pair (created by pmt::cons()). The
+ * first element is a dictionary containing all the tags. The
+ * second is a vector containing the actual data.
+ */
+class PDU_API tagged_stream_to_pdu : virtual public tagged_stream_block
+{
+public:
+ // gr::pdu::tagged_stream_to_pdu::sptr
+ typedef std::shared_ptr<tagged_stream_to_pdu> sptr;
+
+ /*!
+ * \brief Construct a tagged_stream_to_pdu block
+ * \param type PDU type of gr::types::vector_type
+ * \param lengthtagname The name of the tag that specifies
+ * how long the packet is.
+ */
+ static sptr make(gr::types::vector_type type,
+ const std::string& lengthtagname = "packet_len");
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_TAGGED_STREAM_TO_PDU_H */
diff --git a/gr-pdu/lib/CMakeLists.txt b/gr-pdu/lib/CMakeLists.txt
index 72fb6a80f3..e0d609424a 100644
--- a/gr-pdu/lib/CMakeLists.txt
+++ b/gr-pdu/lib/CMakeLists.txt
@@ -9,8 +9,14 @@
# Setup library
########################################################################
add_library(gnuradio-pdu
- pdu_split_impl.cc
pdu.cc
+ pdu_filter_impl.cc
+ pdu_remove_impl.cc
+ pdu_set_impl.cc
+ pdu_split_impl.cc
+ pdu_to_tagged_stream_impl.cc
+ random_pdu_impl.cc
+ tagged_stream_to_pdu_impl.cc
)
#Add Windows DLL resource file if using MSVC
diff --git a/gr-pdu/lib/pdu.cc b/gr-pdu/lib/pdu.cc
index 68d7dec3a4..3f0a32e6e4 100644
--- a/gr-pdu/lib/pdu.cc
+++ b/gr-pdu/lib/pdu.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2021 NTESS LLC.
+ * Copyright 2013,2021 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
@@ -44,5 +44,58 @@ const pmt::pmt_t PMTCONSTSTR__pdus()
}
+size_t itemsize(vector_type type)
+{
+ switch (type) {
+ case byte_t:
+ return sizeof(char);
+ case float_t:
+ return sizeof(float);
+ case complex_t:
+ return sizeof(gr_complex);
+ default:
+ throw std::runtime_error("bad PDU type");
+ }
+}
+
+bool type_matches(vector_type type, pmt::pmt_t v)
+{
+ switch (type) {
+ case byte_t:
+ return pmt::is_u8vector(v);
+ case float_t:
+ return pmt::is_f32vector(v);
+ case complex_t:
+ return pmt::is_c32vector(v);
+ default:
+ throw std::runtime_error("bad PDU type");
+ }
+}
+
+pmt::pmt_t make_pdu_vector(vector_type type, const uint8_t* buf, size_t items)
+{
+ switch (type) {
+ case byte_t:
+ return pmt::init_u8vector(items, buf);
+ case float_t:
+ return pmt::init_f32vector(items, (const float*)buf);
+ case complex_t:
+ return pmt::init_c32vector(items, (const gr_complex*)buf);
+ default:
+ throw std::runtime_error("bad PDU type");
+ }
+}
+
+vector_type type_from_pmt(pmt::pmt_t vector)
+{
+ if (pmt::is_u8vector(vector))
+ return byte_t;
+ if (pmt::is_f32vector(vector))
+ return float_t;
+ if (pmt::is_c32vector(vector))
+ return complex_t;
+ throw std::runtime_error("bad PDU type");
+}
+
} /* namespace pdu */
} /* namespace gr */
diff --git a/gr-pdu/lib/pdu_filter_impl.cc b/gr-pdu/lib/pdu_filter_impl.cc
new file mode 100644
index 0000000000..34c519a1f6
--- /dev/null
+++ b/gr-pdu/lib/pdu_filter_impl.cc
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pdu_filter_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace pdu {
+
+pdu_filter::sptr pdu_filter::make(pmt::pmt_t k, pmt::pmt_t v, bool invert)
+{
+ return gnuradio::make_block_sptr<pdu_filter_impl>(k, v, invert);
+}
+
+pdu_filter_impl::pdu_filter_impl(pmt::pmt_t k, pmt::pmt_t v, bool invert)
+ : block("pdu_filter", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_k(k),
+ d_v(v),
+ d_invert(invert)
+{
+ message_port_register_out(msgport_names::pdus());
+ message_port_register_in(msgport_names::pdus());
+ set_msg_handler(msgport_names::pdus(),
+ [this](pmt::pmt_t msg) { this->handle_msg(msg); });
+}
+
+void pdu_filter_impl::handle_msg(pmt::pmt_t pdu)
+{
+ pmt::pmt_t meta = pmt::car(pdu);
+ bool output = d_invert;
+
+ // check base type
+ // key exists
+ // value matches
+ if (pmt::is_dict(meta) && dict_has_key(meta, d_k) &&
+ pmt::eqv(pmt::dict_ref(meta, d_k, pmt::PMT_NIL), d_v)) {
+ output = !d_invert;
+ }
+
+ // if all tests pass, propagate the pdu
+ if (output) {
+ message_port_pub(msgport_names::pdus(), pdu);
+ }
+}
+
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gr-pdu/lib/pdu_filter_impl.h b/gr-pdu/lib/pdu_filter_impl.h
new file mode 100644
index 0000000000..e8f532f132
--- /dev/null
+++ b/gr-pdu/lib/pdu_filter_impl.h
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_PDU_FILTER_IMPL_H
+#define INCLUDED_PDU_PDU_FILTER_IMPL_H
+
+#include <gnuradio/pdu/pdu_filter.h>
+
+namespace gr {
+namespace pdu {
+
+class pdu_filter_impl : public pdu_filter
+{
+private:
+ pmt::pmt_t d_k;
+ pmt::pmt_t d_v;
+ bool d_invert;
+
+public:
+ pdu_filter_impl(pmt::pmt_t k, pmt::pmt_t v, bool invert);
+ void handle_msg(pmt::pmt_t msg);
+ void set_key(pmt::pmt_t key) override { d_k = key; };
+ void set_val(pmt::pmt_t val) override { d_v = val; };
+ void set_inversion(bool invert) override { d_invert = invert; };
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_PDU_FILTER_IMPL_H */
diff --git a/gr-pdu/lib/pdu_remove_impl.cc b/gr-pdu/lib/pdu_remove_impl.cc
new file mode 100644
index 0000000000..a23869a9ff
--- /dev/null
+++ b/gr-pdu/lib/pdu_remove_impl.cc
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pdu_remove_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace pdu {
+
+pdu_remove::sptr pdu_remove::make(pmt::pmt_t k)
+{
+ return gnuradio::make_block_sptr<pdu_remove_impl>(k);
+}
+
+pdu_remove_impl::pdu_remove_impl(pmt::pmt_t k)
+ : block("pdu_remove", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_k(k)
+{
+ message_port_register_out(msgport_names::pdus());
+ message_port_register_in(msgport_names::pdus());
+ set_msg_handler(msgport_names::pdus(),
+ [this](pmt::pmt_t msg) { this->handle_msg(msg); });
+}
+
+void pdu_remove_impl::handle_msg(pmt::pmt_t pdu)
+{
+ // add the field and publish
+ pmt::pmt_t meta = pmt::car(pdu);
+ if (pmt::is_null(meta)) {
+ meta = pmt::make_dict();
+ } else if (!pmt::is_dict(meta)) {
+ throw std::runtime_error("pdu_remove received non PDU input");
+ }
+ meta = pmt::dict_delete(meta, d_k);
+ message_port_pub(msgport_names::pdus(), pmt::cons(meta, pmt::cdr(pdu)));
+}
+
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gr-pdu/lib/pdu_remove_impl.h b/gr-pdu/lib/pdu_remove_impl.h
new file mode 100644
index 0000000000..43da752ddf
--- /dev/null
+++ b/gr-pdu/lib/pdu_remove_impl.h
@@ -0,0 +1,33 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_PDU_REMOVE_IMPL_H
+#define INCLUDED_PDU_PDU_REMOVE_IMPL_H
+
+#include <gnuradio/pdu/pdu_remove.h>
+
+namespace gr {
+namespace pdu {
+
+class pdu_remove_impl : public pdu_remove
+{
+private:
+ pmt::pmt_t d_k;
+
+public:
+ pdu_remove_impl(pmt::pmt_t k);
+ void handle_msg(pmt::pmt_t msg);
+ void set_key(pmt::pmt_t key) override { d_k = key; };
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_PDU_REMOVE_IMPL_H */
diff --git a/gr-pdu/lib/pdu_set_impl.cc b/gr-pdu/lib/pdu_set_impl.cc
new file mode 100644
index 0000000000..08dd68d2b0
--- /dev/null
+++ b/gr-pdu/lib/pdu_set_impl.cc
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pdu_set_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace pdu {
+
+pdu_set::sptr pdu_set::make(pmt::pmt_t k, pmt::pmt_t v)
+{
+ return gnuradio::make_block_sptr<pdu_set_impl>(k, v);
+}
+
+pdu_set_impl::pdu_set_impl(pmt::pmt_t k, pmt::pmt_t v)
+ : block("pdu_set", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_k(k),
+ d_v(v)
+{
+ message_port_register_out(msgport_names::pdus());
+ message_port_register_in(msgport_names::pdus());
+ set_msg_handler(msgport_names::pdus(),
+ [this](pmt::pmt_t msg) { this->handle_msg(msg); });
+}
+
+void pdu_set_impl::handle_msg(pmt::pmt_t pdu)
+{
+ // add the field and publish
+ pmt::pmt_t meta = pmt::car(pdu);
+ if (pmt::is_null(meta)) {
+ meta = pmt::make_dict();
+ } else if (!pmt::is_dict(meta)) {
+ throw std::runtime_error("pdu_set received non PDU input");
+ }
+ meta = pmt::dict_add(meta, d_k, d_v);
+ message_port_pub(msgport_names::pdus(), pmt::cons(meta, pmt::cdr(pdu)));
+}
+
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gr-pdu/lib/pdu_set_impl.h b/gr-pdu/lib/pdu_set_impl.h
new file mode 100644
index 0000000000..4ecfb8db44
--- /dev/null
+++ b/gr-pdu/lib/pdu_set_impl.h
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_PDU_SET_IMPL_H
+#define INCLUDED_PDU_PDU_SET_IMPL_H
+
+#include <gnuradio/pdu/pdu_set.h>
+
+namespace gr {
+namespace pdu {
+
+class pdu_set_impl : public pdu_set
+{
+private:
+ pmt::pmt_t d_k;
+ pmt::pmt_t d_v;
+
+public:
+ pdu_set_impl(pmt::pmt_t k, pmt::pmt_t v);
+ void handle_msg(pmt::pmt_t msg);
+ void set_key(pmt::pmt_t key) override { d_k = key; };
+ void set_val(pmt::pmt_t val) override { d_v = val; };
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_PDU_SET_IMPL_H */
diff --git a/gr-pdu/lib/pdu_split_impl.cc b/gr-pdu/lib/pdu_split_impl.cc
index 491f00683c..678e650ee2 100644
--- a/gr-pdu/lib/pdu_split_impl.cc
+++ b/gr-pdu/lib/pdu_split_impl.cc
@@ -14,7 +14,7 @@
#include "pdu_split_impl.h"
#include <gnuradio/io_signature.h>
-#include <gnuradio/pdu/pdu.h>
+#include <gnuradio/pdu.h>
namespace gr {
namespace pdu {
@@ -28,11 +28,11 @@ pdu_split_impl::pdu_split_impl(const bool pass_empty_data)
: gr::block("pdu_split", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
d_pass_empty_data(pass_empty_data)
{
- message_port_register_in(PMTCONSTSTR__pdus());
- set_msg_handler(PMTCONSTSTR__pdus(),
+ message_port_register_in(msgport_names::pdus());
+ set_msg_handler(msgport_names::pdus(),
[this](pmt::pmt_t msg) { this->handle_pdu(msg); });
- message_port_register_out(PMTCONSTSTR__dict());
- message_port_register_out(PMTCONSTSTR__data());
+ message_port_register_out(msgport_names::dict());
+ message_port_register_out(msgport_names::vec());
}
pdu_split_impl::~pdu_split_impl() {}
@@ -49,11 +49,11 @@ void pdu_split_impl::handle_pdu(pmt::pmt_t pdu)
pmt::pmt_t data = pmt::cdr(pdu);
if ((!pmt::equal(meta, pmt::PMT_NIL)) | d_pass_empty_data) {
- message_port_pub(PMTCONSTSTR__dict(), meta);
+ message_port_pub(msgport_names::dict(), meta);
}
if (pmt::length(data) | d_pass_empty_data) {
- message_port_pub(PMTCONSTSTR__data(), data);
+ message_port_pub(msgport_names::vec(), data);
}
}
diff --git a/gr-pdu/lib/pdu_split_impl.h b/gr-pdu/lib/pdu_split_impl.h
index e927463dba..cf26b5055e 100644
--- a/gr-pdu/lib/pdu_split_impl.h
+++ b/gr-pdu/lib/pdu_split_impl.h
@@ -21,11 +21,17 @@ class pdu_split_impl : public pdu_split
private:
const bool d_pass_empty_data;
+ /*!
+ * \brief PDU formatted messages received in this port are split into theier
+ * dictionary and vector which are each emitted on separate output ports.
+ *
+ * \param pdu A PDU message passed from the scheduler's message handling.
+ */
+ void handle_pdu(pmt::pmt_t pdu);
+
public:
pdu_split_impl(const bool pass_empty_data);
- ~pdu_split_impl();
-
- void handle_pdu(pmt::pmt_t pdu);
+ ~pdu_split_impl() override;
};
} // namespace pdu
diff --git a/gr-pdu/lib/pdu_to_tagged_stream_impl.cc b/gr-pdu/lib/pdu_to_tagged_stream_impl.cc
new file mode 100644
index 0000000000..035e8f85af
--- /dev/null
+++ b/gr-pdu/lib/pdu_to_tagged_stream_impl.cc
@@ -0,0 +1,98 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pdu_to_tagged_stream_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace pdu {
+
+pdu_to_tagged_stream::sptr pdu_to_tagged_stream::make(gr::types::vector_type type,
+ const std::string& tsb_tag_key)
+{
+ return gnuradio::make_block_sptr<pdu_to_tagged_stream_impl>(type, tsb_tag_key);
+}
+
+pdu_to_tagged_stream_impl::pdu_to_tagged_stream_impl(gr::types::vector_type type,
+ const std::string& tsb_tag_key)
+ : tagged_stream_block("pdu_to_tagged_stream",
+ io_signature::make(0, 0, 0),
+ io_signature::make(1, 1, pdu::itemsize(type)),
+ tsb_tag_key),
+ d_itemsize(pdu::itemsize(type)),
+ d_curr_len(0)
+{
+ message_port_register_in(msgport_names::pdus());
+}
+
+int pdu_to_tagged_stream_impl::calculate_output_stream_length(const gr_vector_int&)
+{
+ if (d_curr_len == 0) {
+ pmt::pmt_t msg(delete_head_nowait(msgport_names::pdus()));
+ if (msg.get() == NULL) {
+ return 0;
+ }
+
+ if (!pmt::is_pair(msg))
+ throw std::runtime_error("received a malformed pdu message");
+
+ d_curr_meta = pmt::car(msg);
+ d_curr_vect = pmt::cdr(msg);
+ // do not assume the length of PMT is in items (e.g.: from socket_pdu)
+ d_curr_len = pmt::blob_length(d_curr_vect) / d_itemsize;
+ }
+
+ return d_curr_len;
+}
+
+int pdu_to_tagged_stream_impl::work(int noutput_items,
+ gr_vector_int& ninput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ uint8_t* out = (uint8_t*)output_items[0];
+
+ if (d_curr_len == 0) {
+ return 0;
+ }
+
+ // work() should only be called if the current PDU fits entirely
+ // into the output buffer.
+ assert(noutput_items >= 0 && (unsigned int)noutput_items >= d_curr_len);
+
+ // Copy vector output
+ size_t nout = d_curr_len;
+ size_t io(0);
+ const uint8_t* ptr = (const uint8_t*)uniform_vector_elements(d_curr_vect, io);
+ memcpy(out, ptr, d_curr_len * d_itemsize);
+
+ // Copy tags
+ if (!pmt::eq(d_curr_meta, pmt::PMT_NIL)) {
+ pmt::pmt_t klist(pmt::dict_keys(d_curr_meta));
+ for (size_t i = 0; i < pmt::length(klist); i++) {
+ pmt::pmt_t k(pmt::nth(i, klist));
+ pmt::pmt_t v(pmt::dict_ref(d_curr_meta, k, pmt::PMT_NIL));
+ add_item_tag(0, nitems_written(0), k, v, alias_pmt());
+ }
+ }
+
+ // Reset state
+ d_curr_len = 0;
+
+ return nout;
+} /* work() */
+
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gr-pdu/lib/pdu_to_tagged_stream_impl.h b/gr-pdu/lib/pdu_to_tagged_stream_impl.h
new file mode 100644
index 0000000000..3fdb71491c
--- /dev/null
+++ b/gr-pdu/lib/pdu_to_tagged_stream_impl.h
@@ -0,0 +1,41 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_TO_TAGGED_STREAM_IMPL_H
+#define INCLUDED_PDU_TO_TAGGED_STREAM_IMPL_H
+
+#include <gnuradio/pdu/pdu_to_tagged_stream.h>
+
+namespace gr {
+namespace pdu {
+
+class PDU_API pdu_to_tagged_stream_impl : public pdu_to_tagged_stream
+{
+ const size_t d_itemsize;
+ pmt::pmt_t d_curr_meta;
+ pmt::pmt_t d_curr_vect;
+ size_t d_curr_len;
+
+public:
+ pdu_to_tagged_stream_impl(gr::types::vector_type type,
+ const std::string& lengthtagname = "packet_len");
+
+ int calculate_output_stream_length(const gr_vector_int& ninput_items) override;
+
+ int work(int noutput_items,
+ gr_vector_int& ninput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items) override;
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_TO_TAGGED_STREAM_IMPL_H */
diff --git a/gr-pdu/lib/random_pdu_impl.cc b/gr-pdu/lib/random_pdu_impl.cc
new file mode 100644
index 0000000000..a31f82381e
--- /dev/null
+++ b/gr-pdu/lib/random_pdu_impl.cc
@@ -0,0 +1,74 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "random_pdu_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace pdu {
+
+random_pdu::sptr
+random_pdu::make(int min_items, int max_items, unsigned char byte_mask, int length_modulo)
+{
+ return gnuradio::make_block_sptr<random_pdu_impl>(
+ min_items, max_items, byte_mask, length_modulo);
+}
+
+random_pdu_impl::random_pdu_impl(int min_items,
+ int max_items,
+ unsigned char byte_mask,
+ int length_modulo)
+ : block("random_pdu", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_urange(min_items, max_items),
+ d_brange(0, 255),
+ d_mask(byte_mask),
+ d_length_modulo(length_modulo)
+{
+ message_port_register_out(msgport_names::pdus());
+ message_port_register_in(pmt::mp("generate"));
+ set_msg_handler(pmt::mp("generate"),
+ [this](pmt::pmt_t msg) { this->generate_pdu(msg); });
+ if (length_modulo < 1)
+ throw std::runtime_error("length_module must be >= 1");
+ if (max_items < length_modulo)
+ throw std::runtime_error("max_items must be >= to length_modulo");
+}
+
+bool random_pdu_impl::start()
+{
+ output_random();
+ return true;
+}
+
+void random_pdu_impl::output_random()
+{
+ // pick a random vector length
+ int len = d_urange(d_rng);
+ len = std::max(d_length_modulo, len - len % d_length_modulo);
+
+ // fill it with random bytes
+ std::vector<unsigned char> vec(len);
+ for (int i = 0; i < len; i++)
+ vec[i] = ((unsigned char)d_brange(d_rng)) & d_mask;
+
+ // send the vector
+ pmt::pmt_t vecpmt(pmt::make_blob(&vec[0], len));
+ pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL, vecpmt));
+
+ message_port_pub(msgport_names::pdus(), pdu);
+}
+
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gr-pdu/lib/random_pdu_impl.h b/gr-pdu/lib/random_pdu_impl.h
new file mode 100644
index 0000000000..2f2535fe47
--- /dev/null
+++ b/gr-pdu/lib/random_pdu_impl.h
@@ -0,0 +1,46 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_RANDOM_PDU_IMPL_H
+#define INCLUDED_PDU_RANDOM_PDU_IMPL_H
+
+#include <gnuradio/pdu/random_pdu.h>
+#include <boost/generator_iterator.hpp>
+
+#include <random>
+
+namespace gr {
+namespace pdu {
+
+class random_pdu_impl : public random_pdu
+{
+private:
+ std::mt19937 d_rng;
+ std::uniform_int_distribution<> d_urange;
+ std::uniform_int_distribution<> d_brange;
+ const unsigned char d_mask;
+ const int d_length_modulo;
+
+public:
+ random_pdu_impl(int min_items,
+ int max_items,
+ unsigned char byte_mask,
+ int length_modulo);
+
+ bool start() override;
+ void output_random();
+ void generate_pdu(pmt::pmt_t msg) { output_random(); }
+ void generate_pdu() { output_random(); }
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif /* INCLUDED_PDU_RANDOM_PDU_IMPL_H */
diff --git a/gr-pdu/lib/tagged_stream_to_pdu_impl.cc b/gr-pdu/lib/tagged_stream_to_pdu_impl.cc
new file mode 100644
index 0000000000..66d3cb20e1
--- /dev/null
+++ b/gr-pdu/lib/tagged_stream_to_pdu_impl.cc
@@ -0,0 +1,66 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tagged_stream_to_pdu_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace pdu {
+
+tagged_stream_to_pdu::sptr tagged_stream_to_pdu::make(gr::types::vector_type type,
+ const std::string& lengthtagname)
+{
+ return gnuradio::make_block_sptr<tagged_stream_to_pdu_impl>(type, lengthtagname);
+}
+
+tagged_stream_to_pdu_impl::tagged_stream_to_pdu_impl(gr::types::vector_type type,
+ const std::string& lengthtagname)
+ : tagged_stream_block("tagged_stream_to_pdu",
+ io_signature::make(1, 1, pdu::itemsize(type)),
+ io_signature::make(0, 0, 0),
+ lengthtagname),
+ d_type(type),
+ d_pdu_meta(pmt::PMT_NIL),
+ d_pdu_vector(pmt::PMT_NIL)
+{
+ message_port_register_out(msgport_names::pdus());
+}
+
+int tagged_stream_to_pdu_impl::work(int noutput_items,
+ gr_vector_int& ninput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ const uint8_t* in = (const uint8_t*)input_items[0];
+
+ // Grab tags, throw them into dict
+ get_tags_in_range(d_tags, 0, nitems_read(0), nitems_read(0) + ninput_items[0]);
+ d_pdu_meta = pmt::make_dict();
+ for (const auto& tag : d_tags) {
+ d_pdu_meta = dict_add(d_pdu_meta, tag.key, tag.value);
+ }
+
+ // Grab data, throw into vector
+ d_pdu_vector = pdu::make_pdu_vector(d_type, in, ninput_items[0]);
+
+ // Send msg
+ pmt::pmt_t msg = pmt::cons(d_pdu_meta, d_pdu_vector);
+ message_port_pub(msgport_names::pdus(), msg);
+
+ return ninput_items[0];
+}
+
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gr-pdu/lib/tagged_stream_to_pdu_impl.h b/gr-pdu/lib/tagged_stream_to_pdu_impl.h
new file mode 100644
index 0000000000..5e685b89b1
--- /dev/null
+++ b/gr-pdu/lib/tagged_stream_to_pdu_impl.h
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_TAGGED_STREAM_TO_PDU_IMPL_H
+#define INCLUDED_TAGGED_STREAM_TO_PDU_IMPL_H
+
+#include <gnuradio/pdu/tagged_stream_to_pdu.h>
+
+namespace gr {
+namespace pdu {
+
+class PDU_API tagged_stream_to_pdu_impl : public tagged_stream_to_pdu
+{
+ const gr::types::vector_type d_type;
+ pmt::pmt_t d_pdu_meta;
+ pmt::pmt_t d_pdu_vector;
+ std::vector<tag_t> d_tags;
+
+public:
+ tagged_stream_to_pdu_impl(gr::types::vector_type type,
+ const std::string& lengthtagname);
+
+ int work(int noutput_items,
+ gr_vector_int& ninput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items) override;
+};
+
+} /* namespace pdu */
+} /* namespace gr */
+
+#endif
diff --git a/gr-pdu/python/pdu/bindings/CMakeLists.txt b/gr-pdu/python/pdu/bindings/CMakeLists.txt
index a6b3252af5..1bc138bdb8 100644
--- a/gr-pdu/python/pdu/bindings/CMakeLists.txt
+++ b/gr-pdu/python/pdu/bindings/CMakeLists.txt
@@ -5,8 +5,14 @@ include(GrPybind)
########################################################################
list(APPEND pdu_python_files
- pdu_split_python.cc
+ pdu_filter_python.cc
pdu_python.cc
+ pdu_remove_python.cc
+ pdu_set_python.cc
+ pdu_split_python.cc
+ pdu_to_tagged_stream_python.cc
+ random_pdu_python.cc
+ tagged_stream_to_pdu_python.cc
python_bindings.cc)
GR_PYBIND_MAKE_CHECK_HASH(pdu
diff --git a/gr-pdu/python/pdu/bindings/docstrings/pdu_filter_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/pdu_filter_pydoc_template.h
new file mode 100644
index 0000000000..349fa30c4f
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/docstrings/pdu_filter_pydoc_template.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, pdu, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_pdu_pdu_filter = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_filter_pdu_filter_0 = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_filter_pdu_filter_1 = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_filter_make = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_filter_set_key = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_filter_set_val = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_filter_set_inversion = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/docstrings/pdu_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/pdu_pydoc_template.h
index b1840f5574..9fbbbf380a 100644
--- a/gr-pdu/python/pdu/bindings/docstrings/pdu_pydoc_template.h
+++ b/gr-pdu/python/pdu/bindings/docstrings/pdu_pydoc_template.h
@@ -28,3 +28,15 @@ static const char* __doc_gr_pdu_PMTCONSTSTR__msg = R"doc()doc";
static const char* __doc_gr_pdu_PMTCONSTSTR__pdus = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_itemsize = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_type_matches = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_make_pdu_vector = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_type_from_pmt = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/docstrings/pdu_remove_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/pdu_remove_pydoc_template.h
new file mode 100644
index 0000000000..3360f01bd5
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/docstrings/pdu_remove_pydoc_template.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, pdu, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_pdu_pdu_remove = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_remove_pdu_remove_0 = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_remove_pdu_remove_1 = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_remove_make = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_remove_set_key = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/docstrings/pdu_set_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/pdu_set_pydoc_template.h
new file mode 100644
index 0000000000..69c0cf27e8
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/docstrings/pdu_set_pydoc_template.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, pdu, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_pdu_pdu_set = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_set_pdu_set_0 = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_set_pdu_set_1 = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_set_make = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_set_set_key = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_set_set_val = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/docstrings/pdu_to_tagged_stream_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/pdu_to_tagged_stream_pydoc_template.h
new file mode 100644
index 0000000000..77d9709900
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/docstrings/pdu_to_tagged_stream_pydoc_template.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, pdu, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_pdu_pdu_to_tagged_stream = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_to_tagged_stream_pdu_to_tagged_stream = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_pdu_to_tagged_stream_make = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/docstrings/random_pdu_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/random_pdu_pydoc_template.h
new file mode 100644
index 0000000000..848eac8df3
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/docstrings/random_pdu_pydoc_template.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, pdu, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_pdu_random_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_random_pdu_random_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_random_pdu_make = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/docstrings/tagged_stream_to_pdu_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/tagged_stream_to_pdu_pydoc_template.h
new file mode 100644
index 0000000000..012f727ef9
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/docstrings/tagged_stream_to_pdu_pydoc_template.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, pdu, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_pdu_tagged_stream_to_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_tagged_stream_to_pdu_tagged_stream_to_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_tagged_stream_to_pdu_make = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/pdu_filter_python.cc b/gr-pdu/python/pdu/bindings/pdu_filter_python.cc
new file mode 100644
index 0000000000..51304a5bf5
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/pdu_filter_python.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(pdu_filter.h) */
+/* BINDTOOL_HEADER_FILE_HASH(8ca41a1466a0f9939a533af682d055cb) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu/pdu_filter.h>
+// pydoc.h is automatically generated in the build directory
+#include <pdu_filter_pydoc.h>
+
+void bind_pdu_filter(py::module& m)
+{
+
+ using pdu_filter = ::gr::pdu::pdu_filter;
+
+
+ py::class_<pdu_filter, gr::block, gr::basic_block, std::shared_ptr<pdu_filter>>(
+ m, "pdu_filter", D(pdu_filter))
+
+ .def(py::init(&pdu_filter::make),
+ py::arg("k"),
+ py::arg("v"),
+ py::arg("invert") = false,
+ D(pdu_filter, make))
+
+
+ .def("set_key", &pdu_filter::set_key, py::arg("key"), D(pdu_filter, set_key))
+
+
+ .def("set_val", &pdu_filter::set_val, py::arg("val"), D(pdu_filter, set_val))
+
+
+ .def("set_inversion",
+ &pdu_filter::set_inversion,
+ py::arg("invert"),
+ D(pdu_filter, set_inversion))
+
+ ;
+}
diff --git a/gr-pdu/python/pdu/bindings/pdu_python.cc b/gr-pdu/python/pdu/bindings/pdu_python.cc
index bb34811618..2e25fdb179 100644
--- a/gr-pdu/python/pdu/bindings/pdu_python.cc
+++ b/gr-pdu/python/pdu/bindings/pdu_python.cc
@@ -14,7 +14,7 @@
/* BINDTOOL_GEN_AUTOMATIC(0) */
/* BINDTOOL_USE_PYGCCXML(0) */
/* BINDTOOL_HEADER_FILE(pdu.h) */
-/* BINDTOOL_HEADER_FILE_HASH(34ae96025ac87967432c6b7092d1fd60) */
+/* BINDTOOL_HEADER_FILE_HASH(15f56dfddfda75e396a0b32cca7b7b3d) */
/***********************************************************************************/
#include <pybind11/complex.h>
@@ -31,6 +31,15 @@ void bind_pdu(py::module& m)
{
+ py::enum_<::gr::pdu::vector_type>(m, "vector_type")
+ .value("byte_t", ::gr::pdu::byte_t) // 0
+ .value("float_t", ::gr::pdu::float_t) // 1
+ .value("complex_t", ::gr::pdu::complex_t) // 2
+ .export_values();
+
+ py::implicitly_convertible<int, ::gr::pdu::vector_type>();
+
+
m.def("PMTCONSTSTR__data", &::gr::pdu::PMTCONSTSTR__data, D(PMTCONSTSTR__data));
@@ -43,5 +52,27 @@ void bind_pdu(py::module& m)
m.def("PMTCONSTSTR__msg", &::gr::pdu::PMTCONSTSTR__msg, D(PMTCONSTSTR__msg));
- m.def("PMTCONSTSTR__pdu", &::gr::pdu::PMTCONSTSTR__pdus, D(PMTCONSTSTR__pdus));
+ m.def("PMTCONSTSTR__pdus", &::gr::pdu::PMTCONSTSTR__pdus, D(PMTCONSTSTR__pdus));
+
+
+ m.def("itemsize", &::gr::pdu::itemsize, py::arg("type"), D(itemsize));
+
+
+ m.def("type_matches",
+ &::gr::pdu::type_matches,
+ py::arg("type"),
+ py::arg("v"),
+ D(type_matches));
+
+
+ m.def("make_pdu_vector",
+ &::gr::pdu::make_pdu_vector,
+ py::arg("type"),
+ py::arg("buf"),
+ py::arg("items"),
+ D(make_pdu_vector));
+
+
+ m.def(
+ "type_from_pmt", &::gr::pdu::type_from_pmt, py::arg("vector"), D(type_from_pmt));
}
diff --git a/gr-pdu/python/pdu/bindings/pdu_remove_python.cc b/gr-pdu/python/pdu/bindings/pdu_remove_python.cc
new file mode 100644
index 0000000000..47755e5cdf
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/pdu_remove_python.cc
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(pdu_remove.h) */
+/* BINDTOOL_HEADER_FILE_HASH(2b26df98561ff8f787fc8b3f0ea3a82a) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu/pdu_remove.h>
+// pydoc.h is automatically generated in the build directory
+#include <pdu_remove_pydoc.h>
+
+void bind_pdu_remove(py::module& m)
+{
+
+ using pdu_remove = ::gr::pdu::pdu_remove;
+
+
+ py::class_<pdu_remove, gr::block, gr::basic_block, std::shared_ptr<pdu_remove>>(
+ m, "pdu_remove", D(pdu_remove))
+
+ .def(py::init(&pdu_remove::make), py::arg("k"), D(pdu_remove, make))
+
+
+ .def("set_key", &pdu_remove::set_key, py::arg("key"), D(pdu_remove, set_key))
+
+ ;
+}
diff --git a/gr-pdu/python/pdu/bindings/pdu_set_python.cc b/gr-pdu/python/pdu/bindings/pdu_set_python.cc
new file mode 100644
index 0000000000..834ae6a163
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/pdu_set_python.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(pdu_set.h) */
+/* BINDTOOL_HEADER_FILE_HASH(c7fba803e84070656e7898eb601df1f3) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu/pdu_set.h>
+// pydoc.h is automatically generated in the build directory
+#include <pdu_set_pydoc.h>
+
+void bind_pdu_set(py::module& m)
+{
+
+ using pdu_set = ::gr::pdu::pdu_set;
+
+
+ py::class_<pdu_set, gr::block, gr::basic_block, std::shared_ptr<pdu_set>>(
+ m, "pdu_set", D(pdu_set))
+
+ .def(py::init(&pdu_set::make), py::arg("k"), py::arg("v"), D(pdu_set, make))
+
+
+ .def("set_key", &pdu_set::set_key, py::arg("key"), D(pdu_set, set_key))
+
+
+ .def("set_val", &pdu_set::set_val, py::arg("val"), D(pdu_set, set_val))
+
+ ;
+}
diff --git a/gr-pdu/python/pdu/bindings/pdu_to_tagged_stream_python.cc b/gr-pdu/python/pdu/bindings/pdu_to_tagged_stream_python.cc
new file mode 100644
index 0000000000..5b857cad32
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/pdu_to_tagged_stream_python.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(pdu_to_tagged_stream.h) */
+/* BINDTOOL_HEADER_FILE_HASH(5a0731bc34a2a12add1e9909e2b27b9f) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu/pdu_to_tagged_stream.h>
+// pydoc.h is automatically generated in the build directory
+#include <pdu_to_tagged_stream_pydoc.h>
+
+void bind_pdu_to_tagged_stream(py::module& m)
+{
+
+ using pdu_to_tagged_stream = ::gr::pdu::pdu_to_tagged_stream;
+
+
+ py::class_<pdu_to_tagged_stream,
+ gr::tagged_stream_block,
+ gr::block,
+ gr::basic_block,
+ std::shared_ptr<pdu_to_tagged_stream>>(
+ m, "pdu_to_tagged_stream", D(pdu_to_tagged_stream))
+
+ .def(py::init(&pdu_to_tagged_stream::make),
+ py::arg("type"),
+ py::arg("lengthtagname") = "packet_len",
+ D(pdu_to_tagged_stream, make))
+
+
+ ;
+}
diff --git a/gr-pdu/python/pdu/bindings/python_bindings.cc b/gr-pdu/python/pdu/bindings/python_bindings.cc
index 712021b8d1..7530b7a467 100644
--- a/gr-pdu/python/pdu/bindings/python_bindings.cc
+++ b/gr-pdu/python/pdu/bindings/python_bindings.cc
@@ -15,8 +15,14 @@
namespace py = pybind11;
-void bind_pdu_split(py::module&);
void bind_pdu(py::module&);
+void bind_pdu_filter(py::module&);
+void bind_pdu_remove(py::module&);
+void bind_pdu_set(py::module&);
+void bind_pdu_split(py::module&);
+void bind_pdu_to_tagged_stream(py::module&);
+void bind_random_pdu(py::module&);
+void bind_tagged_stream_to_pdu(py::module&);
// We need this hack because import_array() returns NULL
// for newer Python versions.
@@ -37,6 +43,12 @@ PYBIND11_MODULE(pdu_python, m)
// Allow access to base block methods
py::module::import("gnuradio.gr");
- bind_pdu_split(m);
bind_pdu(m);
+ bind_pdu_filter(m);
+ bind_pdu_remove(m);
+ bind_pdu_set(m);
+ bind_pdu_split(m);
+ bind_pdu_to_tagged_stream(m);
+ bind_random_pdu(m);
+ bind_tagged_stream_to_pdu(m);
}
diff --git a/gr-pdu/python/pdu/bindings/random_pdu_python.cc b/gr-pdu/python/pdu/bindings/random_pdu_python.cc
new file mode 100644
index 0000000000..20e238a7c4
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/random_pdu_python.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(random_pdu.h) */
+/* BINDTOOL_HEADER_FILE_HASH(0ec9de7a89f30dd5a050547975e7c3d4) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu/random_pdu.h>
+// pydoc.h is automatically generated in the build directory
+#include <random_pdu_pydoc.h>
+
+void bind_random_pdu(py::module& m)
+{
+
+ using random_pdu = ::gr::pdu::random_pdu;
+
+
+ py::class_<random_pdu, gr::block, gr::basic_block, std::shared_ptr<random_pdu>>(
+ m, "random_pdu", D(random_pdu))
+
+ .def(py::init(&random_pdu::make),
+ py::arg("mintime"),
+ py::arg("maxtime"),
+ py::arg("byte_mask") = 255,
+ py::arg("length_modulo") = 1,
+ D(random_pdu, make))
+
+
+ ;
+}
diff --git a/gr-pdu/python/pdu/bindings/tagged_stream_to_pdu_python.cc b/gr-pdu/python/pdu/bindings/tagged_stream_to_pdu_python.cc
new file mode 100644
index 0000000000..047f25197a
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/tagged_stream_to_pdu_python.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(tagged_stream_to_pdu.h) */
+/* BINDTOOL_HEADER_FILE_HASH(c3df8858e8b5d77e0d10d762db5238ff) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu/tagged_stream_to_pdu.h>
+// pydoc.h is automatically generated in the build directory
+#include <tagged_stream_to_pdu_pydoc.h>
+
+void bind_tagged_stream_to_pdu(py::module& m)
+{
+
+ using tagged_stream_to_pdu = ::gr::pdu::tagged_stream_to_pdu;
+
+
+ py::class_<tagged_stream_to_pdu,
+ gr::tagged_stream_block,
+ gr::block,
+ gr::basic_block,
+ std::shared_ptr<tagged_stream_to_pdu>>(
+ m, "tagged_stream_to_pdu", D(tagged_stream_to_pdu))
+
+ .def(py::init(&tagged_stream_to_pdu::make),
+ py::arg("type"),
+ py::arg("lengthtagname") = "packet_len",
+ D(tagged_stream_to_pdu, make))
+
+
+ ;
+}
diff --git a/gr-pdu/python/pdu/qa_pdu.py b/gr-pdu/python/pdu/qa_pdu.py
new file mode 100644
index 0000000000..504f151089
--- /dev/null
+++ b/gr-pdu/python/pdu/qa_pdu.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+#
+
+
+from gnuradio import gr, gr_unittest, blocks, pdu
+import pmt
+import time
+
+
+class test_pdu(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ # Just run some data through and make sure it doesn't puke.
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+
+ src = pdu.pdu_to_tagged_stream(pdu.byte_t)
+ snk3 = pdu.tagged_stream_to_pdu(pdu.byte_t)
+ snk2 = blocks.vector_sink_b()
+ snk = blocks.tag_debug(1, "test")
+ snk.set_display(False)
+
+ dbg = blocks.message_debug()
+
+ # Test that the right number of ports exist.
+ pi = snk3.message_ports_in()
+ po = snk3.message_ports_out()
+ # system port is defined automatically
+ self.assertEqual(pmt.length(pi), 1)
+ self.assertEqual(pmt.length(po), 1)
+
+ self.tb.connect(src, snk)
+ self.tb.connect(src, snk2)
+ self.tb.connect(src, snk3)
+ self.tb.msg_connect(snk3, "pdus", dbg, "store")
+
+ # make our reference and message pmts
+ port = pmt.intern("pdus")
+ msg = pmt.cons(pmt.PMT_NIL, pmt.make_u8vector(16, 0xFF))
+
+ # post the message
+ src.to_basic_block()._post(port, msg)
+ src.to_basic_block()._post(
+ pmt.intern("system"), pmt.cons(
+ pmt.intern("done"), pmt.from_long(1)))
+
+ self.tb.start()
+ self.tb.wait()
+
+ # Get the vector of data from the vector sink
+ result_data = snk2.data()
+
+ # Get the vector of data from the message sink
+ # Convert the message PMT as a pair into its vector
+ result_msg = dbg.get_message(0)
+ msg_vec = pmt.cdr(result_msg)
+ # pmt.print(msg_vec)
+
+ # Convert the PMT vector into a Python list
+ msg_data = []
+ for i in range(16):
+ msg_data.append(pmt.u8vector_ref(msg_vec, i))
+
+ actual_data = 16 * [0xFF, ]
+ self.assertEqual(actual_data, list(result_data))
+ self.assertEqual(actual_data, msg_data)
+
+ def test_001(self):
+ # Test the overflow buffer in pdu_to_tagged_stream
+ src_data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
+ src = pdu.pdu_to_tagged_stream(pdu.float_t)
+ snk = blocks.vector_sink_f()
+
+ self.tb.connect(src, snk)
+ port = pmt.intern("pdus")
+
+ msg = pmt.cons(pmt.PMT_NIL, pmt.init_f32vector(10, src_data))
+ src.to_basic_block()._post(port, msg)
+ src.to_basic_block()._post(
+ pmt.intern("system"), pmt.cons(
+ pmt.intern("done"), pmt.from_long(1)))
+
+ self.tb.start()
+ self.tb.wait()
+
+ self.assertEqual(src_data, list(snk.data()))
+
+ def test_002_tags_plus_data(self):
+ packet_len = 16
+ src_data = list(range(packet_len))
+ tag1 = gr.tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol('spam')
+ tag1.value = pmt.from_long(23)
+ tag2 = gr.tag_t()
+ tag2.offset = 10 # Must be < packet_len
+ tag2.key = pmt.string_to_symbol('eggs')
+ tag2.value = pmt.from_long(42)
+ src = blocks.vector_source_f(src_data, tags=(tag1, tag2))
+ s2ts = blocks.stream_to_tagged_stream(
+ gr.sizeof_float,
+ vlen=1,
+ packet_len=packet_len,
+ len_tag_key="packet_len")
+ ts2pdu = pdu.tagged_stream_to_pdu(pdu.float_t, "packet_len")
+ dbg = blocks.message_debug()
+ self.tb.connect(src, s2ts, ts2pdu)
+ self.tb.msg_connect(ts2pdu, "pdus", dbg, "store")
+ self.tb.start()
+ self.tb.wait()
+ result_msg = dbg.get_message(0)
+ metadata = pmt.to_python(pmt.car(result_msg))
+ vector = pmt.f32vector_elements(pmt.cdr(result_msg))
+ self.assertEqual(metadata, {'eggs': 42, 'spam': 23})
+ self.assertFloatTuplesAlmostEqual(tuple(vector), src_data)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pdu)
diff --git a/gr-pdu/python/pdu/qa_pdu_split.py b/gr-pdu/python/pdu/qa_pdu_split.py
index 77f34936d9..76b60499a7 100644
--- a/gr-pdu/python/pdu/qa_pdu_split.py
+++ b/gr-pdu/python/pdu/qa_pdu_split.py
@@ -9,18 +9,10 @@
#
-from gnuradio import gr, gr_unittest
-from gnuradio import blocks
+from gnuradio import gr, gr_unittest, blocks, pdu
import pmt
import time
-try:
- from gnuradio import pdu
-except ImportError:
- import os
- import sys
- dirname, filename = os.path.split(os.path.abspath(__file__))
- sys.path.append(os.path.join(dirname, "bindings"))
- from gnuradio import pdu
+
class qa_pdu_split (gr_unittest.TestCase):
@@ -36,7 +28,7 @@ class qa_pdu_split (gr_unittest.TestCase):
d2 = blocks.message_debug()
self.tb.msg_connect((split, 'dict'), (d1, 'store'))
- self.tb.msg_connect((split, 'data'), (d2, 'store'))
+ self.tb.msg_connect((split, 'vec'), (d2, 'store'))
in_meta1 = pmt.dict_add(pmt.make_dict(), pmt.intern('num'), pmt.from_long(4))
in_meta2 = pmt.dict_add(pmt.make_dict(), pmt.intern('n'), pmt.from_long(99))
@@ -63,9 +55,9 @@ class qa_pdu_split (gr_unittest.TestCase):
split = pdu.pdu_split(True)
d1 = blocks.message_debug()
d2 = blocks.message_debug()
-
+
self.tb.msg_connect((split, 'dict'), (d1, 'store'))
- self.tb.msg_connect((split, 'data'), (d2, 'store'))
+ self.tb.msg_connect((split, 'vec'), (d2, 'store'))
in_meta1 = pmt.dict_add(pmt.make_dict(), pmt.intern('num'), pmt.from_long(4))
in_meta2 = pmt.dict_add(pmt.make_dict(), pmt.intern('n'), pmt.from_long(99))