Merge remote-tracking branch 'origin/master' into staging

pull/184/head
Jeff Becker 6 years ago
commit 49c898ed92
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -9,7 +9,7 @@ option(USE_AVX2 "enable avx2 code" )
option(USE_NETNS "enable networking namespace support" )
option(AMD_RYZEN_HACK "hack for AMD Ryzen FPU bug (support FMA3 and FMA4 in FPU, but does not show in CPUID)" )
option(STATIC_LINK "emit fully linked binaries" )
option(RPI "Build for 32-bit Raspberry Pi" )
option(NON_PC_TARGET "non-pc target build: iphone, andriod, embedded non-i386 SBC, etc" )
option(SHADOW "use shadow testing framework. linux only" )
option(ASAN "use address sanitiser, if your system has it" )
option(JEMALLOC "use jemalloc. Not required on BSD" )
@ -18,6 +18,7 @@ option(TESTNET "testnet build" )
if(WIN32)
set(CMAKE_CXX_STANDARD 17)
ENABLE_LANGUAGE(RC)
else()
set(CMAKE_CXX_STANDARD 11)
endif(WIN32)
@ -70,13 +71,13 @@ if(DEBIAN)
add_definitions(-DDEBIAN)
else()
if(NOT ANDROID)
if(NOT RPI)
if (NOT USE_AVX2)
if(NOT NON_PC_TARGET)
if (NOT USE_AVX2)
set(CRYPTO_FLAGS -march=core2 -msse4.1 -mtune=native -mfpmath=sse)
else()
set(CRYPTO_FLAGS -march=haswell -mtune=native -mfpmath=sse)
endif(NOT USE_AVX2)
endif(NOT RPI)
endif(NOT NON_PC_TARGET)
endif(NOT ANDROID)
endif(DEBIAN)
@ -147,10 +148,11 @@ if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
add_compile_options( ${DEBUG_FLAGS} )
endif(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
if(RPI)
# Add non-386 target-specific options here
if(NON_PC_TARGET)
add_definitions(-DRPI)
set(WITH_STATIC ON)
endif(RPI)
endif(NON_PC_TARGET)
add_compile_options(${OPTIMIZE_FLAGS} ${CRYPTO_FLAGS})
@ -683,8 +685,13 @@ else()
#add_executable(${CLIENT_EXE} ${CLIENT_SRC})
#add_executable(${DNS_EXE} ${DNS_SRC})
add_subdirectory(${GTEST_DIR})
if(NOT WIN32)
add_executable(${TEST_EXE} ${TEST_SRC})
add_executable(${EXE} ${EXE_SRC})
else()
add_executable(${TEST_EXE} ${TEST_SRC} llarp/version.rc)
add_executable(${EXE} ${EXE_SRC} llarp/version.rc)
endif(NOT WIN32)
target_include_directories(${TEST_EXE} PRIVATE ${GTEST_DIR}/include ${GTEST_DIR})
install(TARGETS ${EXE} RUNTIME DESTINATION bin)
if(WIN32)
@ -705,11 +712,11 @@ if(WITH_STATIC)
target_link_libraries(${PLATFORM_LIB} Threads::Threads)
endif(USE_LIBABYSS)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if(RPI)
if(NON_PC_TARGET)
target_link_libraries(${PLATFORM_LIB} -lrt)
else()
target_link_libraries(${PLATFORM_LIB} -lcap)
endif(RPI)
endif(NON_PC_TARGET)
endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
target_link_libraries(${STATIC_LIB} ${CRYPTOGRAPHY_LIB} ${LIBS} ${PLATFORM_LIB})
if(NOT WITH_SHARED)

@ -45,6 +45,14 @@ startWinsock()
}
return 0;
}
extern "C" BOOL FAR PASCAL
handle_signal_win32(DWORD fdwCtrlType)
{
UNREFERENCED_PARAMETER(fdwCtrlType);
handle_signal(SIGINT);
return TRUE; // probably unreachable
}
#endif
int
@ -60,6 +68,7 @@ main(int argc, char *argv[])
#ifdef _WIN32
if(startWinsock())
return -1;
SetConsoleCtrlHandler(handle_signal_win32, TRUE);
#endif
int opt = 0;

@ -343,8 +343,8 @@ namespace tl
using enable_assign_forward = detail::enable_if_t<
!std::is_same< optional< T >, detail::decay_t< U > >::value
&& !detail::conjunction<
std::is_scalar< T >,
std::is_same< T, detail::decay_t< U > > >::value
std::is_scalar< T >,
std::is_same< T, detail::decay_t< U > > >::value
&& std::is_constructible< T, U >::value
&& std::is_assignable< T &, U >::value >;
@ -465,7 +465,7 @@ namespace tl
0))::value &&detail::swap_adl_tests::
is_std_swap_noexcept< T >::value)
|| (!decltype(detail::swap_adl_tests::uses_std< T, U >(
0))::value &&detail::swap_adl_tests::
0))::value &&detail::swap_adl_tests::
is_adl_swap_noexcept< T, U >::value)) >
{
};

@ -257,9 +257,9 @@ namespace llarp
};
private:
using AlignedStorage =
typename std::aligned_storage< sizeof(Data),
alignof(std::max_align_t) >::type;
using AlignedStorage = typename std::aligned_storage< sizeof(Data),
alignof(uint64_t) >::
type; // why did we align to the nearest double-precision float
AlignedStorage val;
};

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

@ -58,7 +58,7 @@ bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result)
buffer->cur++;
numbuf[len] = 0;
numbuf[len] = '\0';
*result = strtoull(numbuf, nullptr, 10);
return true;
}
@ -75,7 +75,7 @@ bencode_read_string(llarp_buffer_t* buffer, llarp_buffer_t* result)
if(!len)
return false;
numbuf[len] = 0;
numbuf[len] = '\0';
num = atoi(numbuf);
if(num < 0)
return false;

@ -669,7 +669,8 @@ namespace llarp
"cannot handle exploritory router lookup, no dht peers");
return false;
}
llarp::LogDebug("We have ", nodes->Size(), " connected nodes into the DHT");
llarp::LogDebug("We have ", nodes->Size(),
" connected nodes into the DHT");
// ourKey should never be in the connected list
// requester is likely in the connected list
// 4 or connection nodes (minus a potential requestor), whatever is less

