Skip to content

Commit

Permalink
Merge pull request #1748 from majestrate/liblokinet-udp-api-2021-09-19
Browse files Browse the repository at this point in the history
liblokinet updates
  • Loading branch information
majestrate committed Feb 6, 2022
2 parents fbb0ed8 + 04b2341 commit 838183e
Show file tree
Hide file tree
Showing 23 changed files with 1,214 additions and 190 deletions.
19 changes: 15 additions & 4 deletions CMakeLists.txt
Expand Up @@ -5,8 +5,11 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Has to be set before `project()`, and ignored on non-macos:
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12 CACHE STRING "macOS deployment target (Apple clang only)")

option(BUILD_DAEMON "build lokinet daemon and associated utils" ON)


set(LANGS C CXX)
if(APPLE)
if(APPLE AND BUILD_DAEMON)
set(LANGS ${LANGS} OBJC Swift)
endif()

Expand Down Expand Up @@ -43,6 +46,12 @@ endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

set(DEFAULT_WITH_BOOTSTRAP ON)
if(APPLE)
set(DEFAULT_WITH_BOOTSTRAP OFF)
endif()


# Core options
option(USE_AVX2 "enable avx2 code" OFF)
option(USE_NETNS "enable networking namespace support. Linux only" OFF)
Expand All @@ -60,6 +69,7 @@ option(TRACY_ROOT "include tracy profiler source" OFF)
option(WITH_TESTS "build unit tests" OFF)
option(WITH_HIVE "build simulation stubs" OFF)
option(BUILD_PACKAGE "builds extra components for making an installer (with 'make package')" OFF)
option(WITH_BOOTSTRAP "build lokinet-bootstrap tool" ${DEFAULT_WITH_BOOTSTRAP})

include(cmake/enable_lto.cmake)

Expand Down Expand Up @@ -182,7 +192,7 @@ if(OXENMQ_FOUND)
message(STATUS "Found system liboxenmq ${OXENMQ_VERSION}")
else()
message(STATUS "using oxenmq submodule")
add_subdirectory(${CMAKE_SOURCE_DIR}/external/oxen-mq)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/oxen-mq)
endif()


Expand Down Expand Up @@ -327,8 +337,9 @@ endif()

add_subdirectory(crypto)
add_subdirectory(llarp)
add_subdirectory(daemon)

if(BUILD_DAEMON)
add_subdirectory(daemon)
endif()

if(WITH_HIVE)
add_subdirectory(pybind)
Expand Down
5 changes: 4 additions & 1 deletion cmake/StaticBuild.cmake
Expand Up @@ -294,7 +294,6 @@ build_external(expat
)
add_static_target(expat expat_external libexpat.a)


