37 namespace bi = ba::ip;
56 bi::udp::endpoint
const&
endpoint()
const {
return locus; }
68 static uint32_t
futureFromEpoch(std::chrono::seconds _sec) {
return static_cast<uint32_t
>(std::chrono::duration_cast<std::chrono::seconds>((std::chrono::system_clock::now() + _sec).time_since_epoch()).
count()); }
69 static uint32_t
secondsSinceEpoch() {
return static_cast<uint32_t
>(std::chrono::duration_cast<std::chrono::seconds>((std::chrono::system_clock::now()).time_since_epoch()).
count()); }
75 virtual uint8_t packetType()
const = 0;
77 virtual void streamRLP(
RLPStream&)
const = 0;
87 virtual void disconnect() = 0;
106 template <
typename Handler,
unsigned MaxDatagramSize>
110 enum { maxDatagramSize = MaxDatagramSize };
111 static_assert((
unsigned)maxDatagramSize < 65507u,
"UDP datagrams cannot be larger than 65507 bytes");
114 UDPSocket(ba::io_service& _io,
UDPSocketEvents& _host, bi::udp::endpoint _endpoint): m_host(_host), m_endpoint(_endpoint), m_socket(_io) { m_started.store(
false); m_closed.store(
true); };
117 UDPSocket(ba::io_service& _io,
UDPSocketEvents& _host,
unsigned _port): m_host(_host), m_endpoint(bi::udp::v4(), _port), m_socket(_io) { m_started.store(
false); m_closed.store(
true); };
130 void disconnect() { disconnectWithError(boost::asio::error::connection_reset); }
137 void disconnectWithError(boost::system::error_code _ec);
155 template <
typename Handler,
unsigned MaxDatagramSize>
159 if (!m_started.compare_exchange_strong(expect,
true))
162 m_socket.open(bi::udp::v4());
165 m_socket.bind(m_endpoint);
169 m_socket.bind(bi::udp::endpoint(bi::udp::v4(), m_endpoint.port()));
180 template <
typename Handler,
unsigned MaxDatagramSize>
187 m_sendQ.push_back(_datagram);
188 if (m_sendQ.size() == 1)
194 template <
typename Handler,
unsigned MaxDatagramSize>
201 m_socket.async_receive_from(boost::asio::buffer(m_recvData), m_recvEndpoint, [
this,
self](boost::system::error_code _ec,
size_t _len)
204 return disconnectWithError(_ec);
206 if (_ec != boost::system::errc::success)
207 clog(
NetWarn) <<
"Receiving UDP message failed. " << _ec.value() <<
":" << _ec.message();
210 m_host.onReceived(
this, m_recvEndpoint,
bytesConstRef(m_recvData.data(), _len));
215 template <
typename Handler,
unsigned MaxDatagramSize>
223 bi::udp::endpoint endpoint(datagram.
endpoint());
224 m_socket.async_send_to(boost::asio::buffer(datagram.
data), endpoint, [
this,
self, endpoint](boost::system::error_code _ec, std::size_t)
227 return disconnectWithError(_ec);
229 if (_ec != boost::system::errc::success)
230 clog(NetWarn) <<
"Failed delivering UDP message. " << _ec.value() <<
":" << _ec.message();
240 template <
typename Handler,
unsigned MaxDatagramSize>
244 if (!m_started && m_closed && !m_socket.is_open() )
250 Guard l(x_socketError);
251 if (m_socketError != boost::system::error_code())
258 bool expected =
true;
259 if (!m_started.compare_exchange_strong(expected,
false))
263 bool wasClosed = m_closed;
267 boost::system::error_code ec;
268 m_socket.shutdown(bi::udp::socket::shutdown_both, ec);
275 m_host.onDisconnected(
this);
bool send(UDPDatagram const &_datagram)
Send datagram.
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
std::deque< UDPDatagram > m_sendQ
Queue for egress data.
UDPSocketEvents & m_host
Interface which owns this socket.
bi::udp::socket m_socket
Boost asio udp socket.
bi::udp::endpoint m_recvEndpoint
Endpoint data was received from.
UDP Interface Handler must implement UDPSocketEvents.
static uint32_t secondsSinceEpoch()
assert(len-trim+(2 *lenIndices)<=WIDTH)
bi::udp::endpoint m_endpoint
Endpoint which we listen to.
void disconnect()
Disconnect socket.
static const char * name()
UDPSocket(ba::io_service &_io, UDPSocketEvents &_host, bi::udp::endpoint _endpoint)
Create socket for specific endpoint.
bool isOpen()
Returns if socket is open.
std::array< byte, maxDatagramSize > m_recvData
Buffer for ingress data.
static const int verbosity
boost::system::error_code m_socketError
Set when shut down due to error.
std::lock_guard< std::mutex > Guard
std::atomic< bool > m_started
Atomically ensure connection is started once. Start cannot occur unless m_started is false...
std::vector< byte > bytes
vector_ref< byte const > bytesConstRef
void disconnectWithError(boost::system::error_code _ec)
Mutex x_socketError
Mutex for error which can be set from host or IO thread.
RLPX Datagram which can be signed.
static uint32_t futureFromEpoch(std::chrono::seconds _sec)
UDPDatagram(bi::udp::endpoint const &_ep, bytes _data)
Signature sign(Secret const &_k, h256 const &_hash)
Returns siganture of message hash.
virtual void onDisconnected(UDPSocketFace *)
RLPXDatagramFace(bi::udp::endpoint const &_ep)
bi::udp::endpoint const & endpoint() const
UDPSocket(ba::io_service &_io, UDPSocketEvents &_host, unsigned _port)
Create socket which listens to all ports.
The default logging channels.
Interface which UDPSocket will implement.
void connect()
Socket will begin listening for and delivering packets.
Class for writing to an RLP bytestream.
UDPDatagram(bi::udp::endpoint const &_ep)
Interface which a UDPSocket's owner must implement.
std::atomic< bool > m_closed
Connection availability.