GNU Radio 3.6.3 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2012 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #ifndef INCLUDED_GR_SOCKET_PDU_H 00024 #define INCLUDED_GR_SOCKET_PDU_H 00025 00026 #include <gr_core_api.h> 00027 #include <gr_sync_block.h> 00028 #include <gr_message.h> 00029 #include <gr_msg_queue.h> 00030 #include <gr_stream_pdu_base.h> 00031 #include <boost/array.hpp> 00032 #include <boost/asio.hpp> 00033 00034 class gr_socket_pdu; 00035 typedef boost::shared_ptr<gr_socket_pdu> gr_socket_pdu_sptr; 00036 00037 GR_CORE_API gr_socket_pdu_sptr gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); 00038 00039 class tcp_connection 00040 : public boost::enable_shared_from_this<tcp_connection> 00041 { 00042 public: 00043 typedef boost::shared_ptr<tcp_connection> pointer; 00044 gr_socket_pdu *d_block; 00045 boost::array<char, 10000> buf; 00046 00047 static pointer create(boost::asio::io_service& io_service) 00048 { 00049 return pointer(new tcp_connection(io_service)); 00050 } 00051 00052 boost::asio::ip::tcp::socket& socket() 00053 { 00054 return socket_; 00055 } 00056 00057 void start(gr_socket_pdu* parent) 00058 { 00059 d_block = parent; 00060 // message_ = "connected to gr_socket_pdu\n"; 00061 // boost::asio::async_write(socket_, boost::asio::buffer(message_), 00062 // boost::bind(&tcp_connection::handle_write, shared_from_this(), 00063 // boost::asio::placeholders::error, 00064 // boost::asio::placeholders::bytes_transferred)); 00065 00066 socket_.async_read_some( 00067 boost::asio::buffer(buf), 00068 boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 00069 } 00070 void send(pmt::pmt_t vector){ 00071 size_t len = pmt::pmt_length(vector); 00072 size_t offset(0); 00073 boost::array<char, 10000> txbuf; 00074 memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); 00075 boost::asio::async_write(socket_, boost::asio::buffer(txbuf, len), 00076 boost::bind(&tcp_connection::handle_write, shared_from_this(), 00077 boost::asio::placeholders::error, 00078 boost::asio::placeholders::bytes_transferred)); 00079 } 00080 00081 ~tcp_connection(){ 00082 // std::cout << "tcp_connection destroyed\n"; 00083 } 00084 00085 private: 00086 tcp_connection(boost::asio::io_service& io_service) 00087 : socket_(io_service) 00088 { 00089 } 00090 00091 void handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred); 00092 00093 void handle_write(const boost::system::error_code& /*error*/, 00094 size_t /*bytes_transferred*/) 00095 { 00096 } 00097 00098 boost::asio::ip::tcp::socket socket_; 00099 std::string message_; 00100 }; 00101 00102 00103 /*! 00104 * \brief Gather received items into messages and insert into msgq 00105 * \ingroup sink_blk 00106 */ 00107 class GR_CORE_API gr_socket_pdu : public gr_stream_pdu_base 00108 { 00109 private: 00110 friend GR_CORE_API gr_socket_pdu_sptr 00111 gr_make_socket_pdu(std::string type, std::string addr, std::string port, int MTU); 00112 00113 boost::asio::io_service _io_service; 00114 00115 boost::array<char, 10000> rxbuf; 00116 00117 // tcp specific 00118 boost::asio::ip::tcp::endpoint _tcp_endpoint; 00119 00120 // specific to tcp server 00121 boost::shared_ptr<boost::asio::ip::tcp::acceptor> _acceptor_tcp; 00122 std::vector<tcp_connection::pointer> d_tcp_connections; 00123 void tcp_server_send(pmt::pmt_t msg); 00124 void tcp_client_send(pmt::pmt_t msg); 00125 void udp_send(pmt::pmt_t msg); 00126 00127 // specific to tcp client 00128 boost::shared_ptr<boost::asio::ip::tcp::socket> _tcp_socket; 00129 00130 // specific to udp client/server 00131 boost::asio::ip::udp::endpoint _udp_endpoint; 00132 boost::asio::ip::udp::endpoint _udp_endpoint_other; 00133 boost::shared_ptr<boost::asio::ip::udp::socket> _udp_socket; 00134 00135 void handle_receive(const boost::system::error_code& error, std::size_t ){ 00136 } 00137 00138 void start_tcp_accept(){ 00139 tcp_connection::pointer new_connection = 00140 tcp_connection::create(_acceptor_tcp->get_io_service()); 00141 00142 _acceptor_tcp->async_accept(new_connection->socket(), 00143 boost::bind(&gr_socket_pdu::handle_tcp_accept, this, new_connection, 00144 boost::asio::placeholders::error)); 00145 } 00146 00147 void handle_tcp_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error){ 00148 if (!error) 00149 { 00150 new_connection->start(this); 00151 d_tcp_connections.push_back(new_connection); 00152 start_tcp_accept(); 00153 } else { 00154 std::cout << error << std::endl; 00155 } 00156 } 00157 00158 void run_io_service(){ 00159 _io_service.run(); 00160 } 00161 00162 void handle_udp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ 00163 if(!error){ 00164 pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); 00165 pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); 00166 00167 message_port_pub( pmt::mp("pdus"), pdu ); 00168 00169 _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, 00170 boost::bind(&gr_socket_pdu::handle_udp_read, this, 00171 boost::asio::placeholders::error, 00172 boost::asio::placeholders::bytes_transferred)); 00173 } else { 00174 throw boost::system::system_error(error); 00175 // std::cout << "error occurred\n"; 00176 } 00177 } 00178 void handle_tcp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ 00179 if(!error) 00180 { 00181 pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); 00182 pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); 00183 00184 message_port_pub( pmt::mp("pdus"), pdu ); 00185 00186 _tcp_socket->async_read_some( 00187 boost::asio::buffer(rxbuf), 00188 boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 00189 00190 } else { 00191 //std::cout << "error occurred\n"; 00192 throw boost::system::system_error(error); 00193 } 00194 } 00195 00196 protected: 00197 gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); 00198 public: 00199 ~gr_socket_pdu () {} 00200 }; 00201 00202 #endif /* INCLUDED_GR_TUNTAP_PDU_H */