build_external(unbound
DEPENDS openssl_external expat_external
CONFIGURE_COMMAND ./configure ${cross_host} ${cross_rc} --prefix=${DEPS_DESTDIR} --disable-shared
Expand Down Expand Up @@ -352,6 +351,10 @@ set_target_properties(libzmq PROPERTIES
INTERFACE_LINK_LIBRARIES "${libzmq_link_libs}"
INTERFACE_COMPILE_DEFINITIONS "ZMQ_STATIC")

if(NOT WITH_BOOTSTRAP)
return()
endif()

set(curl_extra)
if(WIN32)
set(curl_ssl_opts --without-ssl --with-schannel)
Expand Down
10 changes: 10 additions & 0 deletions contrib/liblokinet/CMakeLists.txt
@@ -0,0 +1,10 @@

cmake_minimum_required(VERSION 3.10)

project(udptest LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
add_executable(udptest udptest.cpp)
include_directories(../../include)
target_link_libraries(udptest PUBLIC lokinet)

13 changes: 13 additions & 0 deletions contrib/liblokinet/readme.md
@@ -0,0 +1,13 @@
# liblokinet examples

building:

$ mkdir -p build
$ cd build
$ cp /path/to/liblokinet.so .
$ cmake .. -DCMAKE_EXE_LINKER_FLAGS='-L.'
$ make

running:

$ ./udptest /path/to/bootstrap.signed
239 changes: 239 additions & 0 deletions contrib/liblokinet/udptest.cpp
@@ -0,0 +1,239 @@
#include <lokinet.h>

#include <signal.h>

#include <memory>
#include <stdexcept>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <cstring>
#include <algorithm>

bool _run{true};

using Lokinet_ptr = std::shared_ptr<lokinet_context>;

[[nodiscard]] auto
MakeLokinet(const std::vector<char>& bootstrap)
{
auto ctx = std::shared_ptr<lokinet_context>(lokinet_context_new(), lokinet_context_free);
if (auto err = lokinet_add_bootstrap_rc(bootstrap.data(), bootstrap.size(), ctx.get()))
throw std::runtime_error{strerror(err)};
if (lokinet_context_start(ctx.get()))
throw std::runtime_error{"could not start context"};
return ctx;
}

void
WaitForReady(const Lokinet_ptr& ctx)
{
while (_run and lokinet_wait_for_ready(1000, ctx.get()))
{
std::cout << "waiting for context..." << std::endl;
}
}

class Flow
{
lokinet_udp_flowinfo const _info;
lokinet_context* const _ctx;

public:
explicit Flow(const lokinet_udp_flowinfo* info, lokinet_context* ctx) : _info{*info}, _ctx{ctx}
{}

lokinet_context*
Context() const
{
return _ctx;
}

std::string
String() const
{
std::stringstream ss;
ss << std::string{_info.remote_host} << ":" << std::to_string(_info.remote_port)
<< " on socket " << _info.socket_id;
return ss.str();
}
};

struct ConnectJob
{
lokinet_udp_flowinfo remote;
lokinet_context* ctx;
};

void
CreateOutboundFlow(void* user, void** flowdata, int* timeout)
{
auto* job = static_cast<ConnectJob*>(user);
Flow* flow = new Flow{&job->remote, job->ctx};
*flowdata = flow;
*timeout = 30;
std::cout << "made outbound flow: " << flow->String() << std::endl;
;
}

int
ProcessNewInboundFlow(void* user, const lokinet_udp_flowinfo* remote, void** flowdata, int* timeout)
{
auto* ctx = static_cast<lokinet_context*>(user);
Flow* flow = new Flow{remote, ctx};
std::cout << "new udp flow: " << flow->String() << std::endl;
*flowdata = flow;
*timeout = 30;

return 0;
}

void
DeleteFlow(const lokinet_udp_flowinfo* remote, void* flowdata)
{
auto* flow = static_cast<Flow*>(flowdata);
std::cout << "udp flow from " << flow->String() << " timed out" << std::endl;
delete flow;
}

void
HandleUDPPacket(const lokinet_udp_flowinfo* remote, const char* pkt, size_t len, void* flowdata)
{
auto* flow = static_cast<Flow*>(flowdata);
std::cout << "we got " << len << " bytes of udp from " << flow->String() << std::endl;
}

void
BounceUDPPacket(const lokinet_udp_flowinfo* remote, const char* pkt, size_t len, void* flowdata)
{
auto* flow = static_cast<Flow*>(flowdata);
std::cout << "bounce " << len << " bytes of udp from " << flow->String() << std::endl;
if (auto err = lokinet_udp_flow_send(remote, pkt, len, flow->Context()))
{
std::cout << "bounce failed: " << strerror(err) << std::endl;
}
}

Lokinet_ptr sender, recip;

void
signal_handler(int)
{
_run = false;
}

int
main(int argc, char* argv[])
{
if (argc == 1)
{
std::cout << "usage: " << argv[0] << " bootstrap.signed" << std::endl;
return 1;
}

/*
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
*/

std::vector<char> bootstrap;

// load bootstrap.signed
{
std::ifstream inf{argv[1], std::ifstream::ate | std::ifstream::binary};
size_t len = inf.tellg();
inf.seekg(0);
bootstrap.resize(len);
inf.read(bootstrap.data(), bootstrap.size());
}

if (auto* loglevel = getenv("LOKINET_LOG"))
lokinet_log_level(loglevel);
else
lokinet_log_level("none");

std::cout << "starting up" << std::endl;

recip = MakeLokinet(bootstrap);
WaitForReady(recip);

lokinet_udp_bind_result recipBindResult{};

const auto port = 10000;

if (auto err = lokinet_udp_bind(
port,
ProcessNewInboundFlow,
BounceUDPPacket,
DeleteFlow,
recip.get(),
&recipBindResult,
recip.get()))
{
std::cout << "failed to bind recip udp socket " << strerror(err) << std::endl;
return 0;
}

std::cout << "bound recip udp" << std::endl;

sender = MakeLokinet(bootstrap);
WaitForReady(sender);

std::string recipaddr{lokinet_address(recip.get())};

std::cout << "recip ready at " << recipaddr << std::endl;

lokinet_udp_bind_result senderBindResult{};

if (auto err = lokinet_udp_bind(
port,
ProcessNewInboundFlow,
HandleUDPPacket,
DeleteFlow,
sender.get(),
&senderBindResult,
sender.get()))
{
std::cout << "failed to bind sender udp socket " << strerror(err) << std::endl;
return 0;
}

ConnectJob connect{};
connect.remote.socket_id = senderBindResult.socket_id;
connect.remote.remote_port = port;
std::copy_n(recipaddr.c_str(), recipaddr.size(), connect.remote.remote_host);
connect.ctx = sender.get();

std::cout << "bound sender udp" << std::endl;

do
{
std::cout << "try establish to " << connect.remote.remote_host << std::endl;
if (auto err =
lokinet_udp_establish(CreateOutboundFlow, &connect, &connect.remote, sender.get()))
{
std::cout << "failed to establish to recip: " << strerror(err) << std::endl;
usleep(100000);
}
else
break;
} while (true);
std::cout << "sender established" << std::endl;

const std::string buf{"liblokinet"};

const std::string senderAddr{lokinet_address(sender.get())};

do
{
std::cout << senderAddr << " send to remote: " << buf << std::endl;
if (auto err = lokinet_udp_flow_send(&connect.remote, buf.data(), buf.size(), sender.get()))
{
std::cout << "send failed: " << strerror(err) << std::endl;
}
usleep(100000);
} while (_run);
return 0;
}
14 changes: 4 additions & 10 deletions daemon/CMakeLists.txt
@@ -1,8 +1,3 @@
set(DEFAULT_WITH_BOOTSTRAP ON)
if(APPLE)
set(DEFAULT_WITH_BOOTSTRAP OFF)
endif()
option(WITH_BOOTSTRAP "build lokinet-bootstrap tool" ${DEFAULT_WITH_BOOTSTRAP})

add_executable(lokinet-vpn lokinet-vpn.cpp)
if(APPLE)
Expand All @@ -11,11 +6,10 @@ if(APPLE)
else()
add_executable(lokinet lokinet.cpp)
enable_lto(lokinet lokinet-vpn)

if(WITH_BOOTSTRAP)
add_executable(lokinet-bootstrap lokinet-bootstrap.cpp)
enable_lto(lokinet-bootstrap)
endif()
endif()
if(WITH_BOOTSTRAP)
add_executable(lokinet-bootstrap lokinet-bootstrap.cpp)
enable_lto(lokinet-bootstrap)
endif()


Expand Down

0 comments on commit 838183e

Please sign in to comment.