hproselet/udp.hpp

74 lines
2.3 KiB
C++
Raw Permalink Normal View History

2022-12-15 02:05:06 +00:00
#ifndef _UDP_HPP_
#define _UDP_HPP_
#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE
#endif
#include <asio.hpp>
#include <type_traits>
#include "buffers.hpp"
using asio::ip::udp;
using udp_receiver = std::function<size_t(StaticBuffer&, size_t)>;
using udp_sender = std::function<void(StaticBuffer&, size_t)>;
using udp_cb_received = std::function<void(const udp_receiver&, const udp_sender&, size_t)>;
class UDPPeer : public std::enable_shared_from_this<UDPPeer> {
public:
UDPPeer(asio::io_context& ctx, short port) : socket(ctx, udp::endpoint(udp::v4(), port)) {}
UDPPeer(asio::io_context& ctx) : socket(ctx, udp::v4()) {}
void StartReceive() {
if(started)
return;
started = true;
_ReceiveFrom();
}
void StopReceive() {
if(!started)
return;
started = false;
socket.cancel();
}
void SendTo(const char* addr, uint16_t port, StaticBuffer& buf, size_t length) {
udp::endpoint remote_peer(asio::ip::make_address_v4(addr), port);
auto abuf = asio::buffer(buf.Data(), length);
socket.async_send_to(abuf, remote_peer, [obuf = std::move(buf)](std::error_code ec, size_t){});
}
UDPPeer& SetReceivedCallback(udp_cb_received cb) { callback = cb; return *this; }
protected:
void _ReceiveFrom() {
socket.async_wait(udp::socket::wait_read, [this, self = this->shared_from_this()](std::error_code ec){
if(!ec) {
size_t reserve_size = socket.available();
if(callback) {
auto receiver = [this](StaticBuffer& buf, size_t length) -> size_t {
return socket.receive_from(asio::buffer(buf.Data(), length), remote);
};
auto sender = [this](StaticBuffer& buf, size_t length) {
auto abuf = asio::buffer(buf.Data(), length);
socket.async_send_to(abuf, remote, [obuf = std::move(buf)](std::error_code ec, size_t){});
};
callback(receiver, sender, reserve_size);
}
}
if(started)
_ReceiveFrom();
});
}
bool started = false;
udp_cb_received callback;
udp::socket socket;
udp::endpoint remote;
};
#endif