diff options
author | Johnathan Corgan <johnathan@corganlabs.com> | 2013-02-28 09:44:24 -0800 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2013-02-28 09:51:32 -0800 |
commit | 51c02f87a08efa4e679630771ec7dd0605e4986a (patch) | |
tree | 3201074186d887beb4db9d9f40843ea081891573 | |
parent | c4edfc69a1e2e5b6800d00a2436fb3c8d5ef3233 (diff) |
blocks: added gr::blocks::socket_pdu
-rw-r--r-- | gr-blocks/grc/blocks_block_tree.xml | 1 | ||||
-rw-r--r-- | gr-blocks/grc/blocks_socket_pdu.xml | 62 | ||||
-rw-r--r-- | gr-blocks/include/blocks/CMakeLists.txt | 3 | ||||
-rw-r--r-- | gr-blocks/include/blocks/socket_pdu.h | 53 | ||||
-rw-r--r-- | gr-blocks/lib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | gr-blocks/lib/socket_pdu_impl.cc | 198 | ||||
-rw-r--r-- | gr-blocks/lib/socket_pdu_impl.h | 69 | ||||
-rw-r--r-- | gr-blocks/lib/tcp_connection.cc | 87 | ||||
-rw-r--r-- | gr-blocks/lib/tcp_connection.h | 60 | ||||
-rw-r--r-- | gr-blocks/swig/blocks_swig.i | 3 |
10 files changed, 537 insertions, 1 deletions
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml index 2e05c87f04..a2658d1466 100644 --- a/gr-blocks/grc/blocks_block_tree.xml +++ b/gr-blocks/grc/blocks_block_tree.xml @@ -116,5 +116,6 @@ <cat> <name>Networking</name> <block>blocks_tuntap_pdu</block> + <block>blocks_socket_pdu</block> </cat> </cat> diff --git a/gr-blocks/grc/blocks_socket_pdu.xml b/gr-blocks/grc/blocks_socket_pdu.xml new file mode 100644 index 0000000000..1e897cfc4b --- /dev/null +++ b/gr-blocks/grc/blocks_socket_pdu.xml @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Socket PDU Message source/sink +################################################### + --> +<block> + <name>Socket PDU</name> + <key>blocks_socket_pdu</key> + <import>from gnuradio import blocks</import> + <make>blocks.socket_pdu($type, $host, $port, $mtu)</make> + <param> + <name>Type</name> + <key>type</key> + <value>TCP_SERVER</value> + <type>enum</type> + <option> + <name>TCP Server</name> + <key>"TCP_SERVER"</key> + </option> + <option> + <name>TCP Client</name> + <key>"TCP_CLIENT"</key> + </option> + <option> + <name>UDP Server</name> + <key>"UDP_SERVER"</key> + </option> + <option> + <name>UDP Client</name> + <key>"UDP_CLIENT"</key> + </option> + </param> + <param> + <name>Host</name> + <key>host</key> + <value></value> + <type>string</type> + </param> + <param> + <name>Port</name> + <key>port</key> + <value>52001</value> + <type>string</type> + </param> + <param> + <name>MTU</name> + <key>mtu</key> + <value>10000</value> + <type>int</type> + </param> + <sink> + <name>pdus</name> + <type>message</type> + <optional>1</optional> + </sink> + <source> + <name>pdus</name> + <type>message</type> + <optional>1</optional> + </source> +</block> diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt index 48e399d065..cea725d360 100644 --- a/gr-blocks/include/blocks/CMakeLists.txt +++ b/gr-blocks/include/blocks/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -134,6 +134,7 @@ install(FILES rms_ff.h short_to_char.h short_to_float.h + socket_pdu.h stream_mux.h stream_to_streams.h stream_to_vector.h diff --git a/gr-blocks/include/blocks/socket_pdu.h b/gr-blocks/include/blocks/socket_pdu.h new file mode 100644 index 0000000000..1a67f8358c --- /dev/null +++ b/gr-blocks/include/blocks/socket_pdu.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_BLOCKS_SOCKET_PDU_H +#define INCLUDED_BLOCKS_SOCKET_PDU_H + +#include <blocks/api.h> +#include <gr_block.h> + +namespace gr { + namespace blocks { + + /*! + * \brief Creates socket interface and translates traffic to PDUs + * \ingroup net_blk + */ + class BLOCKS_API socket_pdu : virtual public gr_block + { + public: + // gr::blocks::socket_pdu::sptr + typedef boost::shared_ptr<socket_pdu> sptr; + + /*! + * \brief Construct a SOCKET PDU interface + * \param dev Device name to create + * \param MTU Maximum Transmission Unit size + */ + static sptr make(std::string type, std::string addr, std::string port, int MTU=10000); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_BLOCKS_SOCKET_PDU_H */ diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index 28158ab593..17068f472d 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -173,6 +173,7 @@ list(APPEND gr_blocks_sources rms_ff_impl.cc short_to_char_impl.cc short_to_float_impl.cc + socket_pdu_impl.cc stream_mux_impl.cc stream_pdu_base.cc stream_to_streams_impl.cc @@ -183,6 +184,7 @@ list(APPEND gr_blocks_sources threshold_ff_impl.cc throttle_impl.cc transcendental_impl.cc + tcp_connection.cc tuntap_pdu_impl.cc uchar_array_to_float.cc uchar_to_float_impl.cc diff --git a/gr-blocks/lib/socket_pdu_impl.cc b/gr-blocks/lib/socket_pdu_impl.cc new file mode 100644 index 0000000000..0a48c2b9f4 --- /dev/null +++ b/gr-blocks/lib/socket_pdu_impl.cc @@ -0,0 +1,198 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "socket_pdu_impl.h" +#include "tcp_connection.h" +#include <gr_io_signature.h> +#include <gr_pdu.h> + +namespace gr { + namespace blocks { + + socket_pdu::sptr + socket_pdu::make(std::string type, std::string addr, std::string port, int MTU) + { + return gnuradio::get_initial_sptr(new socket_pdu_impl(type, addr, port, MTU)); + } + + socket_pdu_impl::socket_pdu_impl(std::string type, std::string addr, std::string port, int MTU) + : gr_block("socket_pdu", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)) + { + message_port_register_in(PDU_PORT_ID); + message_port_register_out(PDU_PORT_ID); + + 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); + d_tcp_endpoint = *resolver.resolve(query); + } + + 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); + + 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.reset(new 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(PDU_PORT_ID, boost::bind(&socket_pdu_impl::tcp_server_send, this, _1)); + + } + else if (type =="TCP_CLIENT") { + boost::system::error_code error = boost::asio::error::host_not_found; + d_tcp_socket.reset(new boost::asio::ip::tcp::socket(d_io_service)); + d_tcp_socket->connect(d_tcp_endpoint, error); + if (error) + throw boost::system::system_error(error); + + set_msg_handler(PDU_PORT_ID, boost::bind(&socket_pdu_impl::tcp_client_send, this, _1)); + + 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.reset(new 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(PDU_PORT_ID, boost::bind(&socket_pdu_impl::udp_send, this, _1)); + } + else if (type =="UDP_CLIENT") { + d_udp_socket.reset(new 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(PDU_PORT_ID, boost::bind(&socket_pdu_impl::udp_send, this, _1)); + } + else + throw std::runtime_error("gr::blocks:socket_pdu: unknown socket type"); + + d_thread = gruel::thread(boost::bind(&socket_pdu_impl::run_io_service, this)); + d_started = 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::pmt_init_u8vector(bytes_transferred, (const uint8_t *)&d_rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons(pmt::PMT_NIL, vector); + message_port_pub(PDU_PORT_ID, 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() + { + tcp_connection::sptr new_connection = tcp_connection::make(d_acceptor_tcp->get_io_service()); + + 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::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) { + 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::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + d_tcp_socket->send(boost::asio::buffer(txbuf,len)); + } + + void + socket_pdu_impl::udp_send(pmt::pmt_t msg) + { + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + if (d_udp_endpoint_other.address().to_string() != "0.0.0.0") + d_udp_socket->send_to(boost::asio::buffer(txbuf,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::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&d_rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + message_port_pub(PDU_PORT_ID, 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 blocks */ +}/* namespace gr */ diff --git a/gr-blocks/lib/socket_pdu_impl.h b/gr-blocks/lib/socket_pdu_impl.h new file mode 100644 index 0000000000..78602754c7 --- /dev/null +++ b/gr-blocks/lib/socket_pdu_impl.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_BLOCKS_SOCKET_PDU_IMPL_H +#define INCLUDED_BLOCKS_SOCKET_PDU_IMPL_H + +#include <blocks/socket_pdu.h> +#include "stream_pdu_base.h" +#include "tcp_connection.h" + +namespace gr { + namespace blocks { + + class socket_pdu_impl : public socket_pdu, public stream_pdu_base + { + private: + boost::asio::io_service d_io_service; + boost::array<char, 10000> d_rxbuf; + void run_io_service() { d_io_service.run(); } + + // 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); + + // TCP server specific + boost::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 + boost::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; + boost::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); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_BLOCKS_SOCKET_PDU_IMPL_H */ diff --git a/gr-blocks/lib/tcp_connection.cc b/gr-blocks/lib/tcp_connection.cc new file mode 100644 index 0000000000..4ead6442d8 --- /dev/null +++ b/gr-blocks/lib/tcp_connection.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tcp_connection.h" +#include <gr_basic_block.h> +#include <gr_pdu.h> +//#include <boost/asio.hpp> +//#include <boost/bind.hpp> + +namespace gr { + namespace blocks { + + tcp_connection::sptr tcp_connection::make(boost::asio::io_service& io_service) + { + return sptr(new tcp_connection(io_service)); + } + + tcp_connection::tcp_connection(boost::asio::io_service& io_service) + : d_socket(io_service) + { + } + + void + tcp_connection::send(pmt::pmt_t vector) + { + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + boost::asio::async_write(d_socket, boost::asio::buffer(txbuf, len), + boost::bind(&tcp_connection::handle_write, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + void + tcp_connection::start(gr_basic_block *block) + { + d_block = block; + 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) { + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&d_buf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + d_block->message_port_pub(PDU_PORT_ID, 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)); + + } + } + + } /* namespace blocks */ +}/* namespace gr */ diff --git a/gr-blocks/lib/tcp_connection.h b/gr-blocks/lib/tcp_connection.h new file mode 100644 index 0000000000..94755e847a --- /dev/null +++ b/gr-blocks/lib/tcp_connection.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TCP_CONNECTION_H +#define INCLUDED_TCP_CONNECTION_H + +#include <boost/asio.hpp> +#include <gruel/pmt.h> + +class gr_basic_block; + +namespace gr { + namespace blocks { + + class tcp_connection + { + private: + boost::asio::ip::tcp::socket d_socket; + boost::array<char, 10000> d_buf; + std::string d_message; + gr_basic_block *d_block; + + tcp_connection(boost::asio::io_service& io_service); + + public: + typedef boost::shared_ptr<tcp_connection> sptr; + + static sptr make(boost::asio::io_service& io_service); + + boost::asio::ip::tcp::socket& socket() { return d_socket; }; + + void start(gr_basic_block *block); + void send(pmt::pmt_t vector); + void handle_read(const boost::system::error_code& error, size_t bytes_transferred); + void handle_write(const boost::system::error_code& error, size_t bytes_transferred) { } + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_TCP_CONNECTION_H */ diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i index bd57da5348..c5ca221fbe 100644 --- a/gr-blocks/swig/blocks_swig.i +++ b/gr-blocks/swig/blocks_swig.i @@ -113,6 +113,7 @@ #include "blocks/rms_ff.h" #include "blocks/short_to_char.h" #include "blocks/short_to_float.h" +#include "blocks/socket_pdu.h" #include "blocks/stream_mux.h" #include "blocks/stream_to_streams.h" #include "blocks/stream_to_vector.h" @@ -222,6 +223,7 @@ %include "blocks/rms_ff.h" %include "blocks/short_to_char.h" %include "blocks/short_to_float.h" +%include "blocks/socket_pdu.h" %include "blocks/stream_mux.h" %include "blocks/stream_to_streams.h" %include "blocks/stream_to_vector.h" @@ -330,6 +332,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, rms_cf); GR_SWIG_BLOCK_MAGIC2(blocks, rms_ff); GR_SWIG_BLOCK_MAGIC2(blocks, short_to_char); GR_SWIG_BLOCK_MAGIC2(blocks, short_to_float); +GR_SWIG_BLOCK_MAGIC2(blocks, socket_pdu); GR_SWIG_BLOCK_MAGIC2(blocks, stream_mux); GR_SWIG_BLOCK_MAGIC2(blocks, stream_to_streams); GR_SWIG_BLOCK_MAGIC2(blocks, stream_to_vector); |