@ -39,6 +39,9 @@ llarp_ev_loop_free(struct llarp_ev_loop **ev)
{
delete *ev;
*ev = nullptr;
#ifdef _WIN32
exit_tun_loop();
#endif
}
int
@ -139,6 +142,7 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const sockaddr *to,
return ret;
}
#ifndef _WIN32
bool
llarp_ev_add_tun(struct llarp_ev_loop *loop, struct llarp_tun_io *tun)
{
@ -148,6 +152,52 @@ llarp_ev_add_tun(struct llarp_ev_loop *loop, struct llarp_tun_io *tun)
return loop->add_ev(dev, false);
return false;
}
#else
// OK, now it's time to do it my way.
// we're not even going to use the existing llarp::tun
// we still use the llarp_tun_io struct
// since we still need to branch to the
// packet processing functions
bool
llarp_ev_add_tun(llarp_ev_loop *loop, llarp_tun_io *tun)
{
UNREFERENCED_PARAMETER(loop);
auto dev = new win32_tun_io(tun);
tun->impl = dev;
// We're not even going to add this to the socket event loop
if(dev)
{
dev->setup();
return dev->add_ev(); // start up tun and add to event queue
}
return false;
}
#endif
#ifndef _WIN32
bool
llarp_ev_tun_async_write(struct llarp_tun_io *tun, llarp_buffer_t buf)
{
if(buf.sz > EV_WRITE_BUF_SZ)
{
llarp::LogWarn("packet too big, ", buf.sz, " > ", EV_WRITE_BUF_SZ);
return false;
}
return static_cast< llarp::tun * >(tun->impl)->queue_write(buf.base, buf.sz);
}
#else
bool
llarp_ev_tun_async_write(struct llarp_tun_io *tun, llarp_buffer_t buf)
{
if(buf.sz > EV_WRITE_BUF_SZ)
{
llarp::LogWarn("packet too big, ", buf.sz, " > ", EV_WRITE_BUF_SZ);
return false;
}
return static_cast< win32_tun_io * >(tun->impl)->queue_write(buf.base,
buf.sz);
}
#endif
bool
llarp_tcp_conn_async_write(struct llarp_tcp_conn *conn, llarp_buffer_t buf)
@ -231,17 +281,6 @@ llarp_tcp_acceptor_close(struct llarp_tcp_acceptor *tcp)
// dont free acceptor because it may be stack allocated
}
bool
llarp_ev_tun_async_write(struct llarp_tun_io *tun, llarp_buffer_t buf)
{
if(buf.sz > EV_WRITE_BUF_SZ)
{
llarp::LogWarn("packet too big, ", buf.sz, " > ", EV_WRITE_BUF_SZ);
return false;
}
return static_cast< llarp::tun * >(tun->impl)->queue_write(buf.base, buf.sz);
}
void
llarp_tcp_conn_close(struct llarp_tcp_conn *conn)
{

@ -19,14 +19,15 @@
#ifdef _WIN32
#include <win32_up.h>
#include <win32_upoll.h>
// io packet for TUN read/write
struct asio_evt_pkt
// 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
{
OVERLAPPED pkt = {
0, 0, 0, 0, nullptr}; // must be first, since this is part of the IO call
bool write = false; // true, or false if read pkt
size_t sz; // if this doesn't match what is in the packet, note the error
};
ADDRESS_FAMILY sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
} SOCKADDR_UN, *PSOCKADDR_UN;
#else
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
@ -118,43 +119,28 @@ namespace llarp
};
};
using LossyWriteQueue_t =
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
WriteBuffer::PutTime, WriteBuffer::Compare,
WriteBuffer::GetNow, llarp::util::NullMutex,
llarp::util::NullLock, 5, 100, 128 >;
using LosslessWriteQueue_t = std::deque< WriteBuffer >;
union {
intptr_t socket;
HANDLE tun;
} fd;
int flags = 0;
bool is_tun = false;
win32_ev_io(intptr_t f)
{
fd.socket = f;
}
intptr_t
fd; // Sockets only, fuck UNIX-style reactive IO with a rusty knife
/// for tun
win32_ev_io(HANDLE f, LossyWriteQueue_t* q) : m_LossyWriteQueue(q)
{
fd.tun = f;
}
int flags = 0;
win32_ev_io(intptr_t f) : fd(f){};
/// for tcp
win32_ev_io(intptr_t f, LosslessWriteQueue_t* q) : m_BlockingWriteQueue(q)
win32_ev_io(intptr_t f, LosslessWriteQueue_t* q)
: fd(f), m_BlockingWriteQueue(q)
{
fd.socket = f;
}
virtual void
error()
{
llarp::LogError(strerror(errno));
char ebuf[1024];
int err = WSAGetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_NEUTRAL,
ebuf, 1024, nullptr);
llarp::LogError(ebuf);
}
virtual int
@ -163,9 +149,9 @@ namespace llarp
virtual int
sendto(const sockaddr* dst, const void* data, size_t sz)
{
(void)(dst);
(void)(data);
(void)(sz);
UNREFERENCED_PARAMETER(dst);
UNREFERENCED_PARAMETER(data);
UNREFERENCED_PARAMETER(sz);
return -1;
};
@ -180,35 +166,13 @@ namespace llarp
virtual ssize_t
do_write(void* data, size_t sz)
{
if(this->is_tun)
{
DWORD x;
bool r;
asio_evt_pkt* pkt = new asio_evt_pkt;
pkt->sz = sz;
pkt->write = true;
int e = 0;
r = WriteFile(fd.tun, data, sz, &x, &pkt->pkt);
if(r) // we returned immediately
return x;
e = GetLastError();
if(e == ERROR_IO_PENDING)
return sz;
else
return -1;
}
return uwrite(fd.socket, (char*)data, sz);
return uwrite(fd, (char*)data, sz);
}
bool
queue_write(const byte_t* buf, size_t sz)
{
if(m_LossyWriteQueue)
{
m_LossyWriteQueue->Emplace(buf, sz);
return true;
}
else if(m_BlockingWriteQueue)
if(m_BlockingWriteQueue)
{
m_BlockingWriteQueue->emplace_back(buf, sz);
return true;
@ -229,13 +193,7 @@ namespace llarp
virtual void
flush_write_buffers(size_t amount)
{
if(m_LossyWriteQueue)
m_LossyWriteQueue->Process([&](WriteBuffer& buffer) {
do_write(buffer.buf, buffer.bufsz);
// if we would block we save the entries for later
// discard entry
});
else if(m_BlockingWriteQueue)
if(m_BlockingWriteQueue)
{
if(amount)
{
@ -280,11 +238,8 @@ namespace llarp
}
m_BlockingWriteQueue->pop_front();
int wsaerr = WSAGetLastError();
int syserr = GetLastError();
if(wsaerr == WSA_IO_PENDING || wsaerr == WSAEWOULDBLOCK
|| syserr == 997 || syserr == 21)
if(wsaerr == WSA_IO_PENDING || wsaerr == WSAEWOULDBLOCK)
{
SetLastError(0);
WSASetLastError(0);
return;
}
@ -292,20 +247,17 @@ namespace llarp
}
}
/// reset errno
SetLastError(0);
WSASetLastError(0);
}
std::unique_ptr< LossyWriteQueue_t > m_LossyWriteQueue;
std::unique_ptr< LosslessWriteQueue_t > m_BlockingWriteQueue;
virtual ~win32_ev_io()
{
uclose(fd.socket);
uclose(fd);
};
};
#endif
#else
struct posix_ev_io
{
struct WriteBuffer
@ -538,19 +490,11 @@ namespace llarp
close(fd);
};
};
#endif
// finally create aliases by platform
#ifdef _WIN32
using ev_io = win32_ev_io;
#define UNIX_PATH_MAX 108
typedef struct sockaddr_un
{
ADDRESS_FAMILY sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
} SOCKADDR_UN, *PSOCKADDR_UN;
#else
using ev_io = posix_ev_io;
#endif

@ -210,9 +210,7 @@ namespace llarp
flush_write()
{
if(t->before_write)
{
t->before_write(t);
}
ev_io::flush_write();
}

