1
1
Fork 0
mirror of https://github.com/oxen-io/lokinet synced 2023-12-14 06:53:00 +01:00
lokinet/llarp/ev/ev.hpp

889 lines
18 KiB
C++
Raw Normal View History

2018-04-30 15:18:57 +02:00
#ifndef LLARP_EV_HPP
#define LLARP_EV_HPP
2019-10-02 15:06:14 +02:00
#include <net/net_addr.hpp>
2019-01-11 02:19:36 +01:00
#include <ev/ev.h>
2019-02-03 00:12:42 +01:00
#include <util/buffer.hpp>
#include <util/codel.hpp>
2019-09-01 15:26:16 +02:00
#include <util/thread/threading.hpp>
// writev
#ifndef _WIN32
#include <sys/uio.h>
#include <unistd.h>
#endif
#include <algorithm>
#include <deque>
#include <list>
#include <future>
2019-07-31 01:42:13 +02:00
#include <utility>
#ifdef _WIN32
2019-01-11 02:22:21 +01:00
#include <win32/win32_up.h>
#include <win32/win32_upoll.h>
2018-12-14 00:02:41 +01:00
// From the preview SDK, should take a look at that
// periodically in case its definition changes
#define UNIX_PATH_MAX 108
typedef struct sockaddr_un
{
2018-12-14 00:02:41 +01:00
ADDRESS_FAMILY sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
} SOCKADDR_UN, *PSOCKADDR_UN;
2018-12-03 21:37:25 +01:00
#else
2018-12-05 00:45:08 +01:00
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|| (__APPLE__ && __MACH__)
#include <sys/event.h>
#endif
2018-12-03 21:37:25 +01:00
#include <sys/un.h>
#endif
2019-08-22 13:18:05 +02:00
struct llarp_ev_pkt_pipe;
2018-08-15 17:36:34 +02:00
#ifndef MAX_WRITE_QUEUE_SIZE
2018-11-09 15:48:43 +01:00
#define MAX_WRITE_QUEUE_SIZE (1024UL)
2018-08-15 17:36:34 +02:00
#endif
2018-04-30 15:18:57 +02:00
2018-09-06 22:31:58 +02:00
#ifndef EV_READ_BUF_SZ
2018-11-09 15:48:43 +01:00
#define EV_READ_BUF_SZ (4 * 1024UL)
2018-09-06 22:31:58 +02:00
#endif
2018-10-27 20:26:08 +02:00
#ifndef EV_WRITE_BUF_SZ
2018-11-09 15:48:43 +01:00
#define EV_WRITE_BUF_SZ (2 * 1024UL)
2018-10-27 20:26:08 +02:00
#endif
2018-09-06 22:31:58 +02:00
/// do io and reset errno after
static ssize_t
IO(std::function< ssize_t(void) > iofunc)
{
ssize_t ret = iofunc();
#ifndef _WIN32
errno = 0;
#else
WSASetLastError(0);
#endif
return ret;
}
namespace llarp
{
#ifdef _WIN32
struct win32_ev_io
2018-10-29 17:48:36 +01:00
{
2018-10-03 12:40:32 +02:00
struct WriteBuffer
2018-08-15 17:36:34 +02:00
{
2018-10-29 17:48:36 +01:00
llarp_time_t timestamp = 0;
2018-10-03 12:40:32 +02:00
size_t bufsz;
2018-10-31 02:48:41 +01:00
byte_t buf[EV_WRITE_BUF_SZ] = {0};
2018-10-03 12:40:32 +02:00
WriteBuffer() = default;
2018-10-25 14:09:29 +02:00
WriteBuffer(const byte_t* ptr, size_t sz)
2018-10-03 12:40:32 +02:00
{
if(sz <= sizeof(buf))
{
bufsz = sz;
memcpy(buf, ptr, bufsz);
}
else
bufsz = 0;
}
struct GetTime
{
llarp_time_t
operator()(const WriteBuffer& buf) const
2018-10-03 12:40:32 +02:00
{
2018-10-29 17:48:36 +01:00
return buf.timestamp;
2018-10-03 12:40:32 +02:00
}
};
2018-12-03 15:39:30 +01:00
struct GetNow
{
2019-04-08 14:01:52 +02:00
llarp_ev_loop_ptr loop;
GetNow(llarp_ev_loop_ptr l) : loop(l)
2018-12-03 15:39:30 +01:00
{
}
llarp_time_t
operator()() const
{
return llarp_ev_loop_time_now_ms(loop);
}
};
2018-10-03 12:40:32 +02:00
struct PutTime
{
2019-04-08 14:01:52 +02:00
llarp_ev_loop_ptr loop;
PutTime(llarp_ev_loop_ptr l) : loop(l)
{
}
void
operator()(WriteBuffer& buf)
2018-10-03 12:40:32 +02:00
{
2018-10-29 17:48:36 +01:00
buf.timestamp = llarp_ev_loop_time_now_ms(loop);
2018-10-03 12:40:32 +02:00
}
};
struct Compare
{
bool
operator()(const WriteBuffer& left, const WriteBuffer& right) const
{
return left.timestamp < right.timestamp;
}
};
};
using LosslessWriteQueue_t = std::deque< WriteBuffer >;
2018-12-23 14:29:11 +01:00
intptr_t
fd; // Sockets only, fuck UNIX-style reactive IO with a rusty knife
2018-12-23 14:29:11 +01:00
int flags = 0;
win32_ev_io(intptr_t f) : fd(f){};
/// for tcp
2018-12-23 14:29:11 +01:00
win32_ev_io(intptr_t f, LosslessWriteQueue_t* q)
: fd(f), m_BlockingWriteQueue(q)
{
}
virtual void
error()
{
2018-12-14 15:38:37 +01:00
char ebuf[1024];
int err = WSAGetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_NEUTRAL,
ebuf, 1024, nullptr);
llarp::LogError(ebuf);
}
virtual int
2018-12-03 15:39:30 +01:00
read(byte_t* buf, size_t sz) = 0;
virtual int
sendto(const sockaddr* dst, const void* data, size_t sz)
{
UNREFERENCED_PARAMETER(dst);
UNREFERENCED_PARAMETER(data);
UNREFERENCED_PARAMETER(sz);
return -1;
};
2018-10-25 14:39:32 +02:00
/// return false if we want to deregister and remove ourselves
virtual bool
tick()
{
return true;
};
/// used for tun interface and tcp conn
2018-10-27 22:02:37 +02:00
virtual ssize_t
do_write(void* data, size_t sz)
{
return uwrite(fd, (char*)data, sz);
}
bool
queue_write(const byte_t* buf, size_t sz)
{
if(m_BlockingWriteQueue)
{
m_BlockingWriteQueue->emplace_back(buf, sz);
return true;
}
else
return false;
}
virtual void
flush_write()
{
flush_write_buffers(0);
}
/// called in event loop when fd is ready for writing
/// requeues anything not written
/// this assumes fd is set to non blocking
virtual void
flush_write_buffers(size_t amount)
{
2018-12-23 14:29:11 +01:00
if(m_BlockingWriteQueue)
{
if(amount)
{
while(amount && m_BlockingWriteQueue->size())
{
auto& itr = m_BlockingWriteQueue->front();
ssize_t result = do_write(itr.buf, std::min(amount, itr.bufsz));
if(result == -1)
return;
ssize_t dlt = itr.bufsz - result;
if(dlt > 0)
{
// queue remaining to front of queue
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
m_BlockingWriteQueue->pop_front();
m_BlockingWriteQueue->push_front(buff);
// TODO: errno?
return;
}
m_BlockingWriteQueue->pop_front();
amount -= result;
}
}
else
{
// write buffers
while(m_BlockingWriteQueue->size())
{
auto& itr = m_BlockingWriteQueue->front();
ssize_t result = do_write(itr.buf, itr.bufsz);
if(result == -1)
return;
ssize_t dlt = itr.bufsz - result;
if(dlt > 0)
{
// queue remaining to front of queue
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
m_BlockingWriteQueue->pop_front();
m_BlockingWriteQueue->push_front(buff);
// TODO: errno?
return;
}
m_BlockingWriteQueue->pop_front();
int wsaerr = WSAGetLastError();
if(wsaerr == WSA_IO_PENDING || wsaerr == WSAEWOULDBLOCK)
{
WSASetLastError(0);
return;
}
}
}
}
/// reset errno
WSASetLastError(0);
}
std::unique_ptr< LosslessWriteQueue_t > m_BlockingWriteQueue;
virtual ~win32_ev_io()
{
uclose(fd);
2018-10-03 12:40:32 +02:00
};
};
2018-12-14 15:38:37 +01:00
#else
struct posix_ev_io
{
struct WriteBuffer
{
llarp_time_t timestamp = 0;
size_t bufsz;
byte_t buf[EV_WRITE_BUF_SZ];
WriteBuffer() = default;
WriteBuffer(const byte_t* ptr, size_t sz)
{
if(sz <= sizeof(buf))
{
bufsz = sz;
memcpy(buf, ptr, bufsz);
}
else
bufsz = 0;
}
struct GetTime
{
llarp_time_t
2019-04-26 01:21:19 +02:00
operator()(const WriteBuffer& writebuf) const
{
2019-04-26 01:21:19 +02:00
return writebuf.timestamp;
}
};
struct GetNow
{
2019-04-08 14:01:52 +02:00
llarp_ev_loop_ptr loop;
2019-07-31 01:42:13 +02:00
GetNow(llarp_ev_loop_ptr l) : loop(std::move(l))
{
}
llarp_time_t
operator()() const
{
return llarp_ev_loop_time_now_ms(loop);
}
};
struct PutTime
{
2019-04-08 14:01:52 +02:00
llarp_ev_loop_ptr loop;
2019-07-31 01:42:13 +02:00
PutTime(llarp_ev_loop_ptr l) : loop(std::move(l))
{
}
void
2019-04-26 01:21:19 +02:00
operator()(WriteBuffer& writebuf)
{
2019-04-26 01:21:19 +02:00
writebuf.timestamp = llarp_ev_loop_time_now_ms(loop);
}
};
struct Compare
{
bool
operator()(const WriteBuffer& left, const WriteBuffer& right) const
{
return left.timestamp < right.timestamp;
}
};
};
using LossyWriteQueue_t =
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
WriteBuffer::PutTime, WriteBuffer::Compare,
WriteBuffer::GetNow, llarp::util::NullMutex,
llarp::util::NullLock, 5, 100, 1024 >;
using LosslessWriteQueue_t = std::deque< WriteBuffer >;
int fd;
int flags = 0;
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|| (__APPLE__ && __MACH__)
struct kevent change;
#endif
posix_ev_io(int f) : fd(f)
{
}
/// for tun
posix_ev_io(int f, LossyWriteQueue_t* q) : fd(f), m_LossyWriteQueue(q)
{
}
/// for tcp
posix_ev_io(int f, LosslessWriteQueue_t* q) : fd(f), m_BlockingWriteQueue(q)
{
}
2018-11-01 13:47:14 +01:00
virtual void
error()
{
llarp::LogError(strerror(errno));
}
virtual int
2018-12-01 15:35:11 +01:00
read(byte_t* buf, size_t sz) = 0;
virtual int
sendto(__attribute__((unused)) const sockaddr* dst,
__attribute__((unused)) const void* data,
__attribute__((unused)) size_t sz)
{
return -1;
}
/// return false if we want to deregister and remove ourselves
virtual bool
tick()
{
return true;
}
/// used for tun interface and tcp conn
2018-10-27 22:02:37 +02:00
virtual ssize_t
do_write(void* data, size_t sz)
{
return write(fd, data, sz);
}
bool
queue_write(const byte_t* buf, size_t sz)
{
if(m_LossyWriteQueue)
{
m_LossyWriteQueue->Emplace(buf, sz);
return true;
}
2019-07-06 19:03:40 +02:00
if(m_BlockingWriteQueue)
{
m_BlockingWriteQueue->emplace_back(buf, sz);
return true;
}
2019-07-06 19:03:40 +02:00
return false;
}
virtual void
flush_write()
{
flush_write_buffers(0);
}
2018-12-14 16:43:44 +01:00
virtual void
before_flush_write()
{
}
2018-12-14 16:43:44 +01:00
/// called in event loop when fd is ready for writing
/// requeues anything not written
/// this assumes fd is set to non blocking
virtual void
flush_write_buffers(size_t amount)
{
2018-12-14 17:01:32 +01:00
before_flush_write();
if(m_LossyWriteQueue)
2018-12-14 16:43:44 +01:00
{
m_LossyWriteQueue->Process([&](WriteBuffer& buffer) {
do_write(buffer.buf, buffer.bufsz);
// if we would block we save the entries for later
// discard entry
});
2018-12-14 16:43:44 +01:00
}
else if(m_BlockingWriteQueue)
{
if(amount)
{
while(amount && m_BlockingWriteQueue->size())
{
auto& itr = m_BlockingWriteQueue->front();
ssize_t result = do_write(itr.buf, std::min(amount, itr.bufsz));
2019-04-08 16:04:58 +02:00
if(result <= 0)
return;
ssize_t dlt = itr.bufsz - result;
if(dlt > 0)
{
// queue remaining to front of queue
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
m_BlockingWriteQueue->pop_front();
m_BlockingWriteQueue->push_front(buff);
// TODO: errno?
return;
}
m_BlockingWriteQueue->pop_front();
amount -= result;
}
}
else
{
// write buffers
while(m_BlockingWriteQueue->size())
{
auto& itr = m_BlockingWriteQueue->front();
ssize_t result = do_write(itr.buf, itr.bufsz);
2019-04-08 16:04:58 +02:00
if(result <= 0)
2019-02-28 17:02:36 +01:00
{
errno = 0;
return;
2019-02-28 17:02:36 +01:00
}
ssize_t dlt = itr.bufsz - result;
if(dlt > 0)
{
// queue remaining to front of queue
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
m_BlockingWriteQueue->pop_front();
m_BlockingWriteQueue->push_front(buff);
// TODO: errno?
return;
}
m_BlockingWriteQueue->pop_front();
if(errno == EAGAIN || errno == EWOULDBLOCK)
{
errno = 0;
return;
}
}
}
}
/// reset errno
errno = 0;
}
std::unique_ptr< LossyWriteQueue_t > m_LossyWriteQueue;
std::unique_ptr< LosslessWriteQueue_t > m_BlockingWriteQueue;
virtual ~posix_ev_io()
{
close(fd);
}
};
2018-12-14 15:38:37 +01:00
#endif
// finally create aliases by platform
#ifdef _WIN32
using ev_io = win32_ev_io;
#else
using ev_io = posix_ev_io;
#endif
// wew, managed to get away with using
// 'int fd' across all platforms
// since we're operating entirely
// on sockets
struct tcp_conn : public ev_io
{
2018-11-01 13:47:14 +01:00
sockaddr_storage _addr;
bool _shouldClose = false;
bool _calledConnected = false;
llarp_tcp_conn tcp;
// null if inbound otherwise outbound
llarp_tcp_connecter* _conn;
2019-06-02 23:17:05 +02:00
static void
DoClose(llarp_tcp_conn* conn)
{
static_cast< tcp_conn* >(conn->impl)->_shouldClose = true;
}
2018-11-01 13:47:14 +01:00
/// inbound
2019-08-02 11:27:27 +02:00
tcp_conn(llarp_ev_loop* loop, int _fd)
: ev_io(_fd, new LosslessWriteQueue_t{}), _conn(nullptr)
2018-11-01 13:47:14 +01:00
{
tcp.impl = this;
tcp.loop = loop;
tcp.closed = nullptr;
tcp.user = nullptr;
tcp.read = nullptr;
tcp.tick = nullptr;
2019-06-02 23:17:05 +02:00
tcp.close = &DoClose;
2018-11-01 13:47:14 +01:00
}
/// outbound
2019-08-02 11:27:27 +02:00
tcp_conn(llarp_ev_loop* loop, int _fd, const sockaddr* addr,
2018-11-01 13:47:14 +01:00
llarp_tcp_connecter* conn)
2019-08-02 11:27:27 +02:00
: ev_io(_fd, new LosslessWriteQueue_t{}), _conn(conn)
{
2018-11-01 13:47:14 +01:00
socklen_t slen = sizeof(sockaddr_in);
if(addr->sa_family == AF_INET6)
slen = sizeof(sockaddr_in6);
else if(addr->sa_family == AF_UNIX)
slen = sizeof(sockaddr_un);
memcpy(&_addr, addr, slen);
tcp.impl = this;
tcp.loop = loop;
tcp.closed = nullptr;
tcp.user = nullptr;
tcp.read = nullptr;
tcp.tick = nullptr;
2019-06-02 23:17:05 +02:00
tcp.close = &DoClose;
}
2019-07-31 01:42:13 +02:00
~tcp_conn() override = default;
2018-11-01 13:47:14 +01:00
/// start connecting
void
connect();
/// calls connected hooks
void
connected()
{
sockaddr_storage st;
socklen_t sl;
if(getpeername(fd, (sockaddr*)&st, &sl) == 0)
2018-11-01 13:47:14 +01:00
{
// we are connected yeh boi
if(_conn)
{
if(_conn->connected && !_calledConnected)
_conn->connected(_conn, &tcp);
}
_calledConnected = true;
}
else
{
error();
2018-11-01 13:47:14 +01:00
}
}
void
2019-02-28 23:59:36 +01:00
flush_write() override;
2018-11-01 13:47:14 +01:00
void
2019-02-28 23:59:36 +01:00
flush_write_buffers(size_t a) override
{
connected();
ev_io::flush_write_buffers(a);
}
void
error() override
{
_shouldClose = true;
if(_conn)
{
#ifndef _WIN32
llarp::LogError("tcp_conn error: ", strerror(errno));
#else
char ebuf[1024];
int err = WSAGetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_NEUTRAL,
ebuf, 1024, nullptr);
llarp::LogError("tcp_conn error: ", ebuf);
#endif
if(_conn->error)
_conn->error(_conn);
}
2019-02-28 17:02:36 +01:00
errno = 0;
}
2018-11-01 13:47:14 +01:00
2019-07-31 01:42:13 +02:00
ssize_t
2019-02-28 23:59:36 +01:00
do_write(void* buf, size_t sz) override;
2019-07-31 01:42:13 +02:00
int
2019-02-28 23:59:36 +01:00
read(byte_t* buf, size_t sz) override;
bool
2019-02-28 23:59:36 +01:00
tick() override;
};
struct tcp_serv : public ev_io
{
llarp_ev_loop* loop;
llarp_tcp_acceptor* tcp;
2019-08-02 11:27:27 +02:00
tcp_serv(llarp_ev_loop* l, int _fd, llarp_tcp_acceptor* t)
: ev_io(_fd), loop(l), tcp(t)
{
2018-11-01 13:47:14 +01:00
tcp->impl = this;
}
2018-10-25 14:39:32 +02:00
bool
2019-07-31 01:42:13 +02:00
tick() override
{
if(tcp->tick)
tcp->tick(tcp);
2018-10-25 14:39:32 +02:00
return true;
}
/// actually does accept() :^)
2019-07-31 01:42:13 +02:00
int
read(byte_t*, size_t) override;
};
2019-04-26 01:21:19 +02:00
} // namespace llarp
2018-04-30 15:18:57 +02:00
2018-12-03 15:39:30 +01:00
#ifdef _WIN32
struct llarp_fd_promise
{
void
2019-04-08 17:54:19 +02:00
Set(std::pair< int, int >)
2018-12-03 15:39:30 +01:00
{
}
int
Get()
{
return -1;
}
};
#else
struct llarp_fd_promise
{
2019-04-08 17:54:19 +02:00
using promise_val_t = std::pair< int, int >;
llarp_fd_promise(std::promise< promise_val_t >* p) : _impl(p)
{
}
2019-04-08 17:54:19 +02:00
std::promise< promise_val_t >* _impl;
void
2019-04-08 17:54:19 +02:00
Set(promise_val_t fds)
{
2019-04-08 17:54:19 +02:00
_impl->set_value(fds);
}
2019-04-08 17:54:19 +02:00
promise_val_t
Get()
{
auto future = _impl->get_future();
future.wait();
return future.get();
}
};
2018-12-03 15:39:30 +01:00
#endif
// this (nearly!) abstract base class
// is overriden for each platform
struct llarp_ev_loop
{
byte_t readbuf[EV_READ_BUF_SZ] = {0};
2018-11-02 15:58:12 +01:00
llarp_time_t _now = 0;
2019-01-23 23:16:16 +01:00
virtual bool
init() = 0;
2019-01-23 23:16:16 +01:00
virtual int
run() = 0;
2018-06-06 14:46:26 +02:00
2019-01-23 23:16:16 +01:00
virtual bool
running() const = 0;
2019-06-02 23:17:05 +02:00
virtual void
update_time()
{
_now = llarp::time_now_ms();
}
virtual llarp_time_t
time_now() const
{
return _now;
}
2019-06-02 23:17:05 +02:00
virtual void
stopped(){};
2019-01-23 23:16:16 +01:00
/// return false on socket error (non blocking)
virtual bool
tcp_connect(llarp_tcp_connecter* tcp, const sockaddr* addr) = 0;
2018-06-06 14:46:26 +02:00
virtual int
2018-06-06 23:23:57 +02:00
tick(int ms) = 0;
2018-06-06 14:46:26 +02:00
2019-09-05 19:39:09 +02:00
virtual bool
add_ticker(std::function< void(void) > ticker) = 0;
virtual void
stop() = 0;
2018-04-30 15:18:57 +02:00
virtual bool
udp_listen(llarp_udp_io* l, const sockaddr* src) = 0;
2018-08-15 17:36:34 +02:00
virtual bool
udp_close(llarp_udp_io* l) = 0;
2018-10-25 14:39:32 +02:00
/// deregister event listener
virtual bool
close_ev(llarp::ev_io* ev) = 0;
2018-04-30 18:14:20 +02:00
2019-06-02 23:17:05 +02:00
virtual bool
tun_listen(llarp_tun_io* tun)
{
auto dev = create_tun(tun);
tun->impl = dev;
if(dev)
{
return add_ev(dev, false);
}
return false;
}
2018-08-15 17:36:34 +02:00
virtual llarp::ev_io*
create_tun(llarp_tun_io* tun) = 0;
virtual llarp::ev_io*
bind_tcp(llarp_tcp_acceptor* tcp, const sockaddr* addr) = 0;
2019-08-22 13:18:05 +02:00
virtual bool
add_pipe(llarp_ev_pkt_pipe*)
{
return false;
}
2019-08-22 13:18:05 +02:00
/// give this event loop a logic thread for calling
2019-10-02 15:06:14 +02:00
virtual void set_logic(std::shared_ptr< llarp::Logic >) = 0;
2018-10-25 14:39:32 +02:00
/// register event listener
2018-08-15 17:36:34 +02:00
virtual bool
add_ev(llarp::ev_io* ev, bool write) = 0;
2018-08-15 17:36:34 +02:00
2019-06-02 23:17:05 +02:00
virtual bool
tcp_listen(llarp_tcp_acceptor* tcp, const sockaddr* addr)
{
auto conn = bind_tcp(tcp, addr);
return conn && add_ev(conn, true);
}
2019-07-31 01:42:13 +02:00
virtual ~llarp_ev_loop() = default;
std::list< std::unique_ptr< llarp::ev_io > > handlers;
2018-08-15 17:36:34 +02:00
2019-10-02 15:06:14 +02:00
virtual void
2018-08-15 17:36:34 +02:00
tick_listeners()
{
2018-11-08 13:31:50 +01:00
auto itr = handlers.begin();
while(itr != handlers.end())
2018-10-25 14:39:32 +02:00
{
if((*itr)->tick())
++itr;
else
{
close_ev(itr->get());
itr = handlers.erase(itr);
}
}
2018-08-15 17:36:34 +02:00
}
2018-04-30 15:18:57 +02:00
};
2019-10-02 15:06:14 +02:00
struct PacketBuffer
{
PacketBuffer(PacketBuffer&& other)
{
_ptr = other._ptr;
_sz = other._sz;
other._ptr = nullptr;
other._sz = 0;
}
2019-10-28 19:21:08 +01:00
PacketBuffer(const PacketBuffer&) = delete;
2019-10-28 19:34:39 +01:00
PacketBuffer&
operator=(const PacketBuffer&) = delete;
2019-10-02 15:06:14 +02:00
PacketBuffer() : PacketBuffer(nullptr, 0){};
2019-10-28 19:08:59 +01:00
explicit PacketBuffer(size_t sz) : _sz{sz}
2019-10-02 15:06:14 +02:00
{
2019-10-28 19:08:59 +01:00
_ptr = new char[sz];
2019-10-02 15:06:14 +02:00
}
PacketBuffer(char* buf, size_t sz) : _ptr{buf}, _sz{sz}
{
}
~PacketBuffer()
{
if(_ptr)
delete[] _ptr;
}
byte_t*
data()
{
return (byte_t*)_ptr;
}
size_t
size()
{
return _sz;
}
byte_t& operator[](size_t sz)
{
return data()[sz];
}
void
reserve(size_t sz)
{
if(_ptr)
delete[] _ptr;
_ptr = new char[sz];
2019-10-28 19:34:39 +01:00
_sz = sz;
2019-10-02 15:06:14 +02:00
}
private:
char* _ptr = nullptr;
size_t _sz = 0;
};
struct PacketEvent
{
2019-10-28 19:08:59 +01:00
llarp::Addr remote;
PacketBuffer pkt;
2019-10-02 15:06:14 +02:00
};
struct llarp_pkt_list : public std::vector< PacketEvent >
{
};
2018-04-30 15:18:57 +02:00
#endif