mirror of https://github.com/oxen-io/lokinet
commit
b857be3d02
@ -0,0 +1,641 @@
|
||||
#include "ev_libuv.hpp"
|
||||
#include "net/net_addr.hpp"
|
||||
|
||||
namespace libuv
|
||||
{
|
||||
/// tcp connection glue between llarp and libuv
|
||||
struct conn_glue
|
||||
{
|
||||
uv_tcp_t m_Handle;
|
||||
uv_connect_t m_Connect;
|
||||
uv_timer_t m_Ticker;
|
||||
llarp_tcp_connecter* const m_TCP;
|
||||
llarp_tcp_acceptor* const m_Accept;
|
||||
llarp_tcp_conn m_Conn;
|
||||
llarp::Addr m_Addr;
|
||||
|
||||
std::deque< std::vector< char > > m_WriteQueue;
|
||||
|
||||
conn_glue(uv_loop_t* loop, llarp_tcp_connecter* tcp, const sockaddr* addr)
|
||||
: m_TCP(tcp), m_Accept(nullptr), m_Addr(*addr)
|
||||
{
|
||||
m_Connect.data = this;
|
||||
m_Handle.data = this;
|
||||
uv_tcp_init(loop, &m_Handle);
|
||||
m_Ticker.data = this;
|
||||
uv_timer_init(loop, &m_Ticker);
|
||||
m_Conn.close = &ExplicitClose;
|
||||
m_Conn.write = &ExplicitWrite;
|
||||
}
|
||||
|
||||
conn_glue(uv_loop_t* loop, llarp_tcp_acceptor* tcp, const sockaddr* addr)
|
||||
: m_TCP(nullptr), m_Accept(tcp), m_Addr(*addr)
|
||||
{
|
||||
m_Handle.data = this;
|
||||
uv_tcp_init(loop, &m_Handle);
|
||||
m_Ticker.data = this;
|
||||
uv_timer_init(loop, &m_Ticker);
|
||||
m_Accept->close = &ExplicitCloseAccept;
|
||||
m_Conn.write = nullptr;
|
||||
m_Conn.closed = nullptr;
|
||||
}
|
||||
|
||||
conn_glue(conn_glue* parent) : m_TCP(nullptr), m_Accept(nullptr)
|
||||
{
|
||||
m_Conn.close = &ExplicitClose;
|
||||
m_Conn.write = &ExplicitWrite;
|
||||
m_Handle.data = this;
|
||||
uv_tcp_init(parent->m_Handle.loop, &m_Handle);
|
||||
m_Ticker.data = this;
|
||||
uv_timer_init(parent->m_Handle.loop, &m_Ticker);
|
||||
}
|
||||
|
||||
static void
|
||||
OnOutboundConnect(uv_connect_t* c, int status)
|
||||
{
|
||||
conn_glue* self = static_cast< conn_glue* >(c->data);
|
||||
self->HandleConnectResult(status);
|
||||
}
|
||||
|
||||
bool
|
||||
ConnectAsync()
|
||||
{
|
||||
return uv_tcp_connect(&m_Connect, &m_Handle, m_Addr, &OnOutboundConnect)
|
||||
!= -1;
|
||||
}
|
||||
|
||||
static void
|
||||
ExplicitClose(llarp_tcp_conn* conn)
|
||||
{
|
||||
static_cast< conn_glue* >(conn->impl)->Close();
|
||||
}
|
||||
static void
|
||||
ExplicitCloseAccept(llarp_tcp_acceptor* tcp)
|
||||
{
|
||||
static_cast< conn_glue* >(tcp->impl)->Close();
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ExplicitWrite(llarp_tcp_conn* conn, const byte_t* ptr, size_t sz)
|
||||
{
|
||||
return static_cast< conn_glue* >(conn->impl)->WriteAsync((char*)ptr, sz);
|
||||
}
|
||||
|
||||
static void
|
||||
OnRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
if(nread >= 0)
|
||||
static_cast< conn_glue* >(stream->data)->Read(buf->base, nread);
|
||||
else if(nread < 0)
|
||||
static_cast< conn_glue* >(stream->data)->Close();
|
||||
delete[] buf->base;
|
||||
}
|
||||
|
||||
static void
|
||||
Alloc(uv_handle_t*, size_t suggested_size, uv_buf_t* buf)
|
||||
{
|
||||
buf->base = new char[suggested_size];
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
void
|
||||
Read(const char* ptr, ssize_t sz)
|
||||
{
|
||||
if(m_Conn.read)
|
||||
{
|
||||
llarp::LogDebug("tcp read ", sz, " bytes");
|
||||
const llarp_buffer_t buf(ptr, sz);
|
||||
m_Conn.read(&m_Conn, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HandleConnectResult(int status)
|
||||
{
|
||||
if(m_TCP && m_TCP->connected)
|
||||
{
|
||||
if(status == 0)
|
||||
{
|
||||
m_Conn.impl = this;
|
||||
m_Conn.loop = m_TCP->loop;
|
||||
m_Conn.close = &ExplicitClose;
|
||||
m_Conn.write = &ExplicitWrite;
|
||||
m_TCP->connected(m_TCP, &m_Conn);
|
||||
Start();
|
||||
}
|
||||
else if(m_TCP->error)
|
||||
{
|
||||
llarp::LogError("failed to connect tcp ", uv_strerror(status));
|
||||
m_TCP->error(m_TCP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WriteFail()
|
||||
{
|
||||
if(m_Conn.close)
|
||||
m_Conn.close(&m_Conn);
|
||||
}
|
||||
|
||||
uv_stream_t*
|
||||
Stream()
|
||||
{
|
||||
return (uv_stream_t*)&m_Handle;
|
||||
}
|
||||
|
||||
static void
|
||||
OnWritten(uv_write_t* req, int status)
|
||||
{
|
||||
if(status)
|
||||
{
|
||||
llarp::LogError("write failed on tcp: ", uv_strerror(status));
|
||||
static_cast< conn_glue* >(req->data)->Close();
|
||||
return;
|
||||
}
|
||||
static_cast< conn_glue* >(req->data)->DrainOne();
|
||||
}
|
||||
|
||||
void
|
||||
DrainOne()
|
||||
{
|
||||
m_WriteQueue.pop_front();
|
||||
}
|
||||
|
||||
int
|
||||
WriteAsync(char* data, size_t sz)
|
||||
{
|
||||
m_WriteQueue.emplace_back(sz);
|
||||
std::copy_n(data, sz, m_WriteQueue.back().begin());
|
||||
auto buf = uv_buf_init(m_WriteQueue.back().data(), sz);
|
||||
uv_write_t* req = new uv_write_t();
|
||||
req->data = this;
|
||||
return uv_write(req, Stream(), &buf, 1, &OnWritten) == 0 ? sz : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
OnClosed(uv_handle_t* h)
|
||||
{
|
||||
static_cast< conn_glue* >(h->data)->HandleClosed();
|
||||
}
|
||||
|
||||
void
|
||||
HandleClosed()
|
||||
{
|
||||
m_Handle.data = nullptr;
|
||||
if(m_Accept && m_Accept->closed)
|
||||
{
|
||||
m_Accept->impl = nullptr;
|
||||
m_Accept->closed(m_Accept);
|
||||
}
|
||||
m_Conn.impl = nullptr;
|
||||
if(m_Conn.closed)
|
||||
{
|
||||
m_Conn.closed(&m_Conn);
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
void
|
||||
Close()
|
||||
{
|
||||
llarp::LogDebug("close tcp connection");
|
||||
uv_timer_stop(&m_Ticker);
|
||||
uv_close((uv_handle_t*)&m_Handle, &OnClosed);
|
||||
}
|
||||
|
||||
static void
|
||||
OnAccept(uv_stream_t* stream, int status)
|
||||
{
|
||||
if(status == 0)
|
||||
{
|
||||
static_cast< conn_glue* >(stream->data)->Accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogError("tcp accept failed: ", uv_strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
OnTick(uv_timer_t* t)
|
||||
{
|
||||
static_cast< conn_glue* >(t->data)->Tick();
|
||||
uv_timer_again(t);
|
||||
}
|
||||
|
||||
void
|
||||
Tick()
|
||||
{
|
||||
if(m_Accept && m_Accept->tick)
|
||||
m_Accept->tick(m_Accept);
|
||||
if(m_Conn.tick)
|
||||
m_Conn.tick(&m_Conn);
|
||||
}
|
||||
|
||||
void
|
||||
Start()
|
||||
{
|
||||
auto result = uv_timer_start((uv_timer_t*)&m_Ticker, &OnTick, 10, 10);
|
||||
if(result)
|
||||
llarp::LogError("failed to start timer ", uv_strerror(result));
|
||||
result = uv_read_start(Stream(), &Alloc, &OnRead);
|
||||
if(result)
|
||||
llarp::LogError("failed to start reader ", uv_strerror(result));
|
||||
}
|
||||
|
||||
void
|
||||
Accept()
|
||||
{
|
||||
if(m_Accept && m_Accept->accepted)
|
||||
{
|
||||
conn_glue* child = new conn_glue(this);
|
||||
llarp::LogDebug("accepted new connection");
|
||||
child->m_Conn.impl = child;
|
||||
child->m_Conn.loop = m_Accept->loop;
|
||||
child->m_Conn.close = &ExplicitClose;
|
||||
child->m_Conn.write = &ExplicitWrite;
|
||||
auto res = uv_accept(Stream(), child->Stream());
|
||||
if(res)
|
||||
{
|
||||
llarp::LogError("failed to accept tcp connection ", uv_strerror(res));
|
||||
child->Close();
|
||||
return;
|
||||
}
|
||||
m_Accept->accepted(m_Accept, &child->m_Conn);
|
||||
child->Start();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Server()
|
||||
{
|
||||
m_Accept->close = &ExplicitCloseAccept;
|
||||
return uv_tcp_bind(&m_Handle, m_Addr, 0) == 0
|
||||
&& uv_listen(Stream(), 5, &OnAccept) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct udp_glue
|
||||
{
|
||||
uv_udp_t m_Handle;
|
||||
uv_check_t m_Ticker;
|
||||
llarp_udp_io* const m_UDP;
|
||||
llarp::Addr m_Addr;
|
||||
bool gotpkts;
|
||||
|
||||
udp_glue(uv_loop_t* loop, llarp_udp_io* udp, const sockaddr* src)
|
||||
: m_UDP(udp), m_Addr(*src)
|
||||
{
|
||||
m_Handle.data = this;
|
||||
m_Ticker.data = this;
|
||||
gotpkts = false;
|
||||
uv_udp_init(loop, &m_Handle);
|
||||
uv_check_init(loop, &m_Ticker);
|
||||
}
|
||||
|
||||
static void
|
||||
Alloc(uv_handle_t*, size_t suggested_size, uv_buf_t* buf)
|
||||
{
|
||||
buf->base = new char[suggested_size];
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
static void
|
||||
OnRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf,
|
||||
const struct sockaddr* addr, unsigned)
|
||||
{
|
||||
if(addr)
|
||||
static_cast< udp_glue* >(handle->data)->RecvFrom(nread, buf, addr);
|
||||
delete[] buf->base;
|
||||
}
|
||||
|
||||
void
|
||||
RecvFrom(ssize_t sz, const uv_buf_t* buf, const struct sockaddr* fromaddr)
|
||||
{
|
||||
if(sz >= 0 && m_UDP && m_UDP->recvfrom)
|
||||
{
|
||||
const size_t pktsz = sz;
|
||||
const llarp_buffer_t pkt{(const byte_t*)buf->base, pktsz};
|
||||
m_UDP->recvfrom(m_UDP, fromaddr, ManagedBuffer{pkt});
|
||||
gotpkts = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
OnTick(uv_check_t* t)
|
||||
{
|
||||
static_cast< udp_glue* >(t->data)->Tick();
|
||||
}
|
||||
|
||||
void
|
||||
Tick()
|
||||
{
|
||||
if(m_UDP && m_UDP->tick)
|
||||
m_UDP->tick(m_UDP);
|
||||
}
|
||||
|
||||
static int
|
||||
SendTo(llarp_udp_io* udp, const sockaddr* to, const byte_t* ptr, size_t sz)
|
||||
{
|
||||
udp_glue* self = static_cast< udp_glue* >(udp->impl);
|
||||
uv_buf_t buf = uv_buf_init((char*)ptr, sz);
|
||||
return uv_udp_try_send(&self->m_Handle, &buf, 1, to);
|
||||
}
|
||||
|
||||
bool
|
||||
Bind()
|
||||
{
|
||||
auto ret = uv_udp_bind(&m_Handle, m_Addr, 0);
|
||||
if(ret)
|
||||
{
|
||||
llarp::LogError("failed to bind to ", m_Addr, " ", uv_strerror(ret));
|
||||
return false;
|
||||
}
|
||||
if(uv_udp_recv_start(&m_Handle, &Alloc, &OnRecv))
|
||||
{
|
||||
llarp::LogError("failed to start recving packets via ", m_Addr);
|
||||
return false;
|
||||
}
|
||||
if(uv_check_start(&m_Ticker, &OnTick))
|
||||
{
|
||||
llarp::LogError("failed to start ticker");
|
||||
return false;
|
||||
}
|
||||
if(uv_fileno((const uv_handle_t*)&m_Handle, &m_UDP->fd))
|
||||
return false;
|
||||
m_UDP->sendto = &SendTo;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
OnClosed(uv_handle_t* h)
|
||||
{
|
||||
udp_glue* glue = static_cast< udp_glue* >(h->data);
|
||||
glue->m_UDP->impl = nullptr;
|
||||
delete glue;
|
||||
}
|
||||
|
||||
void
|
||||
Close()
|
||||
{
|
||||
uv_check_stop(&m_Ticker);
|
||||
uv_close((uv_handle_t*)&m_Handle, &OnClosed);
|
||||
}
|
||||
};
|
||||
|
||||
struct tun_glue
|
||||
{
|
||||
uv_poll_t m_Handle;
|
||||
uv_check_t m_Ticker;
|
||||
llarp_tun_io* const m_Tun;
|
||||
device* const m_Device;
|
||||
byte_t m_Buffer[1500];
|
||||
bool readpkt;
|
||||
|
||||
tun_glue(llarp_tun_io* tun) : m_Tun(tun), m_Device(tuntap_init())
|
||||
{
|
||||
m_Handle.data = this;
|
||||
m_Ticker.data = this;
|
||||
readpkt = false;
|
||||
}
|
||||
|
||||
~tun_glue()
|
||||
{
|
||||
tuntap_destroy(m_Device);
|
||||
}
|
||||
|
||||
static void
|
||||
OnTick(uv_check_t* timer)
|
||||
{
|
||||
static_cast< tun_glue* >(timer->data)->Tick();
|
||||
}
|
||||
|
||||
static void
|
||||
OnPoll(uv_poll_t* h, int, int events)
|
||||
{
|
||||
if(events & UV_READABLE)
|
||||
{
|
||||
static_cast< tun_glue* >(h->data)->Read();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Read()
|
||||
{
|
||||
auto sz = tuntap_read(m_Device, m_Buffer, sizeof(m_Buffer));
|
||||
if(sz > 0)
|
||||
{
|
||||
llarp::LogDebug("tun read ", sz);
|
||||
llarp_buffer_t pkt(m_Buffer, sz);
|
||||
if(m_Tun && m_Tun->recvpkt)
|
||||
m_Tun->recvpkt(m_Tun, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Tick()
|
||||
{
|
||||
if(m_Tun->before_write)
|
||||
m_Tun->before_write(m_Tun);
|
||||
if(m_Tun->tick)
|
||||
m_Tun->tick(m_Tun);
|
||||
}
|
||||
|
||||
static void
|
||||
OnClosed(uv_handle_t* h)
|
||||
{
|
||||
tun_glue* self = static_cast< tun_glue* >(h->data);
|
||||
delete self;
|
||||
}
|
||||
|
||||
void
|
||||
Close()
|
||||
{
|
||||
uv_close((uv_handle_t*)&m_Handle, &OnClosed);
|
||||
}
|
||||
|
||||
bool
|
||||
Write(const byte_t* pkt, size_t sz)
|
||||
{
|
||||
return tuntap_write(m_Device, (void*)pkt, sz) != -1;
|
||||
}
|
||||
|
||||
static bool
|
||||
WritePkt(llarp_tun_io* tun, const byte_t* pkt, size_t sz)
|
||||
{
|
||||
return static_cast< tun_glue* >(tun->impl)->Write(pkt, sz);
|
||||
}
|
||||
|
||||
bool
|
||||
Init(uv_loop_t* loop)
|
||||
{
|
||||
strncpy(m_Device->if_name, m_Tun->ifname, sizeof(m_Device->if_name));
|
||||
if(tuntap_start(m_Device, TUNTAP_MODE_TUNNEL, 0) == -1)
|
||||
{
|
||||
llarp::LogError("failed to start up ", m_Tun->ifname);
|
||||
return false;
|
||||
}
|
||||
if(tuntap_set_ip(m_Device, m_Tun->ifaddr, m_Tun->ifaddr, m_Tun->netmask)
|
||||
== -1)
|
||||
{
|
||||
llarp::LogError("failed to set address on ", m_Tun->ifname);
|
||||
return false;
|
||||
}
|
||||
if(tuntap_up(m_Device) == -1)
|
||||
{
|
||||
llarp::LogError("failed to put up ", m_Tun->ifname);
|
||||
return false;
|
||||
}
|
||||
if(m_Device->tun_fd == -1)
|
||||
{
|
||||
llarp::LogError("tun interface ", m_Tun->ifname,
|
||||
" has invalid fd: ", m_Device->tun_fd);
|
||||
return false;
|
||||
}
|
||||
if(uv_poll_init(loop, &m_Handle, m_Device->tun_fd) == -1)
|
||||
{
|
||||
llarp::LogError("failed to start polling on ", m_Tun->ifname);
|
||||
return false;
|
||||
}
|
||||
if(uv_poll_start(&m_Handle, UV_READABLE, &OnPoll))
|
||||
{
|
||||
llarp::LogError("failed to start polling on ", m_Tun->ifname);
|
||||
return false;
|
||||
}
|
||||
if(uv_check_init(loop, &m_Ticker) != 0
|
||||
|| uv_check_start(&m_Ticker, &OnTick) != 0)
|
||||
{
|
||||
llarp::LogError("failed to set up tun interface timer for ",
|
||||
m_Tun->ifname);
|
||||
return false;
|
||||
}
|
||||
m_Tun->writepkt = &WritePkt;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
Loop::init()
|
||||
{
|
||||
m_Impl.reset(uv_loop_new());
|
||||
if(uv_loop_init(m_Impl.get()) == -1)
|
||||
return false;
|
||||
uv_loop_configure(m_Impl.get(), UV_LOOP_BLOCK_SIGNAL, SIGPIPE);
|
||||
m_TickTimer.data = this;
|
||||
m_Run.store(true);
|
||||
return uv_timer_init(m_Impl.get(), &m_TickTimer) != -1;
|
||||
}
|
||||
|
||||
void
|
||||
Loop::update_time()
|
||||
{
|
||||
uv_update_time(m_Impl.get());
|
||||
}
|
||||
|
||||
bool
|
||||
Loop::running() const
|
||||
{
|
||||
return m_Run.load();
|
||||
}
|
||||
|
||||
llarp_time_t
|
||||
Loop::time_now() const
|
||||
{
|
||||
return llarp::time_now_ms();
|
||||
}
|
||||
|
||||
bool
|
||||
Loop::tcp_connect(llarp_tcp_connecter* tcp, const sockaddr* addr)
|
||||
{
|
||||
conn_glue* impl = new conn_glue(m_Impl.get(), tcp, addr);
|
||||
tcp->impl = impl;
|
||||
if(impl->ConnectAsync())
|
||||
return true;
|
||||
delete impl;
|
||||
tcp->impl = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
OnTickTimeout(uv_timer_t* timer)
|
||||
{
|
||||
uv_stop(timer->loop);
|
||||
}
|
||||
|
||||
int
|
||||
Loop::tick(int ms)
|
||||
{
|
||||
uv_timer_start(&m_TickTimer, &OnTickTimeout, ms, 0);
|
||||
uv_run(m_Impl.get(), UV_RUN_ONCE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Loop::stop()
|
||||
{
|
||||
llarp::LogInfo("stopping event loop");
|
||||
m_Run.store(false);
|
||||
}
|
||||
|
||||
bool
|
||||
Loop::udp_listen(llarp_udp_io* udp, const sockaddr* src)
|
||||
{
|
||||
udp_glue* impl = new udp_glue(m_Impl.get(), udp, src);
|
||||
udp->impl = impl;
|
||||
if(impl->Bind())
|
||||
{
|
||||
m_CloseFuncs.emplace_back(std::bind(&udp_glue::Close, impl));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Loop::udp_close(llarp_udp_io* udp)
|
||||
{
|
||||
if(udp == nullptr)
|
||||
return false;
|
||||
udp_glue* glue = static_cast< udp_glue* >(udp->impl);
|
||||
if(glue == nullptr)
|
||||
return false;
|
||||
glue->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Loop::tun_listen(llarp_tun_io* tun)
|
||||
{
|
||||
tun_glue* glue = new tun_glue(tun);
|
||||
tun->impl = glue;
|
||||
if(glue->Init(m_Impl.get()))
|
||||
{
|
||||
m_CloseFuncs.emplace_back(std::bind(&tun_glue ::Close, glue));
|
||||
return true;
|
||||
}
|
||||
delete glue;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Loop::tcp_listen(llarp_tcp_acceptor* tcp, const sockaddr* addr)
|
||||
{
|
||||
conn_glue* glue = new conn_glue(m_Impl.get(), tcp, addr);
|
||||
tcp->impl = glue;
|
||||
if(glue->Server())
|
||||
return true;
|
||||
tcp->impl = nullptr;
|
||||
delete glue;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace libuv
|
||||
|
||||
llarp_ev_loop_ptr
|
||||
llarp_make_uv_loop()
|
||||
{
|
||||
auto loop = std::make_shared< libuv::Loop >();
|
||||
if(loop->init())
|
||||
return loop;
|
||||
return nullptr;
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
#ifndef LLARP_EV_LIBUV_HPP
|
||||
#include <ev/ev.hpp>
|
||||
#include <uv.h>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace libuv
|
||||
{
|
||||
struct Loop final : public llarp_ev_loop
|
||||
{
|
||||
bool
|
||||
init() override;
|
||||
|
||||
int
|
||||
run() override
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
running() const override;
|
||||
|
||||
void
|
||||
update_time() override;
|
||||
|
||||
llarp_time_t
|
||||
time_now() const override;
|
||||
|
||||
/// return false on socket error (non blocking)
|
||||
bool
|
||||
tcp_connect(llarp_tcp_connecter* tcp, const sockaddr* addr) override;
|
||||
|
||||
int
|
||||
tick(int ms) override;
|
||||
|
||||
void
|
||||
stop() override;
|
||||
|
||||
void
|
||||
stopped() override
|
||||
{
|
||||
for(const auto& func : m_CloseFuncs)
|
||||
func();
|
||||
m_CloseFuncs.clear();
|
||||
llarp::LogInfo("event loop stopped");
|
||||
}
|
||||
|
||||
bool
|
||||
udp_listen(llarp_udp_io* l, const sockaddr* src) override;
|
||||
|
||||
bool
|
||||
udp_close(llarp_udp_io* l) override;
|
||||
|
||||
/// deregister event listener
|
||||
bool
|
||||
close_ev(llarp::ev_io*) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
tun_listen(llarp_tun_io* tun) override;
|
||||
|
||||
llarp::ev_io*
|
||||
create_tun(llarp_tun_io*) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
tcp_listen(llarp_tcp_acceptor* tcp, const sockaddr* addr) override;
|
||||
|
||||
llarp::ev_io*
|
||||
bind_tcp(llarp_tcp_acceptor*, const sockaddr*) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// register event listener
|
||||
bool
|
||||
add_ev(llarp::ev_io*, bool) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
struct DestructLoop
|
||||
{
|
||||
void
|
||||
operator()(uv_loop_t* l) const
|
||||
{
|
||||
uv_loop_close(l);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr< uv_loop_t, DestructLoop > m_Impl;
|
||||
uv_timer_t m_TickTimer;
|
||||
std::atomic< bool > m_Run;
|
||||
std::vector< std::function< void(void) > > m_CloseFuncs;
|
||||
};
|
||||
|
||||
} // namespace libuv
|
||||
|
||||
#endif
|
@ -0,0 +1,55 @@
|
||||
|
||||
The windows release is signed by rick, his public key is:
|
||||
|
||||
|
||||
```
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mDMEXBhAthYJKwYBBAHaRw8BAQdACj8fXcXB+ktPL/gNRBGZajE9ycsQOiMPXigH
|
||||
0uP6BCW0G1JpY2sgViA8cmlja0Bzbm93bGlnaHQubmV0PoiQBBMWCAA4FiEEsbLw
|
||||
yIc/Y1IT8TNLwO3Icj/cNGUFAlwYQLYCGyMFCwkIBwIGFQoJCAsCBBYCAwECHgEC
|
||||
F4AACgkQwO3Icj/cNGUeCwEAuyFfehigul3So0xOuRIxldiHoqLJfSEp4kjU+8b5
|
||||
NjsBAIOC4KFpdv8CTPa/aQgRIx/UlOjJ8vMnS94XPSs2vRcDuDgEXBhAthIKKwYB
|
||||
BAGXVQEFAQEHQKT2GHP2O+q5vgXd6D4IiOu8rI+kcGllVY/0DEqGesJYAwEIB4h4
|
||||
BBgWCAAgFiEEsbLwyIc/Y1IT8TNLwO3Icj/cNGUFAlwYQLYCGwwACgkQwO3Icj/c
|
||||
NGX/tgD9GES37acIhovhMzDj0u9oU/1HqNyx4A45EQ90dP8KMN4BALBRzWXgB23t
|
||||
9r6g3ZWHQJEpF4RnmcbDbR0SxdyoCkQG
|
||||
=RdBx
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
```
|
||||
|
||||
The linux and macos releases are signed by jeff, his public key is:
|
||||
|
||||
```
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mDMEWZx2ERYJKwYBBAHaRw8BAQdAKxsq4dGzYzKJqU8Vin5d8vJF10/NG4Hziw+f
|
||||
WTbM8nC0MEplZmYgQmVja2VyIChwcm9iYWJseSBub3QgZXZpbCkgPGplZmZAaTJw
|
||||
LnJvY2tzPoh5BBMWCAAhBQJZnHYRAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheA
|
||||
AAoJEPNXs7Qvb5sFP2MBAIcL8KOd/RupEtSMyb2f4OBsaE8oFU+NsvfevW0XrBBQ
|
||||
AQDhjax9f2D0k30pj4uYBJRb/L0JJFfbzI+uwgTtgRp1DLg4BFmcdhESCisGAQQB
|
||||
l1UBBQEBB0BJOuegxPmX1Ma/nv4O2lZp0rA89EazPgtUrR3e1846DQMBCAeIYQQY
|
||||
FggACQUCWZx2EQIbDAAKCRDzV7O0L2+bBUgkAPsEeiiut+gGECP/63m7NyTwruNP
|
||||
oVZUYE1m8XXbHr28UgEA4nXGIAHDRuIUY4sRcVQz2Um9O6kaCdQHH0eSPE48VQ8=
|
||||
=gFkp
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
```
|
||||
|
||||
To verify the releases first import those keys into gpg key database
|
||||
|
||||
run the following, copy paste both keys and press `^D` (control - D) to finish
|
||||
|
||||
$ gpg --import
|
||||
|
||||
Alternatively you can get jeff's key off a key server:
|
||||
|
||||
$ gpg --recv-key 67EF6BA68E7B0B0D6EB4F7D4F357B3B42F6F9B05 # jeff's key
|
||||
|
||||
then verify the signatures, make sure that the `.sig` file and the release file
|
||||
are in the same directory.
|
||||
|
||||
$ gpg --verify release-file.exe.sig
|
Loading…
Reference in New Issue