@ -7,12 +7,321 @@
#include <net.h>
#include <net.hpp>
#include <windows.h>
#include <process.h>
#include <cstdio>
#ifdef sizeof
#undef sizeof
#endif
// io packet for TUN read/write
struct asio_evt_pkt
{
OVERLAPPED pkt = {
0, 0, 0, 0, nullptr}; // must be first, since this is part of the IO call
bool write = false; // true, or false if read pkt
size_t sz; // should match the queued data size, if not try again?
void* buf; // must remain valid until we get notification; this is _supposed_
// to be zero-copy
};
struct win32_tun_io;
extern "C" DWORD FAR PASCAL
tun_ev_loop(void* unused);
// list of TUN listeners (useful for exits or other nodes with multiple TUNs)
std::list< win32_tun_io* > tun_listeners;
// a single event queue for the TUN interface
HANDLE tun_event_queue =
INVALID_HANDLE_VALUE; // we pass this to the event loop thread procedure
// upon setup
// we hand the kernel our thread handles to process completion events
HANDLE* kThreadPool;
void
begin_tun_loop(int nThreads)
{
kThreadPool = new HANDLE[nThreads];
for(int i = 0; i < nThreads; ++i)
{
kThreadPool[i] =
CreateThread(nullptr, 0, &tun_ev_loop, nullptr, 0, nullptr);
}
llarp::LogInfo("created ", nThreads, " threads for TUN event queue");
}
// A different kind of event loop,
// more suited for the native Windows NT
// event model
struct win32_tun_io
{
llarp_tun_io* t;
device* tunif;
byte_t readbuf[EV_READ_BUF_SZ] = {0};
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
operator()(const WriteBuffer& buf) const
{
return buf.timestamp;
}
};
struct GetNow
{
void* loop;
GetNow(void* l) : loop(l)
{
}
llarp_time_t
operator()() const
{
return llarp::time_now_ms();
}
};
struct PutTime
{
void* loop;
PutTime(void* l) : loop(l)
{
}
void
operator()(WriteBuffer& buf)
{
buf.timestamp = llarp::time_now_ms();
}
};
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, 128 >;
std::unique_ptr< LossyWriteQueue_t > m_LossyWriteQueue;
win32_tun_io(llarp_tun_io* tio) : t(tio), tunif(tuntap_init())
{
// This is not your normal everyday event loop, this is _advanced_ event
// handling :>
m_LossyWriteQueue = std::make_unique< LossyWriteQueue_t >("win32_tun_queue",
nullptr, nullptr);
};
bool
queue_write(const byte_t* buf, size_t sz)
{
if(m_LossyWriteQueue)
{
m_LossyWriteQueue->Emplace(buf, sz);
flush_write();
return true;
}
else
return false;
}
bool
setup()
{
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1)
{
llarp::LogWarn("failed to start interface");
return false;
}
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
{
llarp::LogWarn("failed to set ip");
return false;
}
if(tuntap_up(tunif) == -1)
{
char ebuf[1024];
int err = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_NEUTRAL,
ebuf, 1024, nullptr);
llarp::LogWarn("failed to put interface up: ", ebuf);
return false;
}
if(tunif->tun_fd == INVALID_HANDLE_VALUE)
return false;
return true;
}
// first TUN device gets to set up the event port
bool
add_ev()
{
if(tun_event_queue == INVALID_HANDLE_VALUE)
{
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
unsigned long numCPU = sys_info.dwNumberOfProcessors;
// let the system handle 2x the number of CPUs or hardware
// threads
tun_event_queue = CreateIoCompletionPort(tunif->tun_fd, nullptr,
(ULONG_PTR)this, numCPU * 2);
begin_tun_loop(numCPU * 2);
}
else
CreateIoCompletionPort(tunif->tun_fd, tun_event_queue, (ULONG_PTR)this,
0);
// we're already non-blocking
// add to list
tun_listeners.push_back(this);
read(readbuf, 4096);
return true;
}
// places data in event queue for kernel to process
void
do_write(void* data, size_t sz)
{
llarp::LogInfo("writing some data");
asio_evt_pkt* pkt = new asio_evt_pkt;
pkt->buf = data;
pkt->sz = sz;
pkt->write = true;
memset(&pkt->pkt, '\0', sizeof(pkt->pkt));
WriteFile(tunif->tun_fd, data, sz, nullptr, &pkt->pkt);
}
// we call this one when we get a packet in the event port
// which then kicks off another write
void
flush_write()
{
if(t->before_write)
t->before_write(t);
m_LossyWriteQueue->Process([&](WriteBuffer& buffer) {
do_write(buffer.buf, buffer.bufsz);
// we are NEVER going to block
// because Windows NT implements true async io
});
}
void
read(byte_t* buf, size_t sz)
{
asio_evt_pkt* pkt = new asio_evt_pkt;
pkt->buf = buf;
memset(&pkt->pkt, '\0', sizeof(OVERLAPPED));
pkt->sz = sz;
pkt->write = false;
ReadFile(tunif->tun_fd, buf, sz, nullptr, &pkt->pkt);
}
~win32_tun_io()
{
CancelIo(tunif->tun_fd);
if(tunif->tun_fd)
tuntap_destroy(tunif);
}
};
// and now the event loop itself
extern "C" DWORD FAR PASCAL
tun_ev_loop(void* unused)
{
UNREFERENCED_PARAMETER(unused);
DWORD size = 0;
OVERLAPPED* ovl = nullptr;
ULONG_PTR listener = 0;
asio_evt_pkt* pkt = nullptr;
BOOL alert;
while(true)
{
alert =
GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl, 100);
if(!alert)
continue; // let's go at it once more
if(listener == (ULONG_PTR)~0)
break;
// if we're here, then we got something interesting :>
pkt = (asio_evt_pkt*)ovl;
win32_tun_io* ev = reinterpret_cast< win32_tun_io* >(listener);
if(!pkt->write)
{
// llarp::LogInfo("read tun ", size, " bytes, pass to handler");
if(ev->t->recvpkt)
ev->t->recvpkt(ev->t, llarp::InitBuffer(pkt->buf, size));
ev->flush_write();
ev->read(ev->readbuf, sizeof(ev->readbuf));
}
else
{
llarp::LogInfo("write ", size, " bytes to tunnel interface");
// ok let's queue another read!
ev->read(ev->readbuf, sizeof(ev->readbuf));
}
delete pkt; // don't leak
}
llarp::LogInfo("exit TUN event loop thread from system managed thread pool");
return 0;
}
void
exit_tun_loop()
{
// if we get all-ones in the queue, thread exits, and we clean up
PostQueuedCompletionStatus(tun_event_queue, 0, ~0, nullptr);
// kill the kernel's thread pool
int i = (&kThreadPool)[1] - kThreadPool; // get the size of our thread pool
llarp::LogInfo("closing ", i, " threads");
WaitForMultipleObjects(i, kThreadPool, TRUE, INFINITE);
for(int j = 0; j < i; ++j)
CloseHandle(kThreadPool[j]);
delete[] kThreadPool;
// the IOCP refcount is decreased each time an associated fd
// is closed
// the fds are closed in their destructors
// once we get to zero, we can safely close the event port
auto itr = tun_listeners.begin();
while(itr != tun_listeners.end())
{
delete(*itr);
itr = tun_listeners.erase(itr);
}
CloseHandle(tun_event_queue);
}
namespace llarp
{
@ -22,7 +331,7 @@ namespace llarp
if(_shouldClose)
return -1;
ssize_t amount = uread(fd.socket, (char*)buf, sz);
ssize_t amount = uread(fd, (char*)buf, sz);
if(amount > 0)
{
@ -50,7 +359,7 @@ namespace llarp
{
if(_shouldClose)
return -1;
return uwrite(fd.socket, (char*)buf, sz);
return uwrite(fd, (char*)buf, sz);
}
void
@ -58,10 +367,10 @@ namespace llarp
{
socklen_t slen = sizeof(sockaddr_in);
if(_addr.ss_family == AF_UNIX)
slen = 115;
slen = sizeof(sockaddr_un);
else if(_addr.ss_family == AF_INET6)
slen = sizeof(sockaddr_in6);
int result = ::connect(fd.socket, (const sockaddr*)&_addr, slen);
int result = ::connect(fd, (const sockaddr*)&_addr, slen);
if(result == 0)
{
llarp::LogDebug("connected immedidately");
@ -89,14 +398,14 @@ namespace llarp
int
tcp_serv::read(byte_t*, size_t)
{
int new_fd = ::accept(fd.socket, nullptr, nullptr);
int new_fd = ::accept(fd, nullptr, nullptr);
if(new_fd == -1)
{
char ebuf[1024];
int err = WSAGetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_NEUTRAL,
ebuf, 1024, nullptr);
llarp::LogError("failed to accept on ", fd.socket, ":", ebuf);
llarp::LogError("failed to accept on ", fd, ":", ebuf);
return -1;
}
// build handler
@ -113,94 +422,6 @@ namespace llarp
return -1;
}
struct tun : public ev_io
{
llarp_tun_io* t;
device* tunif;
tun(llarp_tun_io* tio, llarp_ev_loop* l)
: ev_io(INVALID_HANDLE_VALUE,
new LossyWriteQueue_t("win32_tun_write_queue", l, l))
, t(tio)
, tunif(tuntap_init())
{
this->is_tun = true;
};
int
sendto(const sockaddr* to, const void* data, size_t sz)
{
UNREFERENCED_PARAMETER(to);
UNREFERENCED_PARAMETER(data);
UNREFERENCED_PARAMETER(sz);
return -1;
}
void
flush_write()
{
if(t->before_write)
{
t->before_write(t);
ev_io::flush_write();
}
}
bool
tick()
{
if(t->tick)
t->tick(t);
flush_write();
return true;
}
int
read(byte_t* buf, size_t sz)
{
ssize_t ret = tuntap_read(tunif, buf, sz);
if(ret > 0 && t->recvpkt)
// should have pktinfo
// I have no idea...
t->recvpkt(t, llarp::InitBuffer(buf, ret));
return ret;
}
bool
setup()
{
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1)
{
llarp::LogWarn("failed to start interface");
return false;
}
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
{
llarp::LogWarn("failed to set ip");
return false;
}
if(tuntap_up(tunif) == -1)
{
char ebuf[1024];
int err = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_NEUTRAL,
ebuf, 1024, nullptr);
llarp::LogWarn("failed to put interface up: ", ebuf);
return false;
}
fd.tun = tunif->tun_fd;
if(fd.tun == INVALID_HANDLE_VALUE)
return false;
// we're already non-blocking
return true;
}
~tun()
{
}
};
struct udp_listener : public ev_io
{
llarp_udp_io* udp;
@ -228,7 +449,7 @@ namespace llarp
sockaddr_in6 src;
socklen_t slen = sizeof(sockaddr_in6);
sockaddr* addr = (sockaddr*)&src;
ssize_t ret = ::recvfrom(fd.socket, (char*)b.base, sz, 0, addr, &slen);
ssize_t ret = ::recvfrom(fd, (char*)b.base, sz, 0, addr, &slen);
if(ret < 0)
return -1;
if(static_cast< size_t >(ret) > sz)
@ -253,7 +474,7 @@ namespace llarp
default:
return -1;
}
ssize_t sent = ::sendto(fd.socket, (char*)data, sz, 0, to, slen);
ssize_t sent = ::sendto(fd, (char*)data, sz, 0, to, slen);
if(sent == -1)
{
char ebuf[1024];
@ -271,9 +492,8 @@ namespace llarp
struct llarp_win32_loop : public llarp_ev_loop
{
upoll_t* upollfd;
HANDLE tun_event_queue;
llarp_win32_loop() : upollfd(nullptr), tun_event_queue(INVALID_HANDLE_VALUE)
llarp_win32_loop() : upollfd(nullptr)
{
}
@ -305,10 +525,8 @@ struct llarp_win32_loop : public llarp_ev_loop
// for now, use the ID numbers directly until this comes out of
// beta
else if(bindaddr->sa_family == AF_UNIX)
{
sz = 110; // current size in 10.0.17763, verify each time the beta PSDK
// is updated
}
sz = sizeof(sockaddr_un);
if(::bind(fd, bindaddr, sz) == -1)
{
uclose(fd);
@ -327,7 +545,7 @@ struct llarp_win32_loop : public llarp_ev_loop
{
auto ev = create_udp(l, src);
if(ev)
l->fd = ev->fd.socket;
l->fd = ev->fd;
return ev && add_ev(ev, false);
}
@ -335,14 +553,12 @@ struct llarp_win32_loop : public llarp_ev_loop
{
if(upollfd)
upoll_destroy(upollfd);
if(tun_event_queue != INVALID_HANDLE_VALUE)
CloseHandle(tun_event_queue);
}
bool
running() const
{
return (upollfd != nullptr) && (tun_event_queue != INVALID_HANDLE_VALUE);
return (upollfd != nullptr);
}
bool
@ -350,12 +566,11 @@ struct llarp_win32_loop : public llarp_ev_loop
{
if(!upollfd)
upollfd = upoll_create(1);
if(tun_event_queue == INVALID_HANDLE_VALUE)
tun_event_queue =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1024);
return upollfd && (tun_event_queue != INVALID_HANDLE_VALUE);
return upollfd != nullptr;
}
// OK, the event loop, as it exists now, will _only_
// work on sockets (and not very efficiently at that).
int
tick(int ms)
{
@ -390,29 +605,6 @@ struct llarp_win32_loop : public llarp_ev_loop
}
}
DWORD size = 0;
OVERLAPPED* ovl = nullptr;
ULONG_PTR listener = 0;
asio_evt_pkt* pkt;
while(
GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl, ms))
{
pkt = (asio_evt_pkt*)ovl;
llarp::ev_io* ev = reinterpret_cast< llarp::ev_io* >(listener);
/*if(size != pkt->sz)
llarp::LogWarn("incomplete async io operation: got ", size,
" bytes, expected ", pkt->sz, " bytes");*/
if(!pkt->write)
ev->read(readbuf, size);
else
{
ev->flush_write_buffers(pkt->sz);
printf("write tun\n");
}
++result;
delete pkt;
}
if(result != -1)
tick_listeners();
return result;
@ -509,24 +701,14 @@ struct llarp_win32_loop : public llarp_ev_loop
bool
close_ev(llarp::ev_io* ev)
{
if(ev->is_tun)
{
CancelIo(ev->fd.tun);
CloseHandle(ev->fd.tun);
return true;
}
return upoll_ctl(upollfd, UPOLL_CTL_DEL, ev->fd.socket, nullptr) != -1;
return upoll_ctl(upollfd, UPOLL_CTL_DEL, ev->fd, nullptr) != -1;
}
// no tunnels here
llarp::ev_io*
create_tun(llarp_tun_io* tun)
{
llarp::tun* t = new llarp::tun(tun, this);
if(t->setup())
{
return t;
}
delete t;
UNREFERENCED_PARAMETER(tun);
return nullptr;
}
@ -544,27 +726,16 @@ struct llarp_win32_loop : public llarp_ev_loop
bool
add_ev(llarp::ev_io* e, bool write)
{
if(e->is_tun)
{
asio_evt_pkt* pkt = new asio_evt_pkt;
pkt->write = false;
pkt->sz = sizeof(readbuf);
CreateIoCompletionPort(e->fd.tun, tun_event_queue, (ULONG_PTR)e, 1024);
// queue an initial read
ReadFile(e->fd.tun, readbuf, sizeof(readbuf), nullptr, &pkt->pkt);
goto add;
}
upoll_event_t ev;
ev.data.ptr = e;
ev.events = UPOLLIN | UPOLLERR;
if(write)
ev.events |= UPOLLOUT;
if(upoll_ctl(upollfd, UPOLL_CTL_ADD, e->fd.socket, &ev) == -1)
if(upoll_ctl(upollfd, UPOLL_CTL_ADD, e->fd, &ev) == -1)
{
delete e;
return false;
}
add:
handlers.emplace_back(e);
return true;
}
@ -596,21 +767,8 @@ struct llarp_win32_loop : public llarp_ev_loop
void
stop()
{
if(upollfd)
upoll_destroy(upollfd);
upollfd = nullptr;
if(tun_event_queue != INVALID_HANDLE_VALUE)
{
CloseHandle(tun_event_queue);
tun_event_queue = INVALID_HANDLE_VALUE;
}
// do nothing
}
};
extern "C" asio_evt_pkt*
getTunEventPkt()
{
return new asio_evt_pkt;
}
#endif

