lokinet/llarp/ev.hpp

196 lines
4.0 KiB
C++
Raw Normal View History

2018-04-30 13:18:57 +00:00
#ifndef LLARP_EV_HPP
#define LLARP_EV_HPP
#include <llarp/ev.h>
#ifndef _MSC_VER
2018-04-30 13:18:57 +00:00
#include <unistd.h>
#endif
2018-08-15 15:36:34 +00:00
#include <llarp/buffer.h>
#include <list>
2018-08-15 15:36:34 +00:00
#include <llarp/codel.hpp>
#include <vector>
#ifndef MAX_WRITE_QUEUE_SIZE
#define MAX_WRITE_QUEUE_SIZE 1024
#endif
2018-04-30 13:18:57 +00:00
namespace llarp
{
struct ev_io
{
#ifndef _WIN32
int fd;
2018-08-15 15:36:34 +00:00
ev_io(int f) : fd(f), m_writeq("writequeue"){};
#else
SOCKET 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
// Here, we'll use the address of the udp_listener instance, converted to
// its literal int/int64 representation.
ULONG_PTR listener_id = 0;
2018-08-15 15:36:34 +00:00
ev_io(SOCKET f) : fd(f), m_writeq("writequeue"){};
#endif
virtual int
read(void* buf, size_t sz) = 0;
virtual int
sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
2018-08-15 15:36:34 +00:00
/// used for tun interface
bool
queue_write(const void* data, size_t sz)
{
return m_writeq.EmplaceIf(
[&](WriteBuffer* pkt) -> bool {
return m_writeq.Size() < MAX_WRITE_QUEUE_SIZE
&& sz <= sizeof(pkt->buf);
},
data, sz);
2018-08-15 15:36:34 +00:00
}
/// called in event loop when fd is ready for writing
/// requeues anything not written
2018-08-15 15:36:34 +00:00
/// this assumes fd is set to non blocking
virtual void
2018-08-15 15:36:34 +00:00
flush_write()
{
2018-08-22 15:52:10 +00:00
m_writeq.ProcessIf([&](WriteBuffer* buffer) -> bool {
// todo: wtf???
#ifndef _WIN32
2018-08-22 15:52:10 +00:00
if(write(fd, buffer->buf, buffer->bufsz) == -1)
{
// if we would block we save the entries for later
return errno == EWOULDBLOCK || errno == EAGAIN;
}
// discard entry
return true;
#else
2018-08-20 10:52:47 +00:00
// writefile
#endif
2018-08-22 15:52:10 +00:00
});
2018-08-15 15:36:34 +00:00
/// reset errno
errno = 0;
}
struct WriteBuffer
{
llarp_time_t timestamp = 0;
size_t bufsz;
byte_t buf[1500];
2018-08-15 15:36:34 +00:00
WriteBuffer(const void* ptr, size_t sz)
2018-08-15 15:36:34 +00:00
{
if(sz <= sizeof(buf))
{
bufsz = sz;
memcpy(buf, ptr, bufsz);
}
else
bufsz = 0;
2018-08-15 15:36:34 +00:00
}
struct GetTime
{
llarp_time_t
operator()(const WriteBuffer* w) const
{
return w->timestamp;
}
};
struct PutTime
{
void
operator()(WriteBuffer* w) const
2018-08-15 15:36:34 +00:00
{
w->timestamp = llarp_time_now_ms();
}
};
struct Compare
{
bool
operator()(const WriteBuffer* left, const WriteBuffer* right) const
2018-08-15 15:36:34 +00:00
{
return left->timestamp < right->timestamp;
}
};
};
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
2018-08-15 15:36:34 +00:00
WriteBuffer::PutTime, WriteBuffer::Compare,
llarp::util::NullMutex, llarp::util::NullLock >
m_writeq;
virtual ~ev_io()
{
#ifndef _WIN32
::close(fd);
#else
closesocket(fd);
#endif
};
};
2018-08-15 15:36:34 +00:00
2018-04-30 16:14:20 +00:00
}; // namespace llarp
2018-04-30 13:18:57 +00:00
struct llarp_ev_loop
{
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
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-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;
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(){};
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-15 15:36:34 +00:00
if(l->tick)
l->tick(l);
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