2018-04-30 13:18:57 +00:00
|
|
|
#ifndef LLARP_EV_HPP
|
|
|
|
#define LLARP_EV_HPP
|
|
|
|
#include <llarp/ev.h>
|
2018-10-01 02:08:03 +00:00
|
|
|
// writev
|
|
|
|
#ifndef _WIN32
|
2018-09-30 13:23:37 +00:00
|
|
|
#include <sys/uio.h>
|
2018-10-01 02:08:03 +00:00
|
|
|
#endif
|
2018-04-30 13:18:57 +00:00
|
|
|
#include <unistd.h>
|
2018-08-15 15:36:34 +00:00
|
|
|
#include <llarp/buffer.h>
|
2018-06-27 13:14:07 +00:00
|
|
|
#include <list>
|
2018-08-15 15:36:34 +00:00
|
|
|
#include <llarp/codel.hpp>
|
|
|
|
#include <vector>
|
2018-10-04 11:20:08 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <variant>
|
|
|
|
#endif
|
|
|
|
|
2018-08-15 15:36:34 +00:00
|
|
|
#ifndef MAX_WRITE_QUEUE_SIZE
|
|
|
|
#define MAX_WRITE_QUEUE_SIZE 1024
|
|
|
|
#endif
|
2018-04-30 13:18:57 +00:00
|
|
|
|
2018-09-06 20:31:58 +00:00
|
|
|
#ifndef EV_READ_BUF_SZ
|
|
|
|
#define EV_READ_BUF_SZ (4 * 1024)
|
|
|
|
#endif
|
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
struct ev_io
|
|
|
|
{
|
2018-07-30 04:38:14 +00:00
|
|
|
#ifndef _WIN32
|
2018-05-22 15:54:19 +00:00
|
|
|
int fd;
|
2018-08-15 15:36:34 +00:00
|
|
|
ev_io(int f) : fd(f), m_writeq("writequeue"){};
|
2018-07-30 04:38:14 +00:00
|
|
|
#else
|
2018-10-04 11:20:08 +00:00
|
|
|
// on windows, udp event loops are socket fds
|
|
|
|
// and TUN device is a plain old fd
|
|
|
|
std::variant< SOCKET, HANDLE > fd;
|
2018-08-15 16:21:51 +00:00
|
|
|
// the unique completion key that helps us to
|
|
|
|
// identify the object instance for which we receive data
|
2018-10-04 11:20:08 +00:00
|
|
|
// Here, we'll use the address of the udp_listener instance, converted
|
|
|
|
// to its literal int/int64 representation.
|
2018-08-15 16:21:51 +00:00
|
|
|
ULONG_PTR listener_id = 0;
|
2018-08-15 15:36:34 +00:00
|
|
|
ev_io(SOCKET f) : fd(f), m_writeq("writequeue"){};
|
2018-10-04 11:20:08 +00:00
|
|
|
ev_io(HANDLE t)
|
|
|
|
: fd(t), m_writeq("writequeue"){}; // overload for TUN device, which
|
|
|
|
// _is_ a regular file descriptor
|
2018-07-30 04:38:14 +00:00
|
|
|
#endif
|
2018-05-22 15:54:19 +00:00
|
|
|
virtual int
|
|
|
|
read(void* buf, size_t sz) = 0;
|
2018-06-27 13:14:07 +00:00
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
virtual int
|
|
|
|
sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
|
2018-08-03 06:03:34 +00:00
|
|
|
|
2018-08-15 15:36:34 +00:00
|
|
|
/// used for tun interface
|
2018-10-01 17:16:15 +00:00
|
|
|
virtual bool
|
2018-09-30 13:23:37 +00:00
|
|
|
do_write(void* data, size_t sz)
|
2018-08-15 15:36:34 +00:00
|
|
|
{
|
2018-08-18 03:19:00 +00:00
|
|
|
#ifndef _WIN32
|
2018-10-01 20:14:36 +00:00
|
|
|
return write(fd, data, sz) != -1;
|
2018-08-18 03:19:00 +00:00
|
|
|
#else
|
2018-10-04 13:32:33 +00:00
|
|
|
DWORD w;
|
|
|
|
return WriteFile(std::get< HANDLE >(fd), data, sz, &w, nullptr);
|
2018-09-29 08:16:54 +00:00
|
|
|
#endif
|
2018-10-01 20:14:36 +00:00
|
|
|
}
|
2018-08-29 20:40:26 +00:00
|
|
|
|
2018-10-03 10:40:32 +00: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()
|
|
|
|
{
|
|
|
|
m_writeq.Process([&](WriteBuffer& buffer) {
|
|
|
|
do_write(buffer.buf, buffer.bufsz);
|
|
|
|
// if we would block we save the entries for later
|
|
|
|
// discard entry
|
|
|
|
});
|
|
|
|
/// reset errno
|
|
|
|
errno = 0;
|
2018-09-29 08:16:54 +00:00
|
|
|
#if _WIN32
|
2018-10-03 10:40:32 +00:00
|
|
|
SetLastError(0);
|
2018-09-29 08:16:54 +00:00
|
|
|
#endif
|
2018-08-15 15:36:34 +00:00
|
|
|
}
|
|
|
|
|
2018-10-03 10:40:32 +00:00
|
|
|
struct WriteBuffer
|
2018-08-15 15:36:34 +00:00
|
|
|
{
|
2018-10-03 10:40:32 +00:00
|
|
|
llarp_time_t timestamp = 0;
|
|
|
|
size_t bufsz;
|
|
|
|
byte_t buf[1500];
|
|
|
|
|
|
|
|
WriteBuffer() = default;
|
|
|
|
|
|
|
|
WriteBuffer(const void* ptr, size_t sz)
|
|
|
|
{
|
|
|
|
if(sz <= sizeof(buf))
|
|
|
|
{
|
|
|
|
bufsz = sz;
|
|
|
|
memcpy(buf, ptr, bufsz);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
bufsz = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct GetTime
|
|
|
|
{
|
|
|
|
llarp_time_t
|
|
|
|
operator()(const WriteBuffer& w) const
|
|
|
|
{
|
|
|
|
return w.timestamp;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PutTime
|
|
|
|
{
|
|
|
|
void
|
|
|
|
operator()(WriteBuffer& w) const
|
|
|
|
{
|
|
|
|
w.timestamp = llarp_time_now_ms();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Compare
|
|
|
|
{
|
|
|
|
bool
|
|
|
|
operator()(const WriteBuffer& left, const WriteBuffer& right) const
|
|
|
|
{
|
|
|
|
return left.timestamp < right.timestamp;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
|
|
|
|
WriteBuffer::PutTime, WriteBuffer::Compare,
|
|
|
|
llarp::util::NullMutex, llarp::util::NullLock >
|
|
|
|
m_writeq;
|
|
|
|
|
|
|
|
virtual ~ev_io()
|
2018-05-22 15:54:19 +00:00
|
|
|
{
|
2018-07-30 04:38:14 +00:00
|
|
|
#ifndef _WIN32
|
2018-10-03 10:40:32 +00:00
|
|
|
::close(fd);
|
2018-07-30 04:38:14 +00:00
|
|
|
#else
|
2018-10-04 11:20:08 +00:00
|
|
|
closesocket(std::get< SOCKET >(fd));
|
2018-07-30 04:38:14 +00:00
|
|
|
#endif
|
2018-10-03 10:40:32 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
}; // namespace llarp
|
2018-04-30 13:18:57 +00:00
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
struct llarp_ev_loop
|
|
|
|
{
|
2018-09-06 20:31:58 +00:00
|
|
|
byte_t readbuf[EV_READ_BUF_SZ];
|
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
virtual bool
|
|
|
|
init() = 0;
|
|
|
|
virtual int
|
|
|
|
run() = 0;
|
2018-06-06 12:46:26 +00:00
|
|
|
|
|
|
|
virtual int
|
2018-06-06 21:23:57 +00:00
|
|
|
tick(int ms) = 0;
|
2018-06-06 12:46:26 +00:00
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
virtual void
|
|
|
|
stop() = 0;
|
2018-04-30 13:18:57 +00:00
|
|
|
|
2018-08-15 15:46:39 +00:00
|
|
|
bool
|
2018-08-15 15:36:34 +00:00
|
|
|
udp_listen(llarp_udp_io* l, const sockaddr* src)
|
|
|
|
{
|
|
|
|
auto ev = create_udp(l, src);
|
2018-09-06 20:31:58 +00:00
|
|
|
if(ev)
|
|
|
|
{
|
2018-10-04 11:20:08 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
l->fd = std::get< SOCKET >(ev->fd);
|
|
|
|
#else
|
2018-09-06 20:31:58 +00:00
|
|
|
l->fd = ev->fd;
|
2018-10-04 11:20:08 +00:00
|
|
|
#endif
|
2018-09-06 20:31:58 +00:00
|
|
|
}
|
2018-08-20 19:12:12 +00:00
|
|
|
return ev && add_ev(ev, false);
|
2018-08-15 15:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual llarp::ev_io*
|
|
|
|
create_udp(llarp_udp_io* l, const sockaddr* src) = 0;
|
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
virtual bool
|
|
|
|
udp_close(llarp_udp_io* l) = 0;
|
|
|
|
virtual bool
|
|
|
|
close_ev(llarp::ev_io* ev) = 0;
|
2018-04-30 16:14:20 +00:00
|
|
|
|
2018-08-15 15:36:34 +00:00
|
|
|
virtual llarp::ev_io*
|
|
|
|
create_tun(llarp_tun_io* tun) = 0;
|
|
|
|
|
|
|
|
virtual bool
|
2018-08-20 19:12:12 +00:00
|
|
|
add_ev(llarp::ev_io* ev, bool write = false) = 0;
|
2018-08-15 15:36:34 +00:00
|
|
|
|
2018-08-10 03:51:38 +00:00
|
|
|
virtual bool
|
|
|
|
running() const = 0;
|
|
|
|
|
2018-04-30 16:14:20 +00:00
|
|
|
virtual ~llarp_ev_loop(){};
|
2018-06-27 13:14:07 +00:00
|
|
|
|
|
|
|
std::list< llarp_udp_io* > udp_listeners;
|
2018-08-15 15:36:34 +00:00
|
|
|
std::list< llarp_tun_io* > tun_listeners;
|
|
|
|
|
|
|
|
void
|
|
|
|
tick_listeners()
|
|
|
|
{
|
|
|
|
for(auto& l : udp_listeners)
|
|
|
|
if(l->tick)
|
|
|
|
l->tick(l);
|
|
|
|
for(auto& l : tun_listeners)
|
2018-08-21 18:17:16 +00:00
|
|
|
{
|
2018-08-15 15:36:34 +00:00
|
|
|
if(l->tick)
|
|
|
|
l->tick(l);
|
2018-08-21 18:17:16 +00:00
|
|
|
if(l->before_write)
|
|
|
|
l->before_write(l);
|
|
|
|
static_cast< llarp::ev_io* >(l->impl)->flush_write();
|
|
|
|
}
|
2018-08-15 15:36:34 +00:00
|
|
|
}
|
2018-04-30 13:18:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|