@ -9,7 +9,8 @@ namespace llarp
Endpoint::Endpoint(const llarp::PubKey& remoteIdent,
const llarp::PathID_t& beginPath, bool rewriteIP,
huint32_t ip, llarp::handlers::ExitEndpoint* parent)
: m_Parent(parent)
: createdAt(parent->Now())
, m_Parent(parent)
, m_remoteSignKey(remoteIdent)
, m_CurrentPath(beginPath)
, m_IP(ip)
@ -73,9 +74,7 @@ namespace llarp
{
if(ExpiresSoon(now, timeout))
return true;
if(now > m_LastActive)
return now - m_LastActive > timeout;
return true;
return now > m_LastActive && now - m_LastActive > timeout;
}
bool

@ -97,6 +97,8 @@ namespace llarp
return m_IP;
}
const llarp_time_t createdAt;
private:
llarp::handlers::ExitEndpoint* m_Parent;
llarp::PubKey m_remoteSignKey;

@ -132,7 +132,6 @@ namespace llarp
void
ExitEndpoint::Flush()
{
auto now = Now();
m_InetToNetwork.Process([&](Pkt_t &pkt) {
llarp::PubKey pk;
{
@ -160,20 +159,7 @@ namespace llarp
return;
}
}
llarp::exit::Endpoint *ep = nullptr;
auto range = m_ActiveExits.equal_range(pk);
auto itr = range.first;
uint64_t min = std::numeric_limits< uint64_t >::max();
/// pick non dead looking path with lowest tx rate
while(itr != range.second)
{
if(itr->second->TxRate() < min && !itr->second->LooksDead(now))
{
ep = itr->second.get();
min = ep->TxRate();
}
++itr;
}
llarp::exit::Endpoint *ep = m_ChosenExits[pk];
if(ep == nullptr)
{
@ -576,18 +562,39 @@ namespace llarp
}
}
{
// expire
auto itr = m_ActiveExits.begin();
while(itr != m_ActiveExits.end())
{
if(itr->second->IsExpired(now))
{
itr = m_ActiveExits.erase(itr);
}
else
{
itr->second->Tick(now);
++itr;
}
// pick chosen exits and tick
m_ChosenExits.clear();
itr = m_ActiveExits.begin();
while(itr != m_ActiveExits.end())
{
// do we have an exit set for this key?
if(m_ChosenExits.find(itr->first) != m_ChosenExits.end())
{
// yes
if(m_ChosenExits[itr->first]->createdAt < itr->second->createdAt)
{
// if the iterators's exit is newer use it for the chosen exit for
// key
if(!itr->second->LooksDead(now))
m_ChosenExits[itr->first] = itr->second.get();
}
}
else if(!itr->second->LooksDead(
now)) // set chosen exit if not dead for key that doesn't
// have one yet
m_ChosenExits[itr->first] = itr->second.get();
// tick which clears the tx rx counters
itr->second->Tick(now);
++itr;
}
}
}

@ -131,6 +131,11 @@ namespace llarp
std::unordered_map< llarp::PathID_t, llarp::PubKey,
llarp::PathID_t::Hash >
m_Paths;
std::unordered_map< llarp::PubKey, llarp::exit::Endpoint*,
llarp::PubKey::Hash >
m_ChosenExits;
std::unordered_multimap< llarp::PubKey,
std::unique_ptr< llarp::exit::Endpoint >,
llarp::PubKey::Hash >

@ -43,10 +43,8 @@ namespace llarp
#endif
tunif.user = this;
tunif.netmask = DefaultTunNetmask;
#ifdef _WIN32
llarp::Zero(tunif.ifaddr, sizeof(tunif.ifaddr));
llarp::Zero(tunif.ifname, sizeof(tunif.ifname));
#else
// eh this shouldn't do anything on windows anyway
strncpy(tunif.ifaddr, DefaultTunSrcAddr, sizeof(tunif.ifaddr) - 1);
strncpy(tunif.ifname, DefaultTunIfname, sizeof(tunif.ifname) - 1);
#endif
@ -671,6 +669,8 @@ namespace llarp
return pkt.Load(buf) && pkt.Header()->version == 4;
}))
{
llarp::LogInfo("invalid pkt");
llarp::DumpBuffer(buf);
}
}

