BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
udp_socket.cpp
Go to the documentation of this file.
2 #include <fc/network/ip.hpp>
3 #include <fc/fwd_impl.hpp>
4 #include <fc/asio.hpp>
5 
6 
7 namespace fc {
8 
10  public:
11  impl():_sock( fc::asio::default_io_service() ){}
12  ~impl(){
13  // _sock.cancel();
14  }
15 
16  boost::asio::ip::udp::socket _sock;
17  };
18 
20  return boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(e.get_address()), e.port() );
21  }
23  return fc::ip::endpoint( e.address().to_v4().to_ulong(), e.port() );
24  }
25 
27  :my( new impl() )
28  {
29  }
30 
32  :my(s.my)
33  {
34  }
35 
37  {
38  try
39  {
40  my->_sock.close(); //close boost socket to make any pending reads run their completion handler
41  }
42  catch (...) //avoid destructor throw and likely this is just happening because socket wasn't open.
43  {
44  }
45  }
46 
47  size_t udp_socket::send_to( const char* buffer, size_t length, const ip::endpoint& to )
48  {
49  try
50  {
51  return my->_sock.send_to( boost::asio::buffer(buffer, length), to_asio_ep(to) );
52  }
53  catch( const boost::system::system_error& e )
54  {
55  if( e.code() != boost::asio::error::would_block )
56  throw;
57  }
58 
59  promise<size_t>::ptr completion_promise = promise<size_t>::create("udp_socket::send_to");
60  my->_sock.async_send_to( boost::asio::buffer(buffer, length), to_asio_ep(to),
61  asio::detail::read_write_handler(completion_promise) );
62 
63  return completion_promise->wait();
64  }
65 
66  size_t udp_socket::send_to( const std::shared_ptr<const char>& buffer, size_t length,
67  const fc::ip::endpoint& to )
68  {
69  try
70  {
71  return my->_sock.send_to( boost::asio::buffer(buffer.get(), length), to_asio_ep(to) );
72  }
73  catch( const boost::system::system_error& e )
74  {
75  if( e.code() != boost::asio::error::would_block )
76  throw;
77  }
78 
79  promise<size_t>::ptr completion_promise = promise<size_t>::create("udp_socket::send_to");
80  my->_sock.async_send_to( boost::asio::buffer(buffer.get(), length), to_asio_ep(to),
81  asio::detail::read_write_handler_with_buffer(completion_promise, buffer) );
82 
83  return completion_promise->wait();
84  }
85 
87  my->_sock.open( boost::asio::ip::udp::v4() );
88  my->_sock.non_blocking(true);
89  }
91  my->_sock.set_option(boost::asio::socket_base::receive_buffer_size(s) );
92  }
94  my->_sock.bind( to_asio_ep(e) );
95  }
96 
97  size_t udp_socket::receive_from( const std::shared_ptr<char>& receive_buffer, size_t receive_buffer_length, fc::ip::endpoint& from )
98  {
99  try
100  {
101  boost::asio::ip::udp::endpoint boost_from_endpoint;
102  size_t bytes_read = my->_sock.receive_from( boost::asio::buffer(receive_buffer.get(), receive_buffer_length),
103  boost_from_endpoint );
104  from = to_fc_ep(boost_from_endpoint);
105  return bytes_read;
106  }
107  catch( const boost::system::system_error& e )
108  {
109  if( e.code() != boost::asio::error::would_block )
110  throw;
111  }
112 
113  boost::asio::ip::udp::endpoint boost_from_endpoint;
114  promise<size_t>::ptr completion_promise = promise<size_t>::create("udp_socket::receive_from");
115  my->_sock.async_receive_from( boost::asio::buffer(receive_buffer.get(), receive_buffer_length),
116  boost_from_endpoint,
117  asio::detail::read_write_handler_with_buffer(completion_promise, receive_buffer) );
118  size_t bytes_read = completion_promise->wait();
119  from = to_fc_ep(boost_from_endpoint);
120  return bytes_read;
121  }
122 
123  size_t udp_socket::receive_from( char* receive_buffer, size_t receive_buffer_length, fc::ip::endpoint& from )
124  {
125  try
126  {
127  boost::asio::ip::udp::endpoint boost_from_endpoint;
128  size_t bytes_read = my->_sock.receive_from( boost::asio::buffer(receive_buffer, receive_buffer_length),
129  boost_from_endpoint );
130  from = to_fc_ep(boost_from_endpoint);
131  return bytes_read;
132  }
133  catch( const boost::system::system_error& e )
134  {
135  if( e.code() != boost::asio::error::would_block )
136  throw;
137  }
138 
139  boost::asio::ip::udp::endpoint boost_from_endpoint;
140  promise<size_t>::ptr completion_promise = promise<size_t>::create("udp_socket::receive_from");
141  my->_sock.async_receive_from( boost::asio::buffer(receive_buffer, receive_buffer_length), boost_from_endpoint,
142  asio::detail::read_write_handler(completion_promise) );
143  size_t bytes_read = completion_promise->wait();
144  from = to_fc_ep(boost_from_endpoint);
145  return bytes_read;
146  }
147 
149  //my->_sock.cancel();
150  my->_sock.close();
151  }
152 
154  return to_fc_ep( my->_sock.local_endpoint() );
155  }
157  my->_sock.connect( to_asio_ep(e) );
158  }
159 
161  {
162  my->_sock.set_option( boost::asio::ip::multicast::enable_loopback(s) );
163  }
165  {
166  my->_sock.set_option( boost::asio::ip::udp::socket::reuse_address(s) );
167  }
169  {
170  my->_sock.set_option( boost::asio::ip::multicast::join_group( boost::asio::ip::address_v4(a) ) );
171  }
172 
173 }
boost::asio::ip::udp::socket _sock
Definition: udp_socket.cpp:16
static ptr create(const char *desc FC_TASK_NAME_DEFAULT_ARG)
Definition: future.hpp:114
void set_receive_buffer_size(size_t s)
Definition: udp_socket.cpp:90
fc::ip::endpoint to_fc_ep(const boost::asio::ip::udp::endpoint &e)
Definition: udp_socket.cpp:22
size_t receive_from(char *b, size_t l, fc::ip::endpoint &from)
Definition: udp_socket.cpp:123
const address & get_address() const
Definition: ip.cpp:72
boost::asio::ip::udp::endpoint to_asio_ep(const fc::ip::endpoint &e)
Definition: udp_socket.cpp:19
const T & wait(const microseconds &timeout=microseconds::maximum())
Definition: future.hpp:127
uint16_t port() const
Definition: ip.cpp:71
void connect(const fc::ip::endpoint &e)
Definition: udp_socket.cpp:156
void set_multicast_enable_loopback(bool)
Definition: udp_socket.cpp:160
boost::asio::ip::tcp::endpoint endpoint
Definition: asio.hpp:240
void bind(const fc::ip::endpoint &)
Definition: udp_socket.cpp:93
size_t send_to(const char *b, size_t l, const fc::ip::endpoint &to)
Definition: udp_socket.cpp:47
fc::ip::endpoint local_endpoint() const
Definition: udp_socket.cpp:153
void set_reuse_address(bool)
Definition: udp_socket.cpp:164
boost::asio::io_service & default_io_service()
Definition: asio.cpp:182
Definition: api.hpp:15
void join_multicast_group(const fc::ip::address &a)
Definition: udp_socket.cpp:168