@ -11,6 +11,32 @@
#include <sys/types.h> // FreeBSD needs this for uchar for ip.h
#include <netinet/in.h>
#include <netinet/ip.h>
// anything not win32
struct ip_header
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl : 4;
unsigned int version : 4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version : 4;
unsigned int ihl : 4;
#else
#error "Please fix <bits/endian.h>"
#endif
#if defined(__linux__)
#define ip_version version
#endif
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint32_t saddr;
uint32_t daddr;
};
#else
// windows nt
#include <winsock2.h>
@ -19,7 +45,7 @@ typedef struct ip_hdr
unsigned char
ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5
// (Means 20 Bytes may be 24 also)
unsigned char ip_version : 4; // 4-bit IPv4 version
unsigned char version : 4; // 4-bit IPv4 version
unsigned char ip_tos; // IP type of service
unsigned short ip_total_length; // Total length
unsigned short ip_id; // Unique identifier
@ -38,42 +64,17 @@ typedef struct ip_hdr
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR;
#define iphdr IPV4_HDR
#define ip_header IPV4_HDR
#define saddr ip_srcaddr
#define daddr ip_destaddr
#define check ip_checksum
#define ihl ip_header_len
#define ip_version version
#endif
#define protocol ip_protocol
#define frag_off ip_frag_offset
#include <memory>
// anything not win32
struct ip_header
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl : 4;
unsigned int version : 4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version : 4;
unsigned int ihl : 4;
#else
#error "Please fix <bits/endian.h>"
#endif
#if defined(__linux__)
#define ip_version version
#endif
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint32_t saddr;
uint32_t daddr;
};
#include <memory>
namespace llarp
{

@ -49,7 +49,7 @@ namespace llarp
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
short old_attrs;
#endif
Logger() : Logger(std::cout, "unnamed")
Logger() : Logger(std::cout)
{
#ifdef _WIN32
// Attempt to use ANSI escapes directly
@ -67,7 +67,7 @@ namespace llarp
#endif
}
Logger(std::ostream& o, const std::string& name) : nodeName(name), out(o)
Logger(std::ostream& o) : out(o)
{
}
};
@ -227,7 +227,9 @@ namespace llarp
#endif
#endif
std::string tag = fname;
ss << _glog.nodeName << " (" << thread_id_string() << ") "
if(_glog.nodeName.size())
ss << _glog.nodeName << " ";
ss << "(" << thread_id_string() << ") "
<< log_timestamp() << " " << tag << ":" << lineno;
ss << "\t";
LogAppend(ss, std::forward< TArgs >(args)...);

@ -18,13 +18,13 @@ namespace llarp
std::vector< std::unique_ptr< llarp::dht::IMessage > > msgs;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
BEncode(llarp_buffer_t* buf) const;
BEncode(llarp_buffer_t* buf) const override;
bool
HandleMessage(llarp::Router* router) const;
HandleMessage(llarp::Router* router) const override;
void
Clear() override;

@ -27,13 +27,13 @@ namespace llarp
operator=(const LinkIntroMessage& msg);
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
BEncode(llarp_buffer_t* buf) const;
BEncode(llarp_buffer_t* buf) const override;
bool
HandleMessage(llarp::Router* router) const;
HandleMessage(llarp::Router* router) const override;
bool
Sign(std::function< bool(Signature&, llarp_buffer_t) > signer);

@ -753,6 +753,14 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
#ifndef _WIN32
if(getifaddrs(&ifa) == -1)
#else
if(!strcmp(ifname, "lo") || !strcmp(ifname, "lo0"))
{
sockaddr_in* lo = (sockaddr_in*)addr;
lo->sin_family = af;
lo->sin_port = 0;
inet_pton(af, "127.0.0.1", &lo->sin_addr);
return true;
}
if(!getifaddrs(&ifa))
#endif
return false;

@ -42,10 +42,16 @@ namespace llarp
virtual bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop, PathRole roles);
size_t hop, PathRole roles) override;
virtual bool
ShouldBuildMore(llarp_time_t now) const;
ShouldBuildMore(llarp_time_t now) const override;
virtual bool
Stop() override;
bool
ShouldRemove() const override;
virtual bool
Stop();
@ -54,7 +60,7 @@ namespace llarp
ShouldRemove() const override;
llarp_time_t
Now() const;
Now() const override;
void
BuildOne(PathRole roles = ePathRoleAny);
@ -74,10 +80,10 @@ namespace llarp
GetTunnelEncryptionSecretKey() const;
virtual void
HandlePathBuilt(Path* p);
HandlePathBuilt(Path* p) override;
virtual void
HandlePathBuildTimeout(Path* p);
HandlePathBuildTimeout(Path* p) override;
};
} // namespace path

@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by version.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

@ -78,22 +78,22 @@ namespace llarp
Name() const;
bool
ShouldPublishDescriptors(llarp_time_t now) const;
ShouldPublishDescriptors(llarp_time_t now) const override;
void
EnsureReplyPath(const ServiceInfo& addr);
bool
PublishIntroSet(llarp::Router* r);
PublishIntroSet(llarp::Router* r) override;
bool
PublishIntroSetVia(llarp::Router* r, path::Path* p);
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg) override;
bool
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg);
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg) override;
bool
HandleHiddenServiceFrame(path::Path* p,
@ -120,7 +120,7 @@ namespace llarp
ForgetPathToService(const Address& remote);
bool
HandleDataMessage(const PathID_t&, ProtocolMessage* msg);
HandleDataMessage(const PathID_t&, ProtocolMessage* msg) override;
virtual bool
HandleWriteIPPacket(llarp_buffer_t pkt,
@ -129,9 +129,6 @@ namespace llarp
bool
ProcessDataMessage(ProtocolMessage* msg);
bool
HandleDataMessage(const PathID_t&);
/// ensure that we know a router, looks up if it doesn't
void
EnsureRouterIsKnown(const RouterID& router);
@ -151,10 +148,10 @@ namespace llarp
}
void
PutLookup(IServiceLookup* lookup, uint64_t txid);
PutLookup(IServiceLookup* lookup, uint64_t txid) override;
void
HandlePathBuilt(path::Path* path);
HandlePathBuilt(path::Path* path) override;
bool
SendToServiceOrQueue(const byte_t* addr, llarp_buffer_t payload,
@ -350,27 +347,27 @@ namespace llarp
HasPathToSNode(const RouterID& remote) const;
void
PutSenderFor(const ConvoTag& tag, const ServiceInfo& info);
PutSenderFor(const ConvoTag& tag, const ServiceInfo& info) override;
bool
GetCachedSessionKeyFor(const ConvoTag& remote,
const byte_t*& secret) const;
const byte_t*& secret) const override;
void
PutCachedSessionKeyFor(const ConvoTag& remote,
const SharedSecret& secret);
const SharedSecret& secret) override;
bool
GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const;
GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const override;
void
PutIntroFor(const ConvoTag& remote, const Introduction& intro);
PutIntroFor(const ConvoTag& remote, const Introduction& intro) override;
bool
GetIntroFor(const ConvoTag& remote, Introduction& intro) const;
GetIntroFor(const ConvoTag& remote, Introduction& intro) const override;
bool
GetConvoTagsForService(const ServiceInfo& si,
std::set< ConvoTag >& tag) const;
std::set< ConvoTag >& tag) const override;
void
PutNewOutboundContext(const IntroSet& introset);

@ -0,0 +1,99 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#include <winresrc.h>
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE 1033,1
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,3,1,0
PRODUCTVERSION 0,3,1,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x3L
#else
FILEFLAGS 0x2L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "includes relay/exit functionality, such code is highly experimental on non UNIX/Linux/Macintosh targets!"
VALUE "CompanyName", "Loki Foundation"
VALUE "FileDescription", "LokiNET daemon for Microsoft® Windows® NT™"
VALUE "FileVersion", "0.3.1-dev"
VALUE "InternalName", "llarpd"
VALUE "LegalCopyright", "Copyright ©2018 Loki Foundation, Jeff Becker, Rick V. All rights reserved. This software is provided under the terms of the zlib-libpng licence; see the file LICENSE for details."
VALUE "OriginalFilename", "llarpd.exe"
VALUE "ProductName", "LokiNET for Windows"
VALUE "ProductVersion", "0.3.1-dev"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// RT_MANIFEST
//
1 RT_MANIFEST "app.xml"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

@ -3,6 +3,7 @@
#pragma GCC diagnostic ignored "-Wvla"
/* emulated epoll, because the native async event system does not do
* particularly well with notification
* update: now win32-exclusive
*/
#include "win32_upoll.h"
@ -172,75 +173,6 @@ upoll_ctl(upoll_t* upq, int op, intptr_t fd, upoll_event_t* event)
return 0;
}
#if defined(HAVE_POLL)
int
upoll_wait_poll(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
{
/* FD_SETSIZE should be smaller than OPEN_MAX, but OPEN_MAX isn't portable */
if(nev > FD_SETSIZE)
nev = FD_SETSIZE;
unote_t* nvec[nev];
int r, i, nfds = 0;
uint32_t hint;
struct pollfd pfds[nev];
unote_t* n = NULL;
ulist_t* s = ulist_mark(&upq->alive);
ulist_t* q = ulist_next(&upq->alive);
while(q != s && nfds < nev)
{
n = ulist_data(q, unote_t, queue);
q = ulist_next(q);
ulist_remove(&n->queue);
ulist_insert(&upq->alive, &n->queue);
nvec[nfds] = n;
pfds[nfds].events = 0;
pfds[nfds].fd = n->fd;
if(n->event.events & UPOLLIN)
{
pfds[nfds].events |= POLLIN;
}
if(n->event.events & UPOLLOUT)
{
pfds[nfds].events |= POLLOUT;
}
nfds++;
}
r = poll(pfds, nfds, timeout);
if(r < 0)
return -errno;
int e = 0;
for(i = 0; i < nfds && e < nev; i++)
{
hint = 0;
if(pfds[i].revents)
{
n = nvec[i];
if(pfds[i].revents & POLLIN)
hint |= UPOLLIN;
if(pfds[i].revents & POLLOUT)
hint |= UPOLLOUT;
if(pfds[i].revents & (POLLERR | POLLNVAL | POLLHUP))
hint |= (UPOLLERR | UPOLLIN);
if(hint & UPOLLERR)
hint &= ~UPOLLOUT;
evs[e].data = n->event.data;
evs[e].events = hint;
++e;
}
}
return e;
}
#else
int
upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
{
@ -302,21 +234,13 @@ upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
nfds++;
}
#if defined(__WINDOWS__)
int rc = select(0, &pollin, &pollout, &pollerr, tvp);
if(rc == SOCKET_ERROR)
{
assert(WSAGetLastError() == WSAENOTSOCK);
return -WSAGetLastError();
}
#else
int rc = select(maxfd + 1, &pollin, &pollout, &pollerr, tvp);
if(rc == -1)
{
assert(errno == EINTR || errno == EBADF);
return -errno;
}
#endif
e = 0;
for(i = 0; i < nfds && e < nev; i++)
{
@ -345,17 +269,12 @@ upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
}
return e;
}
#endif
int
upoll_wait(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
{
int r = 0;
#if defined(HAVE_POLL)
r = upoll_wait_poll(upq, evs, nev, timeout);
#else
r = upoll_wait_select(upq, evs, nev, timeout);
#endif
r = upoll_wait_select(upq, evs, nev, timeout);
return r;
}
@ -364,20 +283,12 @@ usocket(int domain, int type, int proto)
{
intptr_t fd = (intptr_t)socket(domain, type, proto);
#if defined(__WINDOWS__)
if(fd < 0)
return -WSAGetLastError();
unsigned long flags = 1;
int rc = ioctlsocket((SOCKET)fd, FIONBIO, &flags);
if(rc < 0)
return -WSAGetLastError();
#else
if(fd < 0)
return -errno;
int rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
if(rc < 0)
return -errno;
#endif
return fd;
}
@ -391,12 +302,8 @@ ubind(intptr_t fd, const char* host, const char* serv)
int optval = 0;
unsigned int optlen = sizeof(optval);
#if defined(__WINDOWS__)
int rc = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, (char*)&optval,
(int*)&optlen);
#else
int rc = getsockopt(fd, SOL_SOCKET, SO_TYPE, &optval, &optlen);
#endif
hint.ai_family = AF_INET;
hint.ai_socktype = optval;
@ -406,25 +313,15 @@ ubind(intptr_t fd, const char* host, const char* serv)
optval = 1;
if(!rc)
{
#if defined(__WINDOWS__)
rc = setsockopt((SOCKET)fd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval,
sizeof(optval));
#else
rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
#endif
if(!rc)
rc = bind(fd, info->ai_addr, info->ai_addrlen);
}
freeaddrinfo(info);
if(rc)
{
#if defined(__WINDOWS__)
return WSAGetLastError();
#else
return errno;
#endif
}
return 0;
}
@ -439,11 +336,7 @@ uconnect(intptr_t fd, const char* host, const char* serv)
int optval = 0;
unsigned int optlen;
#if defined(__WINDOWS__)
int rc = getsockopt(fd, SOL_SOCKET, SO_TYPE, (char*)&optval, (int*)&optlen);
#else
int rc = getsockopt(fd, SOL_SOCKET, SO_TYPE, &optval, &optlen);
#endif
hint.ai_family = AF_INET;
hint.ai_socktype = optval;
@ -451,25 +344,14 @@ uconnect(intptr_t fd, const char* host, const char* serv)
rc = getaddrinfo(host, serv, &hint, &info);
if(!rc)
{
#if defined(__WINDOWS__)
rc = connect((SOCKET)fd, info->ai_addr, info->ai_addrlen);
#else
rc = connect(fd, info->ai_addr, info->ai_addrlen);
#endif
}
freeaddrinfo(info);
if(rc)
{
#if defined(__WINDOWS__)
if(WSAGetLastError() != WSAEWOULDBLOCK)
return WSAGetLastError();
#else
if(errno != EINPROGRESS)
return errno;
#endif
}
return 0;
}
@ -488,15 +370,9 @@ uaccept(intptr_t sock)
addr.sa_family = AF_INET;
socklen_t addr_len;
#if defined(__WINDOWS__)
intptr_t fd = (intptr_t)accept((SOCKET)sock, &addr, &addr_len);
if(fd == -1)
return WSAGetLastError();
#else
intptr_t fd = accept(sock, &addr, &addr_len);
if(fd < 0)
return errno;
#endif
return fd;
}
@ -504,11 +380,7 @@ uaccept(intptr_t sock)
int
uclose(intptr_t sock)
{
#if defined(__WINDOWS__)
return closesocket((SOCKET)sock);
#else
return close(sock);
#endif
}
int
@ -573,7 +445,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* add argument make_overlapped
*/
#if defined(__WINDOWS__)
int
usocketpair(intptr_t socks[2], int async)
{
@ -646,28 +517,4 @@ usocketpair(intptr_t socks[2], int async)
socks[0] = socks[1] = -1;
return SOCKET_ERROR;
}
#else
int
usocketpair(intptr_t socks[2], int dummy)
{
int sovec[2];
if(socks == 0)
{
errno = EINVAL;
return -1;
}
dummy = socketpair(AF_LOCAL, SOCK_STREAM, 0, sovec);
if(dummy)
{
socks[0] = socks[1] = -1;
}
else
{
socks[0] = sovec[0];
socks[1] = sovec[1];
}
return dummy;
}
#endif
#endif

@ -28,38 +28,20 @@
#include <fcntl.h>
#include <sys/stat.h>
#if defined(__WINDOWS__)
// this is probably big enough to get
// the lesser of 4096 sockets or whatever
// the system allows
#ifndef FD_SETSIZE
#define FD_SETSIZE 4096
#endif
#include <io.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#else
#include <unistd.h>
#include <stdint.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#endif
#if defined(__linux__)
#undef HAVE_EPOLL
#define HAVE_EPOLL 1
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#undef HAVE_POLL
#define HAVE_POLL 1
#else
#undef HAVE_SELECT
#define HAVE_SELECT 1
#endif
#if defined(HAVE_EPOLL)
#include <sys/epoll.h>
#elif defined(HAVE_POLL)
#include <poll.h>
#endif
typedef struct unote unote_t;
typedef struct ulist ulist_t;

@ -268,6 +268,7 @@ tuntap_get_hwaddr(struct device *dev)
return (char *)hwaddr;
}
/* Isn't this an ioctl? */
int
tuntap_set_hwaddr(struct device *dev, const char *hwaddr)
{
@ -338,6 +339,7 @@ tuntap_get_mtu(struct device *dev)
return 0;
}
/* I _think_ it's possible to do this on windows, might be a setting in the reg db */
int
tuntap_set_mtu(struct device *dev, int mtu)
{
@ -415,6 +417,7 @@ tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask)
return 0;
}
/* To be implemented at a later time? I'm not quite certain TAP-Windows v9.x supports inet6 */
int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s, uint32_t mask)
{
@ -426,52 +429,25 @@ tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s, uint32_t mask)
return -1;
}
/* Anything below this comment is unimplemented, either due to lack of OS support, or duplicated functionality elsewhere */
int
tuntap_read(struct device *dev, void *buf, size_t size)
{
DWORD x;
BOOL r;
int e = 0;
struct asio_evt_pkt *pkt = getTunEventPkt();
pkt->write = FALSE;
pkt->sz = size;
if(size)
{
r = ReadFile(dev->tun_fd, buf, (DWORD)size, &x, &pkt->pkt);
if(r)
return x;
e = GetLastError();
if(e && e != 997)
{
tuntap_log(TUNTAP_LOG_ERR,
(const char *)formated_error(L"%1%0", _doserrno));
return -1;
}
}
else
return -1; // unreachable
return size;
// We read and write to TUN directly
UNREFERENCED_PARAMETER(dev);
UNREFERENCED_PARAMETER(buf);
UNREFERENCED_PARAMETER(size);
return -1;
}
int
tuntap_write(struct device *dev, void *buf, size_t size)
{
DWORD x;
if(size)
{
WriteFile(dev->tun_fd, buf, (DWORD)size, &x, NULL);
int errcode = GetLastError();
if(errcode)
{
tuntap_log(TUNTAP_LOG_ERR,
(const char *)formated_error(L"%1%0", errcode));
return -1;
}
}
else
return -1;
return x;
// We read and write to TUN directly
UNREFERENCED_PARAMETER(dev);
UNREFERENCED_PARAMETER(buf);
UNREFERENCED_PARAMETER(size);
return -1;
}
int

@ -43,7 +43,6 @@ InternalCompressLevel=ultra64
MinVersion=0,5.0
ArchitecturesInstallIn64BitMode=x64
VersionInfoCopyright=Copyright ©2018 Loki Project
AlwaysRestart=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
@ -57,10 +56,8 @@ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescrip
Source: "{#DevPath}build\lokinet.exe"; DestDir: "{app}"; Flags: ignoreversion 32bit; Check: not IsWin64
Source: "{#DevPath}build64\lokinet.exe"; DestDir: "{app}"; Flags: ignoreversion 64bit; Check: IsWin64
; eh, might as well ship the 32-bit port of everything else
; do we _need_ to ship these?
Source: "{#DevPath}build\dns.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#DevPath}build\llarpc.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#DevPath}build\rcutil.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#DevPath}build\testAll.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#DevPath}LICENSE"; DestDir: "{app}"; Flags: ignoreversion
; delet this after finishing setup, we only need it to extract the drivers
; and download an initial RC
Source: "{#DevPath}lokinet-bootstrap.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
@ -68,8 +65,8 @@ Source: "{#DevPath}win32-setup\7z.exe"; DestDir: "{tmp}"; Flags: deleteafterinst
; if nonexistent, then inet6 was already installed
Source: "{tmp}\inet6.7z"; DestDir: "{app}"; Flags: ignoreversion external deleteafterinstall skipifsourcedoesntexist; MinVersion: 0,5.0; OnlyBelowVersion: 0,5.1
; Copy the correct tuntap driver for the selected platform
Source: "{tmp}\tuntapv9.7z"; DestDir: "{app}"; Flags: ignoreversion external deleteafterinstall; OnlyBelowVersion: 0, 6.0
Source: "{tmp}\tuntapv9_n6.7z"; DestDir: "{app}"; Flags: ignoreversion external deleteafterinstall; MinVersion: 0,6.0
Source: "{tmp}\tuntapv9.7z"; DestDir: "{app}"; Flags: ignoreversion external deleteafterinstall skipifsourcedoesntexist; OnlyBelowVersion: 0, 6.0
Source: "{tmp}\tuntapv9_n6.7z"; DestDir: "{app}"; Flags: ignoreversion external deleteafterinstall skipifsourcedoesntexist; MinVersion: 0,6.0
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
@ -96,7 +93,7 @@ begin
GetWindowsVersionEx(Version);
if Version.NTPlatform and (Version.Major = 5) and (Version.Minor = 0) and (FileExists(ExpandConstant('{tmp}\inet6.7z')) = true) then
// I need a better message...
MsgBox('Set up IPv6 in Network Connections after reboot.', mbInformation, MB_OK);
MsgBox('Restart your computer, then set up IPv6 in Network Connections.\n[Adapter] > Properties > Install... > Protocol > Microsoft IPv6 Driver...', mbInformation, MB_OK);
end;
end;
@ -106,26 +103,31 @@ var
S: String;
begin
GetWindowsVersionEx(Version);
// if we already have a generic openvpn tap driver installed, then skip all the downloading
// lokinet is coded to enumerate all generic tap virtual adapters and use the first free device
if (FileExists(ExpandConstant('{sys}\drivers\tap0901.sys')) = false) then
begin
if Version.NTPlatform and
(Version.Major < 6) then
begin
// Windows 2000, XP, .NET Svr 2003
// these have a horribly crippled WinInet that issues Triple-DES as its most secure
// these have a horribly crippled WinInet that issues TLSv1-RSA-SHA1-Triple-DES as its most secure
// cipher suite
idpAddFile('http://www.rvx86.net/files/tuntapv9.7z', ExpandConstant('{tmp}\tuntapv9.7z'));
// Windows 2000 only, we need to install inet6 separately
if (FileExists(ExpandConstant('{sys}\drivers\tcpip6.sys')) = false) and (Version.Major = 5) and (Version.Minor = 0) then
begin
idpAddFile('http://www.rvx86.net/files/inet6.7z', ExpandConstant('{tmp}\inet6.7z'));
end;
end
else
begin
// current versions of windows :-)
// (Arguably, one could pull this from any of the forks.)
idpAddFile('https://github.com/despair86/loki-network/raw/master/contrib/tuntapv9-ndis/tap-windows-9.21.2.7z', ExpandConstant('{tmp}\tuntapv9_n6.7z'));
end;
// Windows 2000 only, we need to install inet6 separately
if (FileExists(ExpandConstant('{sys}\drivers\tcpip6.sys')) = false) and (Version.Major = 5) and (Version.Minor = 0) then
begin
idpAddFile('http://www.rvx86.net/files/inet6.7z', ExpandConstant('{tmp}\inet6.7z'));
end;
idpDownloadAfter(wpReady);
end;
end;
[Icons]
@ -139,14 +141,14 @@ Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBa
[Run]
Filename: "{app}\{#MyAppExeName}"; Flags: nowait postinstall skipifsilent; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"
; wait until either one or two of these terminates
Filename: "{tmp}\7z.exe"; Parameters: "x tuntapv9.7z"; WorkingDir: "{app}"; Flags: runascurrentuser waituntilterminated; Description: "extract TUN/TAP-v9 driver"; StatusMsg: "Extracting driver..."; OnlyBelowVersion: 0, 6.0
Filename: "{tmp}\7z.exe"; Parameters: "x tuntapv9_n6.7z"; WorkingDir: "{app}"; Flags: runascurrentuser waituntilterminated; Description: "extract TUN/TAP-v9 driver"; StatusMsg: "Extracting driver..."; MinVersion: 0, 6.0
Filename: "{tmp}\7z.exe"; Parameters: "x inet6.7z"; WorkingDir: "{app}"; Flags: skipifdoesntexist runascurrentuser waituntilterminated; Description: "extract inet6 driver"; StatusMsg: "Extracting IPv6 driver..."; MinVersion: 0, 5.0; OnlyBelowVersion: 0, 5.1
Filename: "{tmp}\7z.exe"; Parameters: "x tuntapv9.7z"; WorkingDir: "{app}"; Flags: runascurrentuser waituntilterminated skipifdoesntexist; Description: "extract TUN/TAP-v9 driver"; StatusMsg: "Extracting driver..."; OnlyBelowVersion: 0, 6.0
Filename: "{tmp}\7z.exe"; Parameters: "x tuntapv9_n6.7z"; WorkingDir: "{app}"; Flags: runascurrentuser waituntilterminated skipifdoesntexist; Description: "extract TUN/TAP-v9 driver"; StatusMsg: "Extracting driver..."; MinVersion: 0, 6.0
Filename: "{tmp}\7z.exe"; Parameters: "x inet6.7z"; WorkingDir: "{app}"; Flags: skipifdoesntexist runascurrentuser waituntilterminated skipifdoesntexist; Description: "extract inet6 driver"; StatusMsg: "Extracting IPv6 driver..."; MinVersion: 0, 5.0; OnlyBelowVersion: 0, 5.1
Filename: "{tmp}\lokinet-bootstrap.exe"; WorkingDir: "{app}"; Flags: runascurrentuser waituntilterminated; Description: "bootstrap dht"; StatusMsg: "Downloading initial RC..."
; then ask to install drivers
Filename: "{app}\tap-windows-9.9.2\install.bat"; WorkingDir: "{app}\tap-windows-9.9.2\"; Flags: runascurrentuser waituntilterminated; Description: "Install TUN/TAP-v9 driver"; StatusMsg: "Installing driver..."; OnlyBelowVersion: 0, 6.0
Filename: "{app}\tap-windows-9.21.2\install.bat"; WorkingDir: "{app}\tap-windows-9.21.2\"; Flags: runascurrentuser waituntilterminated; Description: "Install TUN/TAP-v9 driver"; StatusMsg: "Installing driver..."; MinVersion: 0, 6.0
Filename: "{app}\tap-windows-9.9.2\install.bat"; WorkingDir: "{app}\tap-windows-9.9.2\"; Flags: runascurrentuser waituntilterminated skipifdoesntexist; Description: "Install TUN/TAP-v9 driver"; StatusMsg: "Installing driver..."; OnlyBelowVersion: 0, 6.0; Check: not FileExists(ExpandConstant('{sys}\drivers\tap0901.sys'))
Filename: "{app}\tap-windows-9.21.2\install.bat"; WorkingDir: "{app}\tap-windows-9.21.2\"; Flags: runascurrentuser waituntilterminated skipifdoesntexist; Description: "Install TUN/TAP-v9 driver"; StatusMsg: "Installing driver..."; MinVersion: 0, 6.0; Check: not FileExists(ExpandConstant('{sys}\drivers\tap0901.sys'))
; install inet6 if not present. (I'd assume netsh displays something helpful if inet6 is already set up and configured.)
; if it doesn't exist, then the inet6 driver appears to be installed
Filename: "{app}\inet6_driver\setup\hotfix.exe"; Parameters: "/m /z"; WorkingDir: "{app}\inet6_driver\setup\"; Flags: runascurrentuser waituntilterminated skipifdoesntexist; Description: "Install IPv6 driver"; StatusMsg: "Installing IPv6..."; OnlyBelowVersion: 0, 5.1
Filename: "{app}\inet6_driver\setup\hotfix.exe"; Parameters: "/m /z"; WorkingDir: "{app}\inet6_driver\setup\"; Flags: runascurrentuser waituntilterminated skipifdoesntexist; Description: "Install IPv6 driver"; StatusMsg: "Installing IPv6..."; OnlyBelowVersion: 0, 5.1; Check: not FileExists(ExpandConstant('{sys}\drivers\tcpip6.sys'))
Filename: "{sys}\netsh.exe"; Parameters: "int ipv6 install"; Flags: runascurrentuser waituntilterminated; Description: "install ipv6 on whistler"; StatusMsg: "Installing IPv6..."; MinVersion: 0,5.1; OnlyBelowVersion: 0,6.0
Loading…
Cancel
Save