Merge remote-tracking branch 'origin/stable' into opensuse/tumbleweed

opensuse/tumbleweed
Jason Rhinelander 11 months ago
commit 58c278a866
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262

16
.gitmodules vendored

@ -10,16 +10,10 @@
[submodule "test/Catch2"]
path = test/Catch2
url = https://github.com/catchorg/Catch2
[submodule "external/date"]
path = external/date
url = https://github.com/HowardHinnant/date.git
[submodule "external/pybind11"]
path = external/pybind11
url = https://github.com/pybind/pybind11
branch = stable
[submodule "external/clang-format-hooks"]
path = external/clang-format-hooks
url = https://github.com/barisione/clang-format-hooks/
[submodule "external/sqlite_orm"]
path = external/sqlite_orm
url = https://github.com/fnc12/sqlite_orm
@ -35,3 +29,13 @@
[submodule "external/ngtcp2"]
path = external/ngtcp2
url = https://github.com/ngtcp2/ngtcp2.git
branch = v0.1.0
[submodule "external/oxen-encoding"]
path = external/oxen-encoding
url = https://github.com/oxen-io/oxen-encoding.git
[submodule "external/oxen-logging"]
path = external/oxen-logging
url = https://github.com/oxen-io/oxen-logging.git
[submodule "gui"]
path = gui
url = https://github.com/oxen-io/lokinet-gui.git

@ -1,12 +1,15 @@
cmake_minimum_required(VERSION 3.10) # bionic's cmake version
cmake_minimum_required(VERSION 3.13...3.24) # 3.13 is buster's version
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)")
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 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()
@ -22,26 +25,25 @@ endif()
project(lokinet
VERSION 0.9.8
VERSION 0.9.11
DESCRIPTION "lokinet - IP packet onion router"
LANGUAGES ${LANGS})
if(APPLE)
# Apple build number: must be incremented to submit a new build for the same lokinet version,
# should be reset to 0 when the lokinet version increments.
set(LOKINET_APPLE_BUILD 0)
set(LOKINET_APPLE_BUILD 6)
endif()
set(RELEASE_MOTTO "A Series of Tubes" CACHE STRING "Release motto")
set(RELEASE_MOTTO "Our Lord And Savior" CACHE STRING "Release motto")
add_definitions(-DLLARP_VERSION_MAJOR=${lokinet_VERSION_MAJOR})
add_definitions(-DLLARP_VERSION_MINOR=${lokinet_VERSION_MINOR})
add_definitions(-DLLARP_VERSION_PATCH=${lokinet_VERSION_PATCH})
if(RELEASE_MOTTO AND CMAKE_BUILD_TYPE MATCHES "[Rr][Ee][Ll][Ee][Aa][Ss][Ee]")
add_definitions(-DLLARP_RELEASE_MOTTO="${RELEASE_MOTTO}")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
set(DEFAULT_WITH_BOOTSTRAP ON)
if(APPLE)
set(DEFAULT_WITH_BOOTSTRAP OFF)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
# Core options
option(USE_AVX2 "enable avx2 code" OFF)
@ -49,20 +51,26 @@ option(USE_NETNS "enable networking namespace support. Linux only" OFF)
option(NATIVE_BUILD "optimise for host system and FPU" ON)
option(EMBEDDED_CFG "optimise for older hardware or embedded systems" OFF)
option(BUILD_LIBLOKINET "build liblokinet.so" ON)
option(SHADOW "use shadow testing framework. linux only" OFF)
option(XSAN "use sanitiser, if your system has it (requires -DCMAKE_BUILD_TYPE=Debug)" OFF)
option(USE_JEMALLOC "Link to jemalloc for memory allocations, if found" ON)
option(TESTNET "testnet build" OFF)
option(WITH_COVERAGE "generate coverage data" OFF)
option(USE_SHELLHOOKS "enable shell hooks on compile time (dangerous)" OFF)
option(WARNINGS_AS_ERRORS "treat all warnings as errors. turn off for development, on for release" OFF)
option(TRACY_ROOT "include tracy profiler source" OFF)
option(WITH_TESTS "build unit tests" ON)
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})
option(WITH_PEERSTATS "build with experimental peerstats db support" OFF)
option(STRIP_SYMBOLS "strip off all debug symbols into an external archive for all executables built" OFF)
set(BOOTSTRAP_FALLBACK_MAINNET "${PROJECT_SOURCE_DIR}/contrib/bootstrap/mainnet.signed" CACHE PATH "Fallback bootstrap path (mainnet)")
set(BOOTSTRAP_FALLBACK_TESTNET "${PROJECT_SOURCE_DIR}/contrib/bootstrap/testnet.signed" CACHE PATH "Fallback bootstrap path (testnet)")
include(cmake/enable_lto.cmake)
option(CROSS_PLATFORM "cross compiler platform" "Linux")
option(CROSS_PREFIX "toolchain cross compiler prefix" "")
option(BUILD_STATIC_DEPS "Download, build, and statically link against core dependencies" OFF)
option(STATIC_LINK "link statically against dependencies" ${BUILD_STATIC_DEPS})
if(BUILD_STATIC_DEPS AND NOT STATIC_LINK)
@ -77,9 +85,17 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()
set(debug OFF)
if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
set(debug ON)
add_definitions(-DLOKINET_DEBUG)
endif()
option(WARN_DEPRECATED "show deprecation warnings" ${debug})
if(BUILD_STATIC_DEPS AND STATIC_LINK)
message(STATUS "we are building static deps so we won't build shared libs")
set(BUILD_SHARED_LIBS OFF)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "")
endif()
include(CheckCXXSourceCompiles)
@ -93,19 +109,18 @@ set(CMAKE_C_EXTENSIONS OFF)
include(cmake/target_link_libraries_system.cmake)
include(cmake/add_import_library.cmake)
include(cmake/add_log_tag.cmake)
include(cmake/libatomic.cmake)
include(cmake/link_dep_libs.cmake)
if (STATIC_LINK)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
message(STATUS "setting static library suffix search")
endif()
add_definitions(-D${CMAKE_SYSTEM_NAME})
include(cmake/gui-option.cmake)
include(cmake/solaris.cmake)
include(cmake/win32.cmake)
include(cmake/macos.cmake)
# No in-source building
include(MacroEnsureOutOfSourceBuild)
@ -170,32 +185,19 @@ if(NOT TARGET sodium)
export(TARGETS sodium NAMESPACE sodium:: FILE sodium-exports.cmake)
endif()
option(FORCE_OXENMQ_SUBMODULE "force using oxenmq submodule" OFF)
if(NOT FORCE_OXENMQ_SUBMODULE)
pkg_check_modules(OXENMQ liboxenmq>=1.2.4)
set(warning_flags -Wall -Wextra -Wno-unknown-pragmas -Wno-unused-function -Werror=vla)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND warning_flags -Wno-unknown-warning-option)
endif()
if(OXENMQ_FOUND)
add_library(oxenmq INTERFACE)
link_dep_libs(oxenmq INTERFACE "${OXENMQ_LIBRARY_DIRS}" ${OXENMQ_LIBRARIES})
target_include_directories(oxenmq INTERFACE ${OXENMQ_INCLUDE_DIRS})
add_library(oxenmq::oxenmq ALIAS oxenmq)
message(STATUS "Found system liboxenmq ${OXENMQ_VERSION}")
if(WARN_DEPRECATED)
list(APPEND warning_flags -Wdeprecated-declarations)
else()
message(STATUS "using oxenmq submodule")
add_subdirectory(${CMAKE_SOURCE_DIR}/external/oxen-mq)
endif()
if(NOT APPLE)
add_compile_options(-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -Wall -Wextra -Wno-unknown-pragmas -Wno-unused-function -Wno-deprecated-declarations -Werror=vla)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wno-unknown-warning-option)
endif()
list(APPEND warning_flags -Wno-deprecated-declarations)
endif()
if (NOT CMAKE_SYSTEM_NAME MATCHES "Linux" AND SHADOW)
message( FATAL_ERROR "shadow-framework is Linux only" )
endif()
# If we blindly add these directly as compile_options then they get passed to swiftc on Apple and
# break, so we use a generate expression to set them only for C++/C/ObjC
add_compile_options("$<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:OBJC>>:${warning_flags}>")
if(XSAN)
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fsanitize=${XSAN} -fno-omit-frame-pointer -fno-sanitize-recover")
@ -205,20 +207,6 @@ if(XSAN)
message(STATUS "Doing a ${XSAN} sanitizer build")
endif()
if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
add_definitions(-DLOKINET_DEBUG=1)
endif()
if(WITH_SHELLHOOKS)
add_definitions(-DENABLE_SHELLHOOKS)
endif()
if(TRACY_ROOT)
include_directories(${TRACY_ROOT})
add_definitions(-DTRACY_ENABLE)
endif()
include(cmake/coverage.cmake)
# these vars are set by the cmake toolchain spec
@ -247,22 +235,12 @@ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
if(USE_NETNS)
add_definitions(-DNETNS=1)
else()
add_definitions(-DNETNS=0)
endif()
if(TESTNET)
add_definitions(-DTESTNET=1)
add_definitions(-DTESTNET)
# 5 times slower than realtime
# add_definitions(-DTESTNET_SPEED=5)
endif()
if(SHADOW)
include(cmake/shadow.cmake)
endif()
unset(GIT_VERSION)
unset(GIT_VERSION_REAL)
@ -297,7 +275,6 @@ if(WITH_SYSTEMD AND (NOT ANDROID))
endif()
add_subdirectory(external)
include_directories(SYSTEM external/sqlite_orm/include)
if(USE_JEMALLOC AND NOT STATIC_LINK)
pkg_check_modules(JEMALLOC jemalloc IMPORTED_TARGET)
@ -317,33 +294,34 @@ if(ANDROID)
set(ANDROID_PLATFORM_SRC android/ifaddrs.c)
endif()
if(TRACY_ROOT)
target_link_libraries(base_libs INTERFACE dl)
endif()
if(WITH_HIVE)
add_definitions(-DLOKINET_HIVE=1)
add_definitions(-DLOKINET_HIVE)
endif()
add_subdirectory(crypto)
add_subdirectory(llarp)
add_subdirectory(daemon)
if(BUILD_DAEMON)
add_subdirectory(daemon)
endif()
if(WITH_HIVE)
add_subdirectory(pybind)
endif()
if (NOT SHADOW)
if(WITH_TESTS OR WITH_HIVE)
add_subdirectory(test)
endif()
if(ANDROID)
add_subdirectory(jni)
endif()
if(WITH_TESTS OR WITH_HIVE)
add_subdirectory(test)
endif()
if(ANDROID)
add_subdirectory(jni)
endif()
add_subdirectory(docs)
include(cmake/gui.cmake)
if(APPLE)
macos_target_setup()
endif()
# uninstall target
if(NOT TARGET uninstall)
configure_file(
@ -355,7 +333,10 @@ if(NOT TARGET uninstall)
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
if(BUILD_PACKAGE AND NOT APPLE)
include(cmake/installer.cmake)
include(cmake/installer.cmake)
endif()
if(TARGET package)
add_dependencies(package assemble_gui)
endif()

@ -1,28 +0,0 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"variables": []
},
{
"name": "x64-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ],
"variables": []
}
]
}

@ -3,7 +3,7 @@
* Act like a responsible adult.
* RUN `make format` BEFORE COMMITING ALWAYS.
* RUN `./contrib/format.sh` BEFORE COMMITING ALWAYS.
# Do NOT

@ -1,16 +1,3 @@
LokiNET is the reference implementation of LLARP (Low Latency Anonymous
Routing Protocol).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Copyright (c) 2018-2020 The Loki Project
Copyright (c) 2018-2020 Jeff Becker
Windows NT port and portions Copyright (c) 2018-2020 Rick V.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
@ -684,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
<https://www.gnu.org/licenses/why-not-lgpl.html>.

@ -57,4 +57,4 @@ else()
endif()
endif()
configure_file("${SRC}" "${DEST}")
configure_file("${SRC}" "${DEST}" @ONLY)

@ -5,32 +5,32 @@
set(LOCAL_MIRROR "" CACHE STRING "local mirror path/URL for lib downloads")
set(OPENSSL_VERSION 1.1.1l CACHE STRING "openssl version")
set(OPENSSL_VERSION 3.0.7 CACHE STRING "openssl version")
set(OPENSSL_MIRROR ${LOCAL_MIRROR} https://www.openssl.org/source CACHE STRING "openssl download mirror(s)")
set(OPENSSL_SOURCE openssl-${OPENSSL_VERSION}.tar.gz)
set(OPENSSL_HASH SHA256=0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1
set(OPENSSL_HASH SHA256=83049d042a260e696f62406ac5c08bf706fd84383f945cf21bd61e9ed95c396e
CACHE STRING "openssl source hash")
set(EXPAT_VERSION 2.3.0 CACHE STRING "expat version")
set(EXPAT_VERSION 2.5.0 CACHE STRING "expat version")
string(REPLACE "." "_" EXPAT_TAG "R_${EXPAT_VERSION}")
set(EXPAT_MIRROR ${LOCAL_MIRROR} https://github.com/libexpat/libexpat/releases/download/${EXPAT_TAG}
CACHE STRING "expat download mirror(s)")
set(EXPAT_SOURCE expat-${EXPAT_VERSION}.tar.xz)
set(EXPAT_HASH SHA512=dde8a9a094b18d795a0e86ca4aa68488b352dc67019e0d669e8b910ed149628de4c2a49bc3a5b832f624319336a01f9e4debe03433a43e1c420f36356d886820
set(EXPAT_HASH SHA512=2da73b991b7c0c54440485c787e5edeb3567230204e31b3cac1c3a6713ec6f9f1554d3afffc0f8336168dfd5df02db4a69bcf21b4d959723d14162d13ab87516
CACHE STRING "expat source hash")
set(UNBOUND_VERSION 1.13.2 CACHE STRING "unbound version")
set(UNBOUND_VERSION 1.17.0 CACHE STRING "unbound version")
set(UNBOUND_MIRROR ${LOCAL_MIRROR} https://nlnetlabs.nl/downloads/unbound CACHE STRING "unbound download mirror(s)")
set(UNBOUND_SOURCE unbound-${UNBOUND_VERSION}.tar.gz)
set(UNBOUND_HASH SHA256=0a13b547f3b92a026b5ebd0423f54c991e5718037fd9f72445817f6a040e1a83
set(UNBOUND_HASH SHA512=f6b9f279330fb19b5feca09524959940aad8c4e064528aa82b369c726d77e9e8e5ca23f366f6e9edcf2c061b96f482ed7a2c26ac70fc15ae5762b3d7e36a5284
CACHE STRING "unbound source hash")
set(SQLITE3_VERSION 3350500 CACHE STRING "sqlite3 version")
set(SQLITE3_MIRROR ${LOCAL_MIRROR} https://www.sqlite.org/2021
set(SQLITE3_VERSION 3400000 CACHE STRING "sqlite3 version")
set(SQLITE3_MIRROR ${LOCAL_MIRROR} https://www.sqlite.org/2022
CACHE STRING "sqlite3 download mirror(s)")
set(SQLITE3_SOURCE sqlite-autoconf-${SQLITE3_VERSION}.tar.gz)
set(SQLITE3_HASH SHA512=039af796f79fc4517be0bd5ba37886264d49da309e234ae6fccdb488ef0109ed2b917fc3e6c1fc7224dff4f736824c653aaf8f0a37550c5ebc14d035cb8ac737
CACHE STRING "sqlite3 source hash")
set(SQLITE3_HASH SHA3_256=7ee8f02b21edb4489df5082b5cf5b7ef47bcebcdb0e209bf14240db69633c878
CACHE STRING "sqlite3 source hash")
set(SODIUM_VERSION 1.0.18 CACHE STRING "libsodium version")
set(SODIUM_MIRROR ${LOCAL_MIRROR}
@ -48,29 +48,27 @@ set(ZMQ_SOURCE zeromq-${ZMQ_VERSION}.tar.gz)
set(ZMQ_HASH SHA512=e198ef9f82d392754caadd547537666d4fba0afd7d027749b3adae450516bcf284d241d4616cad3cb4ad9af8c10373d456de92dc6d115b037941659f141e7c0e
CACHE STRING "libzmq source hash")
set(LIBUV_VERSION 1.41.0 CACHE STRING "libuv version")
set(LIBUV_VERSION 1.44.2 CACHE STRING "libuv version")
set(LIBUV_MIRROR ${LOCAL_MIRROR} https://dist.libuv.org/dist/v${LIBUV_VERSION}
CACHE STRING "libuv mirror(s)")
set(LIBUV_SOURCE libuv-v${LIBUV_VERSION}.tar.gz)
set(LIBUV_HASH SHA512=33613fa28e8136507300eba374351774849b6b39aab4e53c997a918d3bc1d1094c6123e0e509535095b14dc5daa885eadb1a67bed46622ad3cc79d62dc817e84
set(LIBUV_HASH SHA512=91197ff9303112567bbb915bbb88058050e2ad1c048815a3b57c054635d5dc7df458b956089d785475290132236cb0edcfae830f5d749de29a9a3213eeaf0b20
CACHE STRING "libuv source hash")
set(ZLIB_VERSION 1.2.11 CACHE STRING "zlib version")
set(ZLIB_VERSION 1.2.13 CACHE STRING "zlib version")
set(ZLIB_MIRROR ${LOCAL_MIRROR} https://zlib.net
CACHE STRING "zlib mirror(s)")
set(ZLIB_SOURCE zlib-${ZLIB_VERSION}.tar.gz)
set(ZLIB_HASH SHA512=73fd3fff4adeccd4894084c15ddac89890cd10ef105dd5e1835e1e9bbb6a49ff229713bd197d203edfa17c2727700fce65a2a235f07568212d820dca88b528ae
CACHE STRING "zlib source hash")
set(CURL_VERSION 7.76.1 CACHE STRING "curl version")
set(ZLIB_SOURCE zlib-${ZLIB_VERSION}.tar.xz)
set(ZLIB_HASH SHA256=d14c38e313afc35a9a8760dadf26042f51ea0f5d154b0630a31da0540107fb98
CACHE STRING "zlib source hash")
set(CURL_VERSION 7.86.0 CACHE STRING "curl version")
set(CURL_MIRROR ${LOCAL_MIRROR} https://curl.haxx.se/download https://curl.askapache.com
CACHE STRING "curl mirror(s)")
set(CURL_SOURCE curl-${CURL_VERSION}.tar.xz)
set(CURL_HASH SHA256=64bb5288c39f0840c07d077e30d9052e1cbb9fa6c2dc52523824cc859e679145
set(CURL_HASH SHA512=18e03a3c00f22125e07bddb18becbf5acdca22baeb7b29f45ef189a5c56f95b2d51247813f7a9a90f04eb051739e9aa7d3a1c5be397bae75d763a2b918d1b656
CACHE STRING "curl source hash")
include(ExternalProject)
set(DEPS_DESTDIR ${CMAKE_BINARY_DIR}/static-deps)
@ -127,21 +125,21 @@ if(ANDROID)
set(android_toolchain_prefix x86_64)
set(android_toolchain_suffix linux-android)
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES x86)
set(android_machine i686)
set(android_machine x86)
set(cross_host "--host=i686-linux-android")
set(android_compiler_prefix i686)
set(android_compiler_suffix linux-android23)
set(android_toolchain_prefix i686)
set(android_toolchain_suffix linux-android)
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES armeabi-v7a)
set(android_machine armv7)
set(android_machine arm)
set(cross_host "--host=armv7a-linux-androideabi")
set(android_compiler_prefix armv7a)
set(android_compiler_suffix linux-androideabi23)
set(android_toolchain_prefix arm)
set(android_toolchain_suffix linux-androideabi)
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES arm64-v8a)
set(android_machine aarch64)
set(android_machine arm64)
set(cross_host "--host=aarch64-linux-android")
set(android_compiler_prefix aarch64)
set(android_compiler_suffix linux-android23)
@ -169,6 +167,11 @@ if(APPLE)
set(deps_CXXFLAGS "${deps_CXXFLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
if(_winver)
set(deps_CFLAGS "${deps_CFLAGS} -D_WIN32_WINNT=${_winver}")
set(deps_CXXFLAGS "${deps_CXXFLAGS} -D_WIN32_WINNT=${_winver}")
endif()
if("${CMAKE_GENERATOR}" STREQUAL "Unix Makefiles")
set(_make $(MAKE))
@ -225,7 +228,7 @@ build_external(libuv
add_static_target(libuv libuv_external libuv.a)
target_link_libraries(libuv INTERFACE ${CMAKE_DL_LIBS})
build_external(zlib
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS} -fPIC" ${cross_extra} ./configure --prefix=${DEPS_DESTDIR} --static
BUILD_BYPRODUCTS
@ -236,24 +239,51 @@ add_static_target(zlib zlib_external libz.a)
set(openssl_system_env "")
set(openssl_arch "")
set(openssl_configure_command ./config)
set(openssl_flags "CFLAGS=${deps_CFLAGS}")
if(CMAKE_CROSSCOMPILING)
if(ARCH_TRIPLET STREQUAL x86_64-w64-mingw32)
set(openssl_system_env SYSTEM=MINGW64 RC=${CMAKE_RC_COMPILER} AR=${ARCH_TRIPLET}-ar RANLIB=${ARCH_TRIPLET}-ranlib)
set(openssl_arch mingw64)
set(openssl_system_env RC=${CMAKE_RC_COMPILER} AR=${ARCH_TRIPLET}-ar RANLIB=${ARCH_TRIPLET}-ranlib)
elseif(ARCH_TRIPLET STREQUAL i686-w64-mingw32)
set(openssl_system_env SYSTEM=MINGW32 RC=${CMAKE_RC_COMPILER} AR=${ARCH_TRIPLET}-ar RANLIB=${ARCH_TRIPLET}-ranlib)
set(openssl_arch mingw)
set(openssl_system_env RC=${CMAKE_RC_COMPILER} AR=${ARCH_TRIPLET}-ar RANLIB=${ARCH_TRIPLET}-ranlib)
elseif(ANDROID)
set(openssl_system_env SYSTEM=Linux MACHINE=${android_machine} LD=${deps_ld} RANLIB=${deps_ranlib} AR=${deps_ar})
set(openssl_arch android-${android_machine})
set(openssl_system_env LD=${deps_ld} RANLIB=${deps_ranlib} AR=${deps_ar} ANDROID_NDK_ROOT=${CMAKE_ANDROID_NDK} "PATH=${CMAKE_ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin:$ENV{PATH}")
list(APPEND openssl_flags "CPPFLAGS=-D__ANDROID_API__=${ANDROID_API}")
set(openssl_extra_opts no-asm)
elseif(ARCH_TRIPLET STREQUAL mips64-linux-gnuabi64)
set(openssl_arch linux-mips64)
elseif(ARCH_TRIPLET STREQUAL mips-linux-gnu)
set(openssl_arch linux-mips32)
elseif(ARCH_TRIPLET STREQUAL mipsel-linux-gnu)
set(openssl_arch linux-mips)
elseif(ARCH_TRIPLET STREQUAL aarch64-linux-gnu)
# cross compile arm64
set(openssl_arch linux-aarch64)
elseif(ARCH_TRIPLET MATCHES arm-linux)
# cross compile armhf
set(openssl_arch linux-armv4)
elseif(ARCH_TRIPLET MATCHES powerpc64le)
# cross compile ppc64le
set(openssl_arch linux-ppc64le)
endif()
elseif(CMAKE_C_FLAGS MATCHES "-march=armv7")
# Help openssl figure out that we're building from armv7 even if on armv8 hardware:
set(openssl_system_env SYSTEM=Linux MACHINE=armv7)
set(openssl_arch linux-armv4)
endif()
build_external(openssl
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CC=${deps_cc} ${openssl_system_env} ./config
--prefix=${DEPS_DESTDIR} ${openssl_extra_opts} no-shared no-capieng no-dso no-dtls1 no-ec_nistp_64_gcc_128 no-gost
no-heartbeats no-md2 no-rc5 no-rdrand no-rfc3779 no-sctp no-ssl-trace no-ssl2 no-ssl3
no-static-engine no-tests no-weak-ssl-ciphers no-zlib no-zlib-dynamic "CFLAGS=${deps_CFLAGS}"
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CC=${deps_cc} ${openssl_system_env} ${openssl_configure_command}
--prefix=${DEPS_DESTDIR} --libdir=lib ${openssl_extra_opts}
no-shared no-capieng no-dso no-dtls1 no-ec_nistp_64_gcc_128 no-gost
no-md2 no-rc5 no-rdrand no-rfc3779 no-sctp no-ssl-trace no-ssl3
no-static-engine no-tests no-weak-ssl-ciphers no-zlib no-zlib-dynamic ${openssl_flags}
${openssl_arch}
BUILD_COMMAND ${CMAKE_COMMAND} -E env ${openssl_system_env} ${_make}
INSTALL_COMMAND ${_make} install_sw
BUILD_BYPRODUCTS
${DEPS_DESTDIR}/lib/libssl.a ${DEPS_DESTDIR}/lib/libcrypto.a
@ -267,7 +297,6 @@ endif()
set(OPENSSL_INCLUDE_DIR ${DEPS_DESTDIR}/include)
set(OPENSSL_CRYPTO_LIBRARY ${DEPS_DESTDIR}/lib/libcrypto.a ${DEPS_DESTDIR}/lib/libssl.a)
set(OPENSSL_VERSION 1.1.1)
set(OPENSSL_ROOT_DIR ${DEPS_DESTDIR})
build_external(expat
@ -278,8 +307,14 @@ build_external(expat
add_static_target(expat expat_external libexpat.a)
if(WIN32)
set(unbound_patch
PATCH_COMMAND ${PROJECT_SOURCE_DIR}/contrib/apply-patches.sh
${PROJECT_SOURCE_DIR}/contrib/patches/unbound-delete-crash-fix.patch)
endif()
build_external(unbound
DEPENDS openssl_external expat_external
${unbound_patch}
CONFIGURE_COMMAND ./configure ${cross_host} ${cross_rc} --prefix=${DEPS_DESTDIR} --disable-shared
--enable-static --with-libunbound-only --with-pic
--$<IF:$<BOOL:${WITH_LTO}>,enable,disable>-flto --with-ssl=${DEPS_DESTDIR}
@ -299,8 +334,11 @@ build_external(sodium CONFIGURE_COMMAND ./configure ${cross_host} ${cross_rc} --
--enable-static --with-pic "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}")
add_static_target(sodium sodium_external libsodium.a)
build_external(sqlite3)
add_static_target(sqlite3 sqlite3_external libsqlite3.a)
if(WITH_PEERSTATS_BACKEND)
build_external(sqlite3)
add_static_target(sqlite3 sqlite3_external libsqlite3.a)
endif()
if(ARCH_TRIPLET MATCHES mingw)
@ -312,7 +350,9 @@ endif()
if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw)
set(zmq_patch
PATCH_COMMAND ${PROJECT_SOURCE_DIR}/contrib/apply-patches.sh ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-wepoll.patch ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-closesocket.patch)
PATCH_COMMAND ${PROJECT_SOURCE_DIR}/contrib/apply-patches.sh
${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-wepoll.patch
${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-unistd.patch)
endif()
build_external(zmq
@ -335,6 +375,19 @@ set_target_properties(libzmq PROPERTIES
INTERFACE_LINK_LIBRARIES "${libzmq_link_libs}"
INTERFACE_COMPILE_DEFINITIONS "ZMQ_STATIC")
#
#
#
# Everything that follows is *only* for lokinet-bootstrap (i.e. if adding new deps put them *above*
# this).
#
#
#
if(NOT WITH_BOOTSTRAP)
return()
endif()
set(curl_extra)
if(WIN32)
set(curl_ssl_opts --without-ssl --with-schannel)
@ -386,7 +439,7 @@ foreach(curl_arch ${curl_arches})
--enable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies
--enable-http-auth --enable-doh --disable-mime --enable-dateparse --disable-netrc --without-libidn2
--disable-progress-meter --without-brotli --with-zlib=${DEPS_DESTDIR} ${curl_ssl_opts}
--without-libmetalink --without-librtmp --disable-versioned-symbols --enable-hidden-symbols
--without-librtmp --disable-versioned-symbols --enable-hidden-symbols
--without-zsh-functions-dir --without-fish-functions-dir
--without-nghttp3 --without-zstd
"CC=${deps_cc}" "CFLAGS=${deps_noarch_CFLAGS}${cflags_extra}" ${curl_extra}
@ -400,7 +453,7 @@ foreach(curl_arch ${curl_arches})
list(APPEND curl_lib_outputs ${curl_prefix}/lib/libcurl.a)
endforeach()
message(STATUS "TARGETS: ${curl_lib_targets}")
if(IOS AND num_arches GREATER 1)
# We are building multiple architectures for different iOS devices, so we need to glue the

@ -1,22 +1,46 @@
# We do this via a custom command that re-invokes a cmake script because we need the DEPENDS on .git/index so that we will re-run it (to regenerate the commit tag in the version) whenever the current commit changes. If we used a configure_file directly here, it would only re-run when something else causes cmake to re-run.
find_package(Git QUIET)
set(GIT_INDEX_FILE "${PROJECT_SOURCE_DIR}/.git/index")
if(EXISTS ${GIT_INDEX_FILE} AND ( GIT_FOUND OR Git_FOUND) )
message(STATUS "Found Git: ${GIT_EXECUTABLE}")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp"
COMMAND "${CMAKE_COMMAND}"
"-D" "GIT=${GIT_EXECUTABLE}"
"-D" "SRC=${CMAKE_CURRENT_SOURCE_DIR}/constants/version.cpp.in"
"-D" "DEST=${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp"
"-P" "${CMAKE_CURRENT_LIST_DIR}/GenVersion.cmake"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/constants/version.cpp.in"
"${GIT_INDEX_FILE}")
if(LOKINET_VERSIONTAG)
set(VERSIONTAG "${LOKINET_VERSIONTAG}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/constants/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp" @ONLY)
else()
message(STATUS "Git was not found! Setting version to to nogit")
set(VERSIONTAG "nogit")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/constants/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp")
set(VERSIONTAG "${GIT_VERSION}")
set(GIT_INDEX_FILE "${PROJECT_SOURCE_DIR}/.git/index")
find_package(Git)
if(EXISTS "${GIT_INDEX_FILE}" AND ( GIT_FOUND OR Git_FOUND) )
message(STATUS "Found Git: ${GIT_EXECUTABLE}")
set(genversion_args "-DGIT=${GIT_EXECUTABLE}")
foreach(v lokinet_VERSION lokinet_VERSION_MAJOR lokinet_VERSION_MINOR lokinet_VERSION_PATCH RELEASE_MOTTO)
list(APPEND genversion_args "-D${v}=${${v}}")
endforeach()
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp"
COMMAND "${CMAKE_COMMAND}"
${genversion_args}
"-D" "SRC=${CMAKE_CURRENT_SOURCE_DIR}/constants/version.cpp.in"
"-D" "DEST=${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp"
"-P" "${CMAKE_CURRENT_LIST_DIR}/GenVersion.cmake"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/constants/version.cpp.in"
"${GIT_INDEX_FILE}")
else()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/constants/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp" @ONLY)
endif()
endif()
add_custom_target(genversion DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp")
if(WIN32)
foreach(exe IN ITEMS lokinet lokinet-vpn lokinet-bootstrap)
set(lokinet_EXE_NAME "${exe}.exe")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/win32/version.rc.in" "${CMAKE_BINARY_DIR}/${exe}.rc" @ONLY)
set_property(SOURCE "${CMAKE_BINARY_DIR}/${exe}.rc" PROPERTY GENERATED 1)
endforeach()
endif()
add_custom_target(genversion_cpp DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp")
if(WIN32)
add_custom_target(genversion_rc DEPENDS "${CMAKE_BINARY_DIR}/lokinet.rc" "${CMAKE_BINARY_DIR}/lokinet-vpn.rc" "${CMAKE_BINARY_DIR}/lokinet-bootstrap.rc")
else()
add_custom_target(genversion_rc)
endif()
add_custom_target(genversion DEPENDS genversion_cpp genversion_rc)

@ -1,7 +0,0 @@
function(add_log_tag target)
get_target_property(TARGET_SRCS ${target} SOURCES)
foreach(F ${TARGET_SRCS})
get_filename_component(fpath "${F}" ABSOLUTE)
set_property(SOURCE ${F} APPEND PROPERTY COMPILE_DEFINITIONS SOURCE_ROOT=\"${PROJECT_SOURCE_DIR}\")
endforeach()
endfunction()

@ -44,6 +44,7 @@ if(filesystem_is_good EQUAL 1)
else()
# Probably broken AF macos
message(STATUS "std::filesystem is not available, apparently this compiler isn't C++17 compliant; falling back to ghc::filesystem")
set(GHC_FILESYSTEM_WITH_INSTALL OFF CACHE INTERNAL "")
add_subdirectory(external/ghc-filesystem)
target_link_libraries(filesystem INTERFACE ghc_filesystem)
target_compile_definitions(filesystem INTERFACE USE_GHC_FILESYSTEM)

@ -2,6 +2,9 @@
include(CheckIPOSupported)
option(WITH_LTO "enable lto on compile time" ON)
if(WITH_LTO)
if(WIN32)
message(FATAL_ERROR "LTO not supported on win32 targets, please set -DWITH_LTO=OFF")
endif()
check_ipo_supported(RESULT IPO_ENABLED OUTPUT ipo_error)
if(IPO_ENABLED)
message(STATUS "LTO enabled")

@ -0,0 +1,17 @@
set(default_build_gui OFF)
if(APPLE OR WIN32)
set(default_build_gui ON)
endif()
if(WIN32)
set(GUI_EXE "" CACHE FILEPATH "path to a pre-built Windows GUI .exe to use (implies -DBUILD_GUI=OFF)")
if(GUI_EXE)
set(default_build_gui OFF)
endif()
endif()
option(BUILD_GUI "build electron gui from 'gui' submodule source" ${default_build_gui})
if(BUILD_GUI AND GUI_EXE)
message(FATAL_ERROR "-DGUI_EXE=... and -DBUILD_GUI=ON are mutually exclusive")
endif()

@ -0,0 +1,67 @@
if(WIN32 AND GUI_EXE)
message(STATUS "using pre-built lokinet gui executable: ${GUI_EXE}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${GUI_EXE}" "${PROJECT_BINARY_DIR}/gui/lokinet-gui.exe")
elseif(BUILD_GUI)
message(STATUS "Building lokinet-gui from source")
set(default_gui_target pack)
if(APPLE)
set(default_gui_target macos:raw)
elseif(WIN32)
set(default_gui_target win32)
endif()
set(GUI_YARN_TARGET "${default_gui_target}" CACHE STRING "yarn target for building the GUI")
set(GUI_YARN_EXTRA_OPTS "" CACHE STRING "extra options to pass into the yarn build command")
# allow manually specifying yarn with -DYARN=
if(NOT YARN)
find_program(YARN NAMES yarnpkg yarn REQUIRED)
endif()
message(STATUS "Building lokinet-gui with yarn ${YARN}, target ${GUI_YARN_TARGET}")
if(NOT WIN32)
add_custom_target(lokinet-gui
COMMAND ${YARN} install --frozen-lockfile &&
${YARN} ${GUI_YARN_EXTRA_OPTS} ${GUI_YARN_TARGET}
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/gui")
endif()
if(APPLE)
add_custom_target(assemble_gui ALL
DEPENDS assemble lokinet-gui
COMMAND mkdir "${lokinet_app}/Contents/Helpers"
COMMAND cp -a "${PROJECT_SOURCE_DIR}/gui/release/mac/Lokinet-GUI.app" "${lokinet_app}/Contents/Helpers/"
COMMAND mkdir -p "${lokinet_app}/Contents/Resources/en.lproj"
COMMAND cp "${PROJECT_SOURCE_DIR}/contrib/macos/InfoPlist.strings" "${lokinet_app}/Contents/Resources/en.lproj/"
COMMAND cp "${lokinet_app}/Contents/Resources/icon.icns" "${lokinet_app}/Contents/Helpers/Lokinet-GUI.app/Contents/Resources/icon.icns"
COMMAND cp "${PROJECT_SOURCE_DIR}/contrib/macos/InfoPlist.strings" "${lokinet_app}/Contents/Helpers/Lokinet-GUI.app/Contents/Resources/en.lproj/"
COMMAND /usr/libexec/PlistBuddy
-c "Delete :CFBundleDisplayName"
-c "Add :LSHasLocalizedDisplayName bool true"
-c "Add :CFBundleDevelopmentRegion string en"
-c "Set :CFBundleShortVersionString ${lokinet_VERSION}"
-c "Set :CFBundleVersion ${lokinet_VERSION}.${LOKINET_APPLE_BUILD}"
"${lokinet_app}/Contents/Helpers/Lokinet-GUI.app/Contents/Info.plist"
)
elseif(WIN32)
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/gui")
add_custom_command(OUTPUT "${PROJECT_BINARY_DIR}/gui/lokinet-gui.exe"
COMMAND ${YARN} install --frozen-lockfile &&
USE_SYSTEM_7ZA=true DISPLAY= WINEDEBUG=-all WINEPREFIX="${PROJECT_BINARY_DIR}/wineprefix" ${YARN} ${GUI_YARN_EXTRA_OPTS} ${GUI_YARN_TARGET}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/gui/release/Lokinet-GUI_portable.exe"
"${PROJECT_BINARY_DIR}/gui/lokinet-gui.exe"
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/gui")
add_custom_target(assemble_gui ALL COMMAND "true" DEPENDS "${PROJECT_BINARY_DIR}/gui/lokinet-gui.exe")
else()
message(FATAL_ERROR "Building/bundling the GUI from this repository is not supported on this platform")
endif()
else()
message(STATUS "not building gui")
endif()
if(NOT TARGET assemble_gui)
add_custom_target(assemble_gui COMMAND "true")
endif()

@ -1,13 +1,46 @@
set(CPACK_PACKAGE_VENDOR "lokinet.org")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://lokinet.org/")
set(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/contrib/readme-installer.txt")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE.txt")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
if(WIN32)
include(cmake/win32_installer_deps.cmake)
install(FILES ${CMAKE_SOURCE_DIR}/contrib/configs/00-exit.ini DESTINATION share/conf.d COMPONENT exit_configs)
install(FILES ${CMAKE_SOURCE_DIR}/contrib/configs/00-keyfile.ini DESTINATION share/conf.d COMPONENT keyfile_configs)
install(FILES ${CMAKE_SOURCE_DIR}/contrib/configs/00-debug-log.ini DESTINATION share/conf.d COMPONENT debug_configs)
get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS)
list(REMOVE_ITEM CPACK_COMPONENTS_ALL "Unspecified" "lokinet" "gui" "exit_configs" "keyfile_configs" "debug_configs")
list(APPEND CPACK_COMPONENTS_ALL "lokinet" "gui" "exit_configs" "keyfile_configs" "debug_configs")
elseif(APPLE)
set(CPACK_GENERATOR DragNDrop;ZIP)
get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS)
list(REMOVE_ITEM CPACK_COMPONENTS_ALL "Unspecified")
endif()
# This must always be last!
include(CPack)
if(WIN32)
cpack_add_component(lokinet
DISPLAY_NAME "lokinet"
DESCRIPTION "core required lokinet files"
REQUIRED)
cpack_add_component(gui
DISPLAY_NAME "lokinet gui"
DESCRIPTION "electron based control panel for lokinet")
cpack_add_component(exit_configs
DISPLAY_NAME "auto-enable exit"
DESCRIPTION "automatically enable usage of exit.loki as an exit node\n"
DISABLED)
cpack_add_component(keyfile_configs
DISPLAY_NAME "persist address"
DESCRIPTION "persist .loki address across restarts of lokinet\nnot recommended when enabling exit nodes"
DISABLED)
cpack_add_component(debug_configs
DISPLAY_NAME "debug logging"
DESCRIPTION "enable debug spew log level by default"
DISABLED)
endif()

@ -1,13 +0,0 @@
# Properly links a target to a list of library names by finding the given libraries. Takes:
# - a target
# - a linktype (e.g. INTERFACE, PUBLIC, PRIVATE)
# - a library search path (or "" for defaults)
# - any number of library names
function(link_dep_libs target linktype libdirs)
foreach(lib ${ARGN})
find_library(link_lib-${lib} NAMES ${lib} PATHS ${libdirs})
if(link_lib-${lib})
target_link_libraries(${target} ${linktype} ${link_lib-${lib}})
endif()
endforeach()
endfunction()

@ -0,0 +1,214 @@
if(NOT APPLE)
return()
endif()
option(MACOS_SYSTEM_EXTENSION
"Build the network extension as a system extension rather than a plugin. This must be ON for non-app store release builds, and must be OFF for dev builds and Mac App Store distribution builds"
OFF)
option(CODESIGN "codesign the resulting app and extension" ON)
set(CODESIGN_ID "" CACHE STRING "codesign the macos app using this key identity; if empty we'll try to guess")
set(default_profile_type "dev")
if(MACOS_SYSTEM_EXTENSION)
set(default_profile_type "release")
endif()
set(CODESIGN_PROFILE "${PROJECT_SOURCE_DIR}/contrib/macos/lokinet.${default_profile_type}.provisionprofile" CACHE FILEPATH
"Path to a .provisionprofile to use for the main app")
set(CODESIGN_EXT_PROFILE "${PROJECT_SOURCE_DIR}/contrib/macos/lokinet-extension.${default_profile_type}.provisionprofile" CACHE FILEPATH
"Path to a .provisionprofile to use for the lokinet extension")
if(CODESIGN AND NOT CODESIGN_ID)
if(MACOS_SYSTEM_EXTENSION)
set(codesign_cert_pattern "Developer ID Application")
else()
set(codesign_cert_pattern "Apple Development")
endif()
execute_process(
COMMAND security find-identity -v -p codesigning
COMMAND sed -n "s/^ *[0-9][0-9]*) *\\([A-F0-9]\\{40\\}\\) *\"\\(${codesign_cert_pattern}.*\\)\"\$/\\1 \\2/p"
RESULT_VARIABLE find_id_exit_code
OUTPUT_VARIABLE find_id_output)
if(NOT find_id_exit_code EQUAL 0)
message(FATAL_ERROR "Finding signing identities with security find-identity failed; try specifying an id using -DCODESIGN_ID=...")
endif()
string(REGEX MATCHALL "(^|\n)[0-9A-F]+" find_id_sign_id "${find_id_output}")
if(NOT find_id_sign_id)
message(FATAL_ERROR "Did not find any \"${codesign_cert_pattern}\" identity; try specifying an id using -DCODESIGN_ID=...")
endif()
if (find_id_sign_id MATCHES ";")
message(FATAL_ERROR "Found multiple \"${codesign_cert_pattern}\" identities:\n${find_id_output}\nSpecify an identify using -DCODESIGN_ID=...")
endif()
set(CODESIGN_ID "${find_id_sign_id}" CACHE STRING "" FORCE)
endif()
if(CODESIGN)
message(STATUS "Codesigning using ${CODESIGN_ID}")
if (NOT MACOS_NOTARIZE_USER AND NOT MACOS_NOTARIZE_PASS AND NOT MACOS_NOTARIZE_ASC AND EXISTS "$ENV{HOME}/.notarization.cmake")
message(STATUS "Loading notarization info from ~/.notarization.cmake")
include("$ENV{HOME}/.notarization.cmake")
endif()
if (MACOS_NOTARIZE_USER AND MACOS_NOTARIZE_PASS AND MACOS_NOTARIZE_ASC)
message(STATUS "Enabling notarization with account ${MACOS_NOTARIZE_ASC}/${MACOS_NOTARIZE_USER}")
else()
message(WARNING "You have not set one or more of MACOS_NOTARIZE_USER, MACOS_NOTARIZE_PASS, MACOS_NOTARIZE_ASC: notarization will fail; see contrib/macos/README.txt")
endif()
else()
message(WARNING "Codesigning disabled; the resulting build will not run on most macOS systems")
endif()
foreach(prof IN ITEMS CODESIGN_PROFILE CODESIGN_EXT_PROFILE)
if(NOT ${prof})
message(WARNING "Missing a ${prof} provisioning profile: Apple will most likely log an uninformative error message to the system log and then kill harmless kittens if you try to run the result")
elseif(NOT EXISTS "${${prof}}")
message(FATAL_ERROR "Provisioning profile ${${prof}} does not exist; fix your -D${prof} path")
endif()
endforeach()
message(STATUS "Using ${CODESIGN_PROFILE} app provisioning profile")
message(STATUS "Using ${CODESIGN_EXT_PROFILE} extension provisioning profile")
set(lokinet_installer "${PROJECT_BINARY_DIR}/Lokinet ${PROJECT_VERSION}")
if(NOT CODESIGN)
set(lokinet_installer "${lokinet_installer}-UNSIGNED")
endif()
set(lokinet_app "${lokinet_installer}/Lokinet.app")
if(MACOS_SYSTEM_EXTENSION)
set(lokinet_ext_dir Contents/Library/SystemExtensions)
else()
set(lokinet_ext_dir Contents/PlugIns)
endif()
if(CODESIGN)
if(MACOS_SYSTEM_EXTENSION)
set(LOKINET_ENTITLEMENTS_TYPE sysext)
set(notarize_py_is_sysext True)
else()
set(LOKINET_ENTITLEMENTS_TYPE plugin)
set(notarize_py_is_sysext False)
endif()
configure_file(
"${PROJECT_SOURCE_DIR}/contrib/macos/sign.sh.in"
"${PROJECT_BINARY_DIR}/sign.sh"
@ONLY)
add_custom_target(
sign
DEPENDS "${PROJECT_BINARY_DIR}/sign.sh"
COMMAND "${PROJECT_BINARY_DIR}/sign.sh"
)
if(MACOS_NOTARIZE_USER AND MACOS_NOTARIZE_PASS AND MACOS_NOTARIZE_ASC)
configure_file(
"${PROJECT_SOURCE_DIR}/contrib/macos/notarize.py.in"
"${PROJECT_BINARY_DIR}/notarize.py"
@ONLY)
add_custom_target(
notarize
DEPENDS "${PROJECT_BINARY_DIR}/notarize.py" sign
COMMAND "${PROJECT_BINARY_DIR}/notarize.py"
)
else()
message(WARNING "You have not set one or more of MACOS_NOTARIZE_USER, MACOS_NOTARIZE_PASS, MACOS_NOTARIZE_ASC: notarization disabled")
endif()
else()
add_custom_target(sign COMMAND "true")
add_custom_target(notarize DEPENDS sign COMMAND "true")
endif()
set(mac_icon "${PROJECT_BINARY_DIR}/lokinet.icns")
add_custom_command(OUTPUT "${mac_icon}"
COMMAND ${PROJECT_SOURCE_DIR}/contrib/macos/mk-icns.sh ${PROJECT_SOURCE_DIR}/contrib/lokinet-mac.svg "${mac_icon}"
DEPENDS ${PROJECT_SOURCE_DIR}/contrib/lokinet-mac.svg ${PROJECT_SOURCE_DIR}/contrib/macos/mk-icns.sh)
add_custom_target(icon DEPENDS "${mac_icon}")
if(BUILD_PACKAGE)
add_executable(seticon "${PROJECT_SOURCE_DIR}/contrib/macos/seticon.swift")
add_custom_command(OUTPUT "${lokinet_installer}.dmg"
DEPENDS notarize seticon
COMMAND create-dmg
--volname "Lokinet ${PROJECT_VERSION}"
--volicon lokinet.icns
--background "${PROJECT_SOURCE_DIR}/contrib/macos/installer.tiff"
--text-size 16
--icon-size 128
--window-size 555 440
--icon Lokinet.app 151 196
--hide-extension Lokinet.app
--app-drop-link 403 196
--eula "${PROJECT_SOURCE_DIR}/LICENSE"
--no-internet-enable
"${lokinet_installer}.dmg"
"${lokinet_installer}"
COMMAND ./seticon lokinet.icns "${lokinet_installer}.dmg"
)
add_custom_target(package DEPENDS "${lokinet_installer}.dmg")
endif()
# Called later to set things up, after the main lokinet targets are set up
function(macos_target_setup)
if(MACOS_SYSTEM_EXTENSION)
target_compile_definitions(lokinet PRIVATE MACOS_SYSTEM_EXTENSION)
endif()
set_target_properties(lokinet
PROPERTIES
OUTPUT_NAME Lokinet
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_STRING "Lokinet IP Packet Onion Router"
MACOSX_BUNDLE_BUNDLE_NAME "Lokinet"
MACOSX_BUNDLE_BUNDLE_VERSION "${lokinet_VERSION}"
MACOSX_BUNDLE_LONG_VERSION_STRING "${lokinet_VERSION}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${lokinet_VERSION_MAJOR}.${lokinet_VERSION_MINOR}"
MACOSX_BUNDLE_GUI_IDENTIFIER "org.lokinet"
MACOSX_BUNDLE_INFO_PLIST "${PROJECT_SOURCE_DIR}/contrib/macos/lokinet.Info.plist.in"
MACOSX_BUNDLE_COPYRIGHT "© 2022, The Oxen Project"
)
add_custom_target(copy_bootstrap
DEPENDS lokinet-extension
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_SOURCE_DIR}/contrib/bootstrap/mainnet.signed
$<TARGET_BUNDLE_DIR:lokinet-extension>/Contents/Resources/bootstrap.signed
)
add_dependencies(lokinet lokinet-extension icon)
if(CODESIGN_PROFILE)
add_custom_target(copy_prov_prof
DEPENDS lokinet
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CODESIGN_PROFILE}
$<TARGET_BUNDLE_DIR:lokinet>/Contents/embedded.provisionprofile
)
else()
add_custom_target(copy_prov_prof COMMAND true)
endif()
add_custom_target(assemble ALL
DEPENDS lokinet lokinet-extension icon copy_prov_prof copy_bootstrap
COMMAND rm -rf "${lokinet_app}"
COMMAND mkdir -p "${lokinet_installer}"
COMMAND cp -a $<TARGET_BUNDLE_DIR:lokinet> "${lokinet_app}"
COMMAND mkdir -p "${lokinet_app}/${lokinet_ext_dir}"
COMMAND cp -a $<TARGET_BUNDLE_DIR:lokinet-extension> "${lokinet_app}/${lokinet_ext_dir}/"
COMMAND mkdir -p "${lokinet_app}/Contents/Resources"
COMMAND cp -a "${mac_icon}" "${lokinet_app}/Contents/Resources/icon.icns"
)
if(BUILD_GUI)
add_dependencies(sign assemble_gui)
else()
add_dependencies(sign assemble)
endif()
endfunction()

@ -45,8 +45,9 @@ function(add_ngtcp2_lib)
configure_file(ngtcp2/cmakeconfig.h.in ngtcp2/config.h)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/ngtcp2") # for config.h
set(ENABLE_STATIC_LIB ON FORCE BOOL)
set(ENABLE_SHARED_LIB OFF FORCE BOOL)
add_subdirectory(ngtcp2/lib EXCLUDE_FROM_ALL)
target_compile_definitions(ngtcp2 PRIVATE -DHAVE_CONFIG_H -D_GNU_SOURCE)
target_compile_definitions(ngtcp2_static PRIVATE -DHAVE_CONFIG_H -D_GNU_SOURCE)
endfunction()

@ -1,18 +0,0 @@
set(WITH_STATIC OFF)
set(WITH_SHARED ON)
if("${SHADOW_ROOT}" STREQUAL "")
set(SHADOW_ROOT "$ENV{HOME}/.shadow")
endif("${SHADOW_ROOT}" STREQUAL "")
if(EXISTS "${SHADOW_ROOT}")
message(STATUS "SHADOW_ROOT = ${SHADOW_ROOT}")
else()
message(FATAL_ERROR "SHADOW_ROOT path does not exist: '${SHADOW_ROOT}'")
endif(EXISTS "${SHADOW_ROOT}")
set(CMAKE_MODULE_PATH "${SHADOW_ROOT}/share/cmake/Modules")
include_directories(${CMAKE_MODULE_PATH})
include(ShadowTools)
add_compile_options(-fno-inline -fno-strict-aliasing )
add_definitions(-DTESTNET=1)
add_definitions(-DLOKINET_SHADOW)
include_directories(${SHADOW_ROOT}/include)

@ -1,31 +1,49 @@
if(NOT WIN32)
return()
endif()
if (NOT STATIC_LINK)
message(FATAL_ERROR "windows requires static builds (thanks balmer)")
endif()
enable_language(RC)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
if(NOT MSVC_VERSION)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-bad-function-cast>)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-cast-function-type>)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
# unlike unix where you get a *single* compiler ID string in .comment
# GNU ld sees fit to merge *all* the .ident sections in object files
# to .r[o]data section one after the other!
add_compile_options(-fno-ident -Wa,-mbig-obj)
link_libraries( -lws2_32 -lshlwapi -ldbghelp -luser32 -liphlpapi -lpsapi -luserenv)
# zmq requires windows xp or higher
add_definitions(-DWINVER=0x0501 -D_WIN32_WINNT=0x0501)
endif()
option(WITH_WINDOWS_32 "build 32 bit windows" OFF)
# unlike unix where you get a *single* compiler ID string in .comment
# GNU ld sees fit to merge *all* the .ident sections in object files
# to .r[o]data section one after the other!
add_compile_options(-fno-ident -Wa,-mbig-obj)
if(EMBEDDED_CFG)
link_libatomic()
endif()
add_definitions(-DWIN32_LEAN_AND_MEAN -DWIN32)
set(WINTUN_VERSION 0.14.1 CACHE STRING "wintun version")
set(WINTUN_MIRROR https://www.wintun.net/builds
CACHE STRING "wintun mirror(s)")
set(WINTUN_SOURCE wintun-${WINTUN_VERSION}.zip)
set(WINTUN_HASH SHA256=07c256185d6ee3652e09fa55c0b673e2624b565e02c4b9091c79ca7d2f24ef51
CACHE STRING "wintun source hash")
if (NOT STATIC_LINK AND NOT MSVC)
message("must ship compiler runtime libraries with this build: libwinpthread-1.dll, libgcc_s_dw2-1.dll, and libstdc++-6.dll")
message("for release builds, turn on STATIC_LINK in cmake options")
endif()
set(WINDIVERT_VERSION 2.2.0-A CACHE STRING "windivert version")
set(WINDIVERT_MIRROR https://reqrypt.org/download
CACHE STRING "windivert mirror(s)")
set(WINDIVERT_SOURCE WinDivert-${WINDIVERT_VERSION}.zip)
set(WINDIVERT_HASH SHA256=2a7630aac0914746fbc565ac862fa096e3e54233883ac52d17c83107496b7a7f
CACHE STRING "windivert source hash")
set(WINTUN_URL ${WINTUN_MIRROR}/${WINTUN_SOURCE}
CACHE STRING "wintun download url")
set(WINDIVERT_URL ${WINDIVERT_MIRROR}/${WINDIVERT_SOURCE}
CACHE STRING "windivert download url")
message(STATUS "Downloading wintun from ${WINTUN_URL}")
file(DOWNLOAD ${WINTUN_URL} ${CMAKE_BINARY_DIR}/wintun.zip EXPECTED_HASH ${WINTUN_HASH})
message(STATUS "Downloading windivert from ${WINDIVERT_URL}")
file(DOWNLOAD ${WINDIVERT_URL} ${CMAKE_BINARY_DIR}/windivert.zip EXPECTED_HASH ${WINDIVERT_HASH})
execute_process(COMMAND ${CMAKE_COMMAND} -E tar x ${CMAKE_BINARY_DIR}/wintun.zip
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E tar x ${CMAKE_BINARY_DIR}/windivert.zip
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})

@ -1,40 +1,46 @@
if(NOT GUI_ZIP_URL)
set(GUI_ZIP_URL "https://oxen.rocks/oxen-io/loki-network-control-panel/lokinet-gui-windows-32bit-v0.3.8.zip")
set(GUI_ZIP_HASH_OPTS EXPECTED_HASH SHA256=60c2b738cf997e5684f307e5222498fd09143d495a932924105a49bf59ded8bb)
install(DIRECTORY ${CMAKE_BINARY_DIR}/gui DESTINATION share COMPONENT gui)
if(WITH_WINDOWS_32)
install(FILES ${CMAKE_BINARY_DIR}/wintun/bin/x86/wintun.dll DESTINATION bin COMPONENT lokinet)
install(FILES ${CMAKE_BINARY_DIR}/WinDivert-${WINDIVERT_VERSION}/x86/WinDivert.sys DESTINATION lib COMPONENT lokinet)
install(FILES ${CMAKE_BINARY_DIR}/WinDivert-${WINDIVERT_VERSION}/x86/WinDivert.dll DESTINATION bin COMPONENT lokinet)
else()
install(FILES ${CMAKE_BINARY_DIR}/wintun/bin/amd64/wintun.dll DESTINATION bin COMPONENT lokinet)
install(FILES ${CMAKE_BINARY_DIR}/WinDivert-${WINDIVERT_VERSION}/x64/WinDivert64.sys DESTINATION lib COMPONENT lokinet)
install(FILES ${CMAKE_BINARY_DIR}/WinDivert-${WINDIVERT_VERSION}/x64/WinDivert.dll DESTINATION bin COMPONENT lokinet)
endif()
set(TUNTAP_URL "https://build.openvpn.net/downloads/releases/latest/tap-windows-latest-stable.exe")
set(TUNTAP_EXE "${CMAKE_BINARY_DIR}/tuntap-install.exe")
set(BOOTSTRAP_FILE "${PROJECT_SOURCE_DIR}/contrib/bootstrap/mainnet.signed")
file(DOWNLOAD
${TUNTAP_URL}
${TUNTAP_EXE})
file(DOWNLOAD
${GUI_ZIP_URL}
${CMAKE_BINARY_DIR}/lokinet-gui.zip
${GUI_ZIP_HASH_OPTS})
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf ${CMAKE_BINARY_DIR}/lokinet-gui.zip
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
install(DIRECTORY ${CMAKE_BINARY_DIR}/gui DESTINATION share COMPONENT gui)
install(PROGRAMS ${TUNTAP_EXE} DESTINATION bin COMPONENT tuntap)
install(FILES ${BOOTSTRAP_FILE} DESTINATION share COMPONENT lokinet RENAME bootstrap.signed)
set(win_ico "${PROJECT_BINARY_DIR}/lokinet.ico")
add_custom_command(OUTPUT "${win_ico}"
COMMAND ${PROJECT_SOURCE_DIR}/contrib/make-ico.sh ${PROJECT_SOURCE_DIR}/contrib/lokinet.svg "${win_ico}"
DEPENDS ${PROJECT_SOURCE_DIR}/contrib/lokinet.svg ${PROJECT_SOURCE_DIR}/contrib/make-ico.sh)
add_custom_target(icon ALL DEPENDS "${win_ico}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Lokinet")
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/win32-setup/lokinet.ico")
set(CPACK_NSIS_MUI_ICON "${PROJECT_BINARY_DIR}/lokinet.ico")
set(CPACK_NSIS_DEFINES "RequestExecutionLevel admin")
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ifFileExists $INSTDIR\\\\bin\\\\tuntap-install.exe 0 +2\\nExecWait '$INSTDIR\\\\bin\\\\tuntap-install.exe /S'\\nExecWait '$INSTDIR\\\\bin\\\\lokinet.exe --install'\\nExecWait 'sc failure lokinet reset= 60 actions= restart/1000'\\nExecWait '$INSTDIR\\\\bin\\\\lokinet.exe -g C:\\\\ProgramData\\\\lokinet\\\\lokinet.ini'\\nCopyFiles '$INSTDIR\\\\share\\\\bootstrap.signed' C:\\\\ProgramData\\\\lokinet\\\\bootstrap.signed\\n")
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "ExecWait 'net stop lokinet'\\nExecWait 'taskkill /f /t /im lokinet-gui.exe'\\nExecWait '$INSTDIR\\\\bin\\\\lokinet.exe --remove'\\nRMDir /r /REBOOTOK C:\\\\ProgramData\\\\lokinet")
set(CPACK_NSIS_CREATE_ICONS_EXTRA
"CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Lokinet.lnk' '$INSTDIR\\\\share\\\\gui\\\\lokinet-gui.exe'"
)
set(CPACK_NSIS_DELETE_ICONS_EXTRA
"Delete '$SMPROGRAMS\\\\$START_MENU\\\\Lokinet.lnk'"
)
get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS)
list(REMOVE_ITEM CPACK_COMPONENTS_ALL "Unspecified")
function(read_nsis_file filename outvar)
file(STRINGS "${filename}" _outvar)
list(TRANSFORM _outvar REPLACE "\\\\" "\\\\\\\\")
list(JOIN _outvar "\\n" out)
set(${outvar} ${out} PARENT_SCOPE)
endfunction()
read_nsis_file("${CMAKE_SOURCE_DIR}/win32-setup/extra_preinstall.nsis" _extra_preinstall)
read_nsis_file("${CMAKE_SOURCE_DIR}/win32-setup/extra_install.nsis" _extra_install)
read_nsis_file("${CMAKE_SOURCE_DIR}/win32-setup/extra_uninstall.nsis" _extra_uninstall)
read_nsis_file("${CMAKE_SOURCE_DIR}/win32-setup/extra_create_icons.nsis" _extra_create_icons)
read_nsis_file("${CMAKE_SOURCE_DIR}/win32-setup/extra_delete_icons.nsis" _extra_delete_icons)
set(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "${_extra_preinstall}")
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${_extra_install}")
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "${_extra_uninstall}")
set(CPACK_NSIS_CREATE_ICONS_EXTRA "${_extra_create_icons}")
set(CPACK_NSIS_DELETE_ICONS_EXTRA "${_extra_delete_icons}")
set(CPACK_NSIS_COMPRESSOR "/SOLID lzma")

@ -0,0 +1,68 @@
#!/bin/bash
set -e
default_abis="armeabi-v7a arm64-v8a x86_64"
build_abis=${ABIS:-$default_abis}
test x$NDK = x && test -e /usr/lib/android-ndk && export NDK=/usr/lib/android-ndk
test x$NDK = x && exit 1
echo "building abis: $build_abis"
root=$(readlink -f "$1")
shift
build=$(readlink -f "$1")
shift
mkdir -p $build
cd $build
for abi in $build_abis; do
mkdir -p build-$abi
cd build-$abi
cmake \
-S "$root" -B . \
-G 'Unix Makefiles' \
-DANDROID=ON \
-DANDROID_ABI=$abi \
-DANDROID_ARM_MODE=arm \
-DANDROID_PLATFORM=android-23 \
-DANDROID_API=23 \
-DANDROID_STL=c++_static \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DBUILD_STATIC_DEPS=ON \
-DBUILD_PACKAGE=ON \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTING=OFF \
-DBUILD_LIBLOKINET=OFF \
-DWITH_TESTS=OFF \
-DWITH_BOOTSTRAP=OFF \
-DNATIVE_BUILD=OFF \
-DSTATIC_LINK=ON \
-DWITH_SYSTEMD=OFF \
-DFORCE_OXENMQ_SUBMODULE=ON \
-DFORCE_OXENC_SUBMODULE=ON \
-DFORCE_FMT_SUBMODULE=ON \
-DFORCE_SPDLOG_SUBMODULE=ON \
-DFORCE_NLOHMANN_SUBMODULE=ON \
-DSUBMODULE_CHECK=OFF \
-DWITH_LTO=OFF \
-DCMAKE_BUILD_TYPE=Release \
"$@"
cd -
done
rm -f $build/Makefile
echo "# generated makefile" >> $build/Makefile
echo "all: $build_abis" >> $build/Makefile
for abi in $build_abis; do
echo -ne "$abi:\n\t" >> $build/Makefile
echo -ne '$(MAKE) -C ' >> $build/Makefile
echo "build-$abi lokinet-android" >> $build/Makefile
echo -ne "\tmkdir -p out/$abi && cp build-$abi/jni/liblokinet-android.so out/$abi/liblokinet-android.so\n\n" >> $build/Makefile
echo -ne "clean-$abi:\n\t" >> $build/Makefile
echo -ne '$(MAKE) -C ' >> $build/Makefile
echo "build-$abi clean" >> $build/Makefile
done
echo -ne "clean:" >> $build/Makefile
for targ in $build_abis ; do echo -ne " clean-$targ" >> $build/Makefile ; done
echo "" >> $build/Makefile

@ -2,50 +2,7 @@
set -e
set +x
default_abis="armeabi-v7a arm64-v8a x86 x86_64"
build_abis=${ABIS:-$default_abis}
test x$NDK = x && echo "NDK env var not set"
test x$NDK = x && exit 1
echo "building abis: $build_abis"
root="$(readlink -f $(dirname $0)/../)"
out=$root/lokinet-jni-$(git describe || echo unknown)
mkdir -p $out
mkdir -p $root/build-android
cd $root/build-android
for abi in $build_abis; do
mkdir -p build-$abi $out/$abi
cd build-$abi
cmake \
-G 'Unix Makefiles' \
-DANDROID=ON \
-DANDROID_ABI=$abi \
-DANDROID_ARM_MODE=arm \
-DANDROID_PLATFORM=android-23 \
-DANDROID_STL=c++_static \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DBUILD_STATIC_DEPS=ON \
-DBUILD_PACKAGE=ON \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTING=OFF \
-DBUILD_LIBLOKINET=OFF \
-DWITH_TESTS=OFF \
-DNATIVE_BUILD=OFF \
-DSTATIC_LINK=ON \
-DWITH_SYSTEMD=OFF \
-DFORCE_OXENMQ_SUBMODULE=ON \
-DSUBMODULE_CHECK=OFF \
-DWITH_LTO=OFF \
-DCMAKE_BUILD_TYPE=Release \
$@ $root
make lokinet-android -j${JOBS:-$(nproc)}
cp jni/liblokinet-android.so $out/$abi/liblokinet-android.so
cd -
done
echo
echo "build artifacts outputted to $out"
cd "$root"
./contrib/android-configure.sh . build-android "$@"
make -C build-android -j ${JOBS:-$(nproc)}

@ -1 +0,0 @@
lokinet-bootserv

@ -1,29 +0,0 @@
# replace your.server.tld with your server's fqdn
server {
listen 80;
server_name your.server.tld;
location / {
return 302 https://your.server.tld$request_uri;
}
location /.well-known/acme-challenge {
root /var/www/letsencrypt;
}
}
server {
listen 443 ssl;
server_name your.server.tld;
ssl_certificate /etc/letsencrypt/live/your.server.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your.server.tld/privkey.pem;
location / {
root /var/www/lokinet-bootserv;
}
location /bootstrap.signed {
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/local/bin/lokinet-bootserv;
fastcgi_pass unix://tmp/cgi.sock;
}
}

@ -1,4 +0,0 @@
# set me to where the nodedb is for lokinet
#[nodedb]
#dir=/path/to/nodedb/

@ -1,20 +0,0 @@
SRC = $(sort $(wildcard src/*.cpp))
OBJS = $(SRC:.cpp=.cpp.o)
CGI_EXE = lokinet-bootserv
CXX = clang++
all: build
build: $(CGI_EXE)
%.cpp.o: %.cpp
$(CXX) -g -std=c++17 -c -Wall -Werror -Wpedantic $^ -o $^.o
$(CGI_EXE): $(OBJS)
$(CXX) -o $(CGI_EXE) $^
clean:
rm -f $(CGI_EXE) $(OBJS)

@ -1,35 +0,0 @@
# lokinet-bootserv
cgi executable for serving a random RC for bootstrap from a nodedb
## configuring
copy the example config (privileged)
# cp configs/lokinet-bootserv.ini /usr/local/etc/lokinet-bootserv.ini
edit config to have proper values,
specifically make sure the `[nodedb]` section has a `dir` value that points to a static copy of a healthy nodedb
## building
to build:
$ make
## installing (priviledged)
install cgi binary:
# cp lokinet-bootserv /usr/local/bin/lokinet-bootserv
set up with nginx cgi:
# cp configs/lokinet-bootserv-nginx.conf /etc/nginx/sites-available/lokinet-bootserv.conf
# ln -s /etc/nginx/sites-available/lokinet-bootserv.conf /etc/nginx/sites-enabled/
## maintainence
add the following to crontab
0 0 * * * /usr/local/bin/lokinet-bootserv --cron

@ -1,171 +0,0 @@
#include "lokinet-cgi.hpp"
#include <fstream>
#include <dirent.h>
#include <list>
#include <sstream>
namespace lokinet
{
namespace bootserv
{
CGIHandler::CGIHandler(std::ostream& o) : Handler(o)
{
}
CGIHandler::~CGIHandler()
{
}
int
CGIHandler::Exec(const Config& conf)
{
const char* e = getenv("REQUEST_METHOD");
if(e == nullptr)
return ReportError("$REQUEST_METHOD not set");
std::string_view method(e);
if(method != "GET")
{
out << "Content-Type: text/plain" << std::endl;
out << "Status: 405 Method Not Allowed" << std::endl << std::endl;
return 0;
}
std::string fname;
if(!conf.VisitSection(
"nodedb", [&](const Config::Section_t& sect) -> bool {
auto itr = sect.find("dir");
if(itr == sect.end())
return false;
fname = PickRandomFileInDir(
std::string(itr->second.data(), itr->second.size()));
return true;
}))
return ReportError("bad values in nodedb section of config");
if(fname.empty())
{
// no files in nodedb
out << "Content-Type: text/plain" << std::endl;
out << "Status: 404 Not Found" << std::endl << std::endl;
return 0;
}
return ServeFile(fname.c_str(), "application/octect-stream");
}
std::string
CGIHandler::PickRandomFileInDir(std::string dirname) const
{
// collect files
std::list< std::string > files;
{
DIR* d = opendir(dirname.c_str());
if(d == nullptr)
{
return "";
};
std::list< std::string > subdirs;
dirent* ent = nullptr;
while((ent = readdir(d)))
{
std::string_view f = ent->d_name;
if(f != "." && f != "..")
{
std::stringstream ss;
ss << dirname;
ss << '/';
ss << f;
subdirs.emplace_back(ss.str());
}
}
closedir(d);
for(const auto& subdir : subdirs)
{
d = opendir(subdir.c_str());
if(d)
{
while((ent = readdir(d)))
{
std::string_view f;
f = ent->d_name;
if(f != "." && f != ".."
&& f.find_last_of(".signed") != std::string_view::npos)
{
std::stringstream ss;
ss << subdir << "/" << f;
files.emplace_back(ss.str());
}
}
closedir(d);
}
}
}
uint32_t randint;
{
std::basic_ifstream< uint32_t > randf("/dev/urandom");
if(!randf.is_open())
return "";
randf.read(&randint, 1);
}
auto itr = files.begin();
if(files.size() > 1)
std::advance(itr, randint % files.size());
return *itr;
}
int
CGIHandler::ServeFile(const char* fname, const char* contentType) const
{
std::ifstream f(fname);
if(f.is_open())
{
f.seekg(0, std::ios::end);
auto sz = f.tellg();
f.seekg(0, std::ios::beg);
if(sz)
{
out << "Content-Type: " << contentType << std::endl;
out << "Status: 200 OK" << std::endl;
out << "Content-Length: " << std::to_string(sz) << std::endl
<< std::endl;
char buf[512] = {0};
size_t r = 0;
while((r = f.readsome(buf, sizeof(buf))) > 0)
out.write(buf, r);
out << std::flush;
}
else
{
out << "Content-Type: text/plain" << std::endl;
out << "Status: 500 Internal Server Error" << std::endl << std::endl;
out << "could not serve '" << fname << "' as it is an empty file"
<< std::endl;
}
}
else
{
out << "Content-Type: text/plain" << std::endl;
out << "Status: 404 Not Found" << std::endl << std::endl;
out << "could not serve '" << fname
<< "' as it does not exist on the filesystem" << std::endl;
}
return 0;
}
int
CGIHandler::ReportError(const char* err)
{
out << "Content-Type: text/plain" << std::endl;
out << "Status: 500 Internal Server Error" << std::endl << std::endl;
out << err << std::endl;
return 0;
}
Handler_ptr
NewCGIHandler(std::ostream& out)
{
return std::make_unique< CGIHandler >(out);
}
} // namespace bootserv
} // namespace lokinet

@ -1,43 +0,0 @@
#ifndef LOKINET_BOOTSERV_HANDLER_HPP
#define LOKINET_BOOTSERV_HANDLER_HPP
#include <iostream>
#include "lokinet-config.hpp"
namespace lokinet
{
namespace bootserv
{
struct Handler
{
Handler(std::ostream& o) : out(o){};
virtual ~Handler(){};
/// handle command
/// return exit code
virtual int
Exec(const Config& conf) = 0;
/// report an error to system however that is done
/// return exit code
virtual int
ReportError(const char* err) = 0;
protected:
std::ostream& out;
};
using Handler_ptr = std::unique_ptr< Handler >;
/// create cgi handler
Handler_ptr
NewCGIHandler(std::ostream& out);
/// create cron handler
Handler_ptr
NewCronHandler(std::ostream& out);
} // namespace bootserv
} // namespace lokinet
#endif

@ -1,31 +0,0 @@
#ifndef BOOTSERV_LOKINET_CRON_HPP
#define BOOTSERV_LOKINET_CRON_HPP
#include "handler.hpp"
namespace lokinet
{
namespace bootserv
{
struct CGIHandler final : public Handler
{
CGIHandler(std::ostream& o);
~CGIHandler();
int
Exec(const Config& conf) override;
int
ReportError(const char* err) override;
int
ServeFile(const char* fname, const char* mime) const;
std::string
PickRandomFileInDir(std::string dirname) const;
};
} // namespace bootserv
} // namespace lokinet
#endif

@ -1,132 +0,0 @@
#include "lokinet-config.hpp"
#include <fstream>
#include <list>
#include <iostream>
namespace lokinet
{
namespace bootserv
{
const char* Config::DefaultPath = "/usr/local/etc/lokinet-bootserv.ini";
bool
Config::LoadFile(const char* fname)
{
{
std::ifstream f(fname);
if(!f.is_open())
return false;
f.seekg(0, std::ios::end);
m_Data.resize(f.tellg());
f.seekg(0, std::ios::beg);
if(m_Data.size() == 0)
return false;
f.read(m_Data.data(), m_Data.size());
}
return Parse();
}
void
Config::Clear()
{
m_Config.clear();
m_Data.clear();
}
bool
Config::Parse()
{
std::list< String_t > lines;
{
auto itr = m_Data.begin();
// split into lines
while(itr != m_Data.end())
{
auto beg = itr;
while(itr != m_Data.end() && *itr != '\n' && *itr != '\r')
++itr;
lines.emplace_back(std::addressof(*beg), (itr - beg));
if(itr == m_Data.end())
break;
++itr;
}
}
String_t sectName;
for(const auto& line : lines)
{
String_t realLine;
auto comment = line.find_first_of(';');
if(comment == String_t::npos)
comment = line.find_first_of('#');
if(comment == String_t::npos)
realLine = line;
else
realLine = line.substr(0, comment);
// blank or commented line?
if(realLine.size() == 0)
continue;
// find delimiters
auto sectOpenPos = realLine.find_first_of('[');
auto sectClosPos = realLine.find_first_of(']');
auto kvDelim = realLine.find_first_of('=');
if(sectOpenPos != String_t::npos && sectClosPos != String_t::npos
&& kvDelim == String_t::npos)
{
// section header
// clamp whitespaces
++sectOpenPos;
while(std::isspace(realLine[sectOpenPos])
&& sectOpenPos != sectClosPos)
++sectOpenPos;
--sectClosPos;
while(std::isspace(realLine[sectClosPos])
&& sectClosPos != sectOpenPos)
--sectClosPos;
// set section name
sectName = realLine.substr(sectOpenPos, sectClosPos);
}
else if(kvDelim != String_t::npos)
{
// key value pair
String_t::size_type k_start = 0;
String_t::size_type k_end = kvDelim;
String_t::size_type v_start = kvDelim + 1;
String_t::size_type v_end = realLine.size() - 1;
// clamp whitespaces
while(std::isspace(realLine[k_start]) && k_start != kvDelim)
++k_start;
while(std::isspace(realLine[k_end]) && k_end != k_start)
--k_end;
while(std::isspace(realLine[v_start]) && v_start != v_end)
++v_start;
while(std::isspace(realLine[v_end]))
--v_end;
// sect.k = v
String_t k = realLine.substr(k_start, k_end);
String_t v = realLine.substr(v_start, v_end);
Section_t& sect = m_Config[sectName];
sect[k] = v;
}
else // malformed?
return false;
}
return true;
}
bool
Config::VisitSection(
const char* name,
std::function< bool(const Section_t& sect) > visit) const
{
auto itr = m_Config.find(name);
if(itr == m_Config.end())
return false;
return visit(itr->second);
}
} // namespace bootserv
} // namespace lokinet

@ -1,47 +0,0 @@
#ifndef LOKINET_BOOTSERV_CONFIG_HPP
#define LOKINET_BOOTSERV_CONFIG_HPP
#include <unordered_map>
#include <string_view>
#include <functional>
#include <memory>
#include <vector>
namespace lokinet
{
namespace bootserv
{
struct Config
{
using String_t = std::string_view;
using Section_t = std::unordered_map< String_t, String_t >;
using Config_impl_t = std::unordered_map< String_t, Section_t >;
static const char* DefaultPath;
/// clear config
void
Clear();
/// load config file for bootserv
/// return true on success
/// return false on error
bool
LoadFile(const char* fname);
/// visit a section in config read only by name
/// return false if no section or value propagated from visitor
bool
VisitSection(const char* name,
std::function< bool(const Section_t&) > visit) const;
private:
bool
Parse();
std::vector< char > m_Data;
Config_impl_t m_Config;
};
} // namespace bootserv
} // namespace lokinet
#endif

@ -1,37 +0,0 @@
#include "lokinet-cron.hpp"
namespace lokinet
{
namespace bootserv
{
CronHandler::CronHandler(std::ostream& o) : Handler(o)
{
}
CronHandler::~CronHandler()
{
}
int
CronHandler::Exec(const Config& conf)
{
// this runs the cron tasks
// TODO: implement me
return 0;
}
int
CronHandler::ReportError(const char* err)
{
out << "error: " << err << std::endl;
return 1;
}
Handler_ptr
NewCronHandler(std::ostream& out)
{
return std::make_unique< CronHandler >(out);
}
} // namespace bootserv
} // namespace lokinet

@ -1,25 +0,0 @@
#ifndef BOOTSERV_LOKINET_CRON_HPP
#define BOOTSERV_LOKINET_CRON_HPP
#include "handler.hpp"
namespace lokinet
{
namespace bootserv
{
struct CronHandler final : public Handler
{
CronHandler(std::ostream& o);
~CronHandler();
int
Exec(const Config& conf) override;
int
ReportError(const char* err) override;
};
} // namespace bootserv
} // namespace lokinet
#endif

@ -1,60 +0,0 @@
#include "handler.hpp"
#include "lokinet-config.hpp"
#include <getopt.h>
#include <string_view>
#include <sstream>
static int
printhelp(const char* exe)
{
std::cout << "usage: " << exe << " [--cron] [--conf /path/to/alt/config.ini]"
<< std::endl;
return 1;
}
int
main(int argc, char* argv[])
{
bool RunCron = false;
const char* confFile = lokinet::bootserv::Config::DefaultPath;
lokinet::bootserv::Config config;
lokinet::bootserv::Handler_ptr handler;
option longopts[] = {{"cron", no_argument, 0, 'C'},
{"help", no_argument, 0, 'h'},
{"conf", required_argument, 0, 'c'},
{0, 0, 0, 0}};
int c = 0;
int index = 0;
while((c = getopt_long(argc, argv, "hCc:", longopts, &index)) != -1)
{
switch(c)
{
case 'h':
return printhelp(argv[0]);
case 'C':
RunCron = true;
break;
case 'c':
confFile = optarg;
break;
}
}
if(RunCron)
handler = lokinet::bootserv::NewCronHandler(std::cout);
else
handler = lokinet::bootserv::NewCGIHandler(std::cout);
if(!config.LoadFile(confFile))
{
std::stringstream ss;
ss << "failed to load " << confFile;
return handler->ReportError(ss.str().c_str());
}
else
return handler->Exec(config);
}

@ -1 +1 @@
d1:ald1:ci2e1:d3:iwp1:e32:9ãxÚsX«l%ìû€ê<,sØ›•©÷ïå_1:i21:::ffff:144.76.164.2021:pi1666e1:vi0eee1:i5:gamma1:k32:ÞÊðòm=o„ZÐ1ÿßmcŒ%»¸ÿû¾™SĹ1:p32:!EÏâéz˜ý:Š‹úý… /0¡Ú„ Ãݪ„µNçB1:rli0ei0ei8ei3ee1:ui1614788310454e1:vi0e1:xle1:z64:Œ¤u G¿”D“=Œxµ¢{ïÌ51þ`í߀ùEâw m)q2Øg¯±˜øš ï³À)˜TÑP•´ò³ö—Á1e
ld1:ald1:ci2e1:d3:iwp1:e32:9ãxÚsX«l%ìû€ê<,sØ›•©÷ïå_1:i21:::ffff:144.76.164.2021:pi1666e1:vi0eee1:i5:gamma1:k32:ÞÊðòm=o„ZÐ1ÿßmcŒ%»¸ÿû¾™SĹ1:p32:!EÏâéz˜ý:Š‹úý… /0¡Ú„ Ãݪ„µNçB1:rli0ei0ei8ei3ee1:ui1614788310454e1:vi0e1:xle1:z64:Œ¤u G¿”D“=Œxµ¢{ïÌ51þ`í߀ùEâw m)q2Øg¯±˜øš ï³À)˜TÑP•´ò³ö—Á1ee

@ -82,7 +82,7 @@ def run_or_report(*args, myline):
log.write(e.output.encode())
global failure
failure = True
print_line(myline, "\033[31;1mError! See {} for details", log.name)
print_line(myline, "\033[31;1mError! See {} for details".format(log.name))
raise e

@ -7,7 +7,8 @@ set -o errexit
bad=
if [ "$DRONE_STAGE_OS" == "darwin" ]; then
if otool -L daemon/lokinet | grep -Ev '^daemon/lokinet:|^\t(/usr/lib/libSystem\.|/usr/lib/libc\+\+\.|/System/Library/Frameworks/CoreFoundation)'; then
if otool -L llarp/apple/org.lokinet.network-extension.systemextension/Contents/MacOS/org.lokinet.network-extension | \
grep -Ev '^llarp/apple:|^\t(/usr/lib/lib(System\.|c\+\+|objc))|/System/Library/Frameworks/(CoreFoundation|NetworkExtension|Foundation|Network)\.framework'; then
bad=1
fi
elif [ "$DRONE_STAGE_OS" == "linux" ]; then

@ -1,6 +1,9 @@
#!/usr/bin/env bash
test "x$IGNORE" != "x" && exit 0
. $(dirname $0)/../format-version.sh
repo=$(readlink -e $(dirname $0)/../../)
clang-format-11 -i $(find $repo/jni $repo/daemon $repo/llarp $repo/include $repo/pybind | grep -E '\.[hc](pp)?$')
$CLANG_FORMAT -i $(find $repo/jni $repo/daemon $repo/llarp $repo/include $repo/pybind | grep -E '\.[hc](pp)?$')
jsonnetfmt -i $repo/.drone.jsonnet
git --no-pager diff --exit-code --color || (echo -ne '\n\n\e[31;1mLint check failed; please run ./contrib/format.sh\e[0m\n\n' ; exit 1)

@ -19,9 +19,15 @@ set -o xtrace # Don't start tracing until *after* we write the ssh key
chmod 600 ssh_key
os="${UPLOAD_OS:-$DRONE_STAGE_OS-$DRONE_STAGE_ARCH}"
if [ -n "$WINDOWS_BUILD_NAME" ]; then
os="windows-$WINDOWS_BUILD_NAME"
os="$UPLOAD_OS"
if [ -z "$os" ]; then
if [ "$DRONE_STAGE_OS" == "darwin" ]; then
os="macos-$DRONE_STAGE_ARCH"
elif [ -n "$WINDOWS_BUILD_NAME" ]; then
os="windows-$WINDOWS_BUILD_NAME"
else
os="$DRONE_STAGE_OS-$DRONE_STAGE_ARCH"
fi
fi
if [ -n "$DRONE_TAG" ]; then
@ -34,8 +40,11 @@ else
fi
mkdir -v "$base"
if [ -e build-windows ]; then
cp -av build-windows/lokinet-*.exe "$base"
if [ -e build/win32 ]; then
# save debug symbols
cp -av build/win32/daemon/debug-symbols.tar.xz "$base-debug-symbols.tar.xz"
# save installer
cp -av build/win32/*.exe "$base"
# zipit up yo
archive="$base.zip"
zip -r "$archive" "$base"
@ -43,9 +52,17 @@ elif [ -e lokinet.apk ] ; then
# android af ngl
archive="$base.apk"
cp -av lokinet.apk "$archive"
elif [ -e build-docs ]; then
archive="$base.tar.xz"
cp -av build-docs/docs/mkdocs.yml build-docs/docs/markdown "$base"
tar cJvf "$archive" "$base"
elif [ -e build-mac ]; then
archive="$base.tar.xz"
mv build-mac/Lokinet*/ "$base"
tar cJvf "$archive" "$base"
else
cp -av daemon/lokinet daemon/lokinet-vpn "$base"
cp -av ../contrib/bootstrap/mainnet.signed "$base/bootstrap.signed"
cp -av build/daemon/lokinet{,-vpn} "$base"
cp -av contrib/bootstrap/mainnet.signed "$base/bootstrap.signed"
# tar dat shiz up yo
archive="$base.tar.xz"
tar cJvf "$archive" "$base"
@ -57,6 +74,7 @@ upload_to="oxen.rocks/${DRONE_REPO// /_}/${DRONE_BRANCH// /_}"
# -mkdir a/, -mkdir a/b/, -mkdir a/b/c/, ... commands. The leading `-` allows the command to fail
# without error.
upload_dirs=(${upload_to//\// })
put_debug=
mkdirs=
dir_tmp=""
for p in "${upload_dirs[@]}"; do
@ -64,10 +82,13 @@ for p in "${upload_dirs[@]}"; do
mkdirs="$mkdirs
-mkdir $dir_tmp"
done
if [ -e "$base-debug-symbols.tar.xz" ] ; then
put_debug="put $base-debug-symbols.tar.xz $upload_to"
fi
sftp -i ssh_key -b - -o StrictHostKeyChecking=off drone@oxen.rocks <<SFTP
$mkdirs
put $archive $upload_to
$put_debug
SFTP
set +o xtrace

@ -0,0 +1,2 @@
[logging]
level=debug

@ -0,0 +1,5 @@
#
# "suggested" default exit node config
#
[network]
exit-node=exit.loki

@ -0,0 +1,5 @@
#
# persist .loki address in a private key file in the data dir
#
[network]
keyfile=lokinet-addr.privkey

@ -0,0 +1,65 @@
#!/bin/bash
#
# helper script for me for when i cross compile
# t. jeff
#
set -e
die() {
echo $@
exit 1
}
platform=${PLATFORM:-Linux}
root="$(readlink -e $(dirname $0)/../)"
cd $root
mkdir -p build-cross
targets=()
cmake_extra=()
while [ "$#" -gt 0 ]; do
if [ "$1" = "--" ]; then
shift
cmake_extra=("$@")
break
fi
targets+=("$1")
shift
done
test ${#targets[@]} = 0 && die no targets provided
archs="${targets[@]}"
echo "all: $archs" > build-cross/Makefile
for arch in $archs ; do
mkdir -p $root/build-cross/build-$arch
cd $root/build-cross/build-$arch
cmake \
-G 'Unix Makefiles' \
-DCROSS_PLATFORM=$platform \
-DCROSS_PREFIX=$arch \
-DCMAKE_EXE_LINKER_FLAGS=-fstack-protector \
-DCMAKE_CXX_FLAGS=-fdiagnostics-color=always \
-DCMAKE_TOOLCHAIN_FILE=$root/contrib/cross/cross.toolchain.cmake \
-DBUILD_STATIC_DEPS=ON \
-DSTATIC_LINK=ON \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTING=OFF \
-DBUILD_LIBLOKINET=OFF \
-DWITH_TESTS=OFF \
-DNATIVE_BUILD=OFF \
-DSTATIC_LINK=ON \
-DWITH_SYSTEMD=OFF \
-DFORCE_OXENMQ_SUBMODULE=ON \
-DSUBMODULE_CHECK=OFF \
-DWITH_LTO=OFF \
-DWITH_BOOTSTRAP=OFF \
-DCMAKE_BUILD_TYPE=RelWithDeb \
"${cmake_extra[@]}" \
$root
cd $root/build-cross
echo -ne "$arch:\n\t\$(MAKE) -C build-$arch\n" >> $root/build-cross/Makefile
done
cd $root
make -j${JOBS:-$(nproc)} -C build-cross

@ -1,12 +0,0 @@
set(CMAKE_SYSTEM_NAME Linux)
set(TOOLCHAIN_PREFIX aarch64-linux-gnu)
#set(TOOLCHAIN_SUFFIX)
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc${TOOLCHAIN_SUFFIX})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++${TOOLCHAIN_SUFFIX})

@ -1,7 +1,5 @@
set(CMAKE_SYSTEM_NAME Linux)
set(TOOLCHAIN_PREFIX arm-linux-gnueabihf)
set(TOOLCHAIN_SUFFIX -8)
set(CMAKE_SYSTEM_NAME ${CROSS_PLATFORM})
set(TOOLCHAIN_PREFIX ${CROSS_PREFIX})
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
@ -10,3 +8,4 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc${TOOLCHAIN_SUFFIX})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++${TOOLCHAIN_SUFFIX})
set(ARCH_TRIPLET ${TOOLCHAIN_PREFIX})

@ -1,4 +1,8 @@
set(CMAKE_SYSTEM_VERSION 5.0)
set(CMAKE_SYSTEM_VERSION 6.0)
# the minimum windows version, set to 6 rn because supporting older windows is hell
set(_winver 0x0600)
add_definitions(-D_WIN32_WINNT=${_winver})
# target environment on the build host system
# second one is for non-root installs

@ -1,12 +0,0 @@
set(CMAKE_SYSTEM_NAME Linux)
set(TOOLCHAIN_PREFIX powerpc64le-linux-gnu)
set(TOOLCHAIN_SUFFIX -8)
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc${TOOLCHAIN_SUFFIX})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++${TOOLCHAIN_SUFFIX})

@ -1,60 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
Created by Manifold
--><service_bundle type="manifest" name="lokinet">
<service name="site/lokinet" type="service" version="1">
<dependency name="network" grouping="require_all" restart_on="error" type="service">
<service_fmri value="svc:/milestone/network:default"/>
</dependency>
<dependency name="filesystem" grouping="require_all" restart_on="error" type="service">
<service_fmri value="svc:/system/filesystem/local"/>
</dependency>
<instance name="default" enabled="false">
<method_context>
<method_credential user="lokinet" group="lokinet"/>
</method_context>
<exec_method type="method" name="start" exec="/usr/bin/lokinet %{config_file}" timeout_seconds="60"/>
<exec_method type="method" name="stop" exec="/usr/bin/kill -INT &lt;&lt;&lt; `pgrep lokinet`" timeout_seconds="60"/>
<property_group name="startd" type="framework">
<propval name="duration" type="astring" value="child"/>
<propval name="ignore_error" type="astring" value="core,signal"/>
</property_group>
<property_group name="application" type="application">
<propval name="config_file" type="astring" value="/etc/loki/lokinet.ini"/>
</property_group>
</instance>
<stability value="Evolving"/>
<template>
<common_name>
<loctext xml:lang="C">
LokiNET: Anonymous Network layer thingydoo.
</loctext>
</common_name>
</template>
</service>
</service_bundle>

@ -1,18 +0,0 @@
#!/usr/sbin/dtrace -s
syscall:::entry
/pid == $target/
{
@calls[ustack(10), probefunc] = count();
}
profile:::tick-1sec
{
/** print */
printa(@calls);
/** clear */
clear(@calls);
trunc(@calls, 15);
}

@ -0,0 +1,19 @@
CLANG_FORMAT_DESIRED_VERSION=14
CLANG_FORMAT=$(command -v clang-format-$CLANG_FORMAT_DESIRED_VERSION 2>/dev/null)
if [ $? -ne 0 ]; then
CLANG_FORMAT=$(command -v clang-format-mp-$CLANG_FORMAT_DESIRED_VERSION 2>/dev/null)
fi
if [ $? -ne 0 ]; then
CLANG_FORMAT=$(command -v clang-format 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Please install clang-format version $CLANG_FORMAT_DESIRED_VERSION and re-run this script."
exit 1
fi
version=$(clang-format --version)
if [[ ! $version == *"clang-format version $CLANG_FORMAT_DESIRED_VERSION"* ]]; then
echo "Please install clang-format version $CLANG_FORMAT_DESIRED_VERSION and re-run this script."
exit 1
fi
fi

@ -1,43 +1,27 @@
#!/usr/bin/env bash
CLANG_FORMAT_DESIRED_VERSION=11
binary=$(command -v clang-format-$CLANG_FORMAT_DESIRED_VERSION 2>/dev/null)
if [ $? -ne 0 ]; then
binary=$(command -v clang-format-mp-$CLANG_FORMAT_DESIRED_VERSION 2>/dev/null)
fi
if [ $? -ne 0 ]; then
binary=$(command -v clang-format 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Please install clang-format version $CLANG_FORMAT_DESIRED_VERSION and re-run this script."
exit 1
fi
version=$(clang-format --version)
if [[ ! $version == *"clang-format version $CLANG_FORMAT_DESIRED_VERSION"* ]]; then
echo "Please install clang-format version $CLANG_FORMAT_DESIRED_VERSION and re-run this script."
exit 1
fi
fi
. $(dirname $0)/format-version.sh
cd "$(dirname $0)/../"
if [ "$1" = "verify" ] ; then
if [ $($binary --output-replacements-xml $(find jni daemon llarp include pybind | grep -E '\.([hc](pp)?|mm?)$' | grep -v '\#') | grep '</replacement>' | wc -l) -ne 0 ] ; then
if [ $($CLANG_FORMAT --output-replacements-xml $(find jni daemon llarp include pybind | grep -E '\.([hc](pp)?|m(m)?)$' | grep -v '#') | grep '</replacement>' | wc -l) -ne 0 ] ; then
exit 2
fi
else
$binary -i $(find jni daemon llarp include pybind | grep -E '\.([hc](pp)?|mm)$' | grep -v '\#') &> /dev/null
$CLANG_FORMAT -i $(find jni daemon llarp include pybind | grep -E '\.([hc](pp)?|m(m)?)$' | grep -v '#') &> /dev/null
fi
swift_format=$(command -v swiftformat 2>/dev/null)
if [ $? -eq 0 ]; then
if [ "$1" = "verify" ] ; then
for f in $(find daemon | grep -E '\.swift$' | grep -v '\#') ; do
for f in $(find daemon | grep -E '\.swift$' | grep -v '#') ; do
if [ $($swift_format --quiet --dryrun < "$f" | diff "$f" - | wc -l) -ne 0 ] ; then
exit 3
fi
done
else
$swift_format --quiet $(find daemon | grep -E '\.swift$' | grep -v '\#')
$swift_format --quiet $(find daemon | grep -E '\.swift$' | grep -v '#')
fi
fi

@ -1,20 +0,0 @@
#!/bin/sh
. /etc/rc.subr
name=lokinet
rcvar=lokinet_enable
command="/usr/local/bin/${name}"
command_args="/usr/local/etc/${name}/daemon.ini > /dev/null 2>&1"
pidfile="/usr/local/etc/${name}/lokinet.pid"
required_files="/usr/local/etc/${name}/daemon.ini"
sig_reload="HUP"
start_precmd="${command} -g /usr/local/etc/${name}/daemon.ini"
load_rc_config $name
run_rc_command "$1"

@ -0,0 +1,26 @@
#!/usr/bin/env python3
#
# .loki secret key generator script
# makes keyfile contents
#
# usage: python3 keygen.py out.private
# python3 keygen.py > /some/where/over/the/rainbow
#
from nacl.bindings import crypto_sign_keypair
import sys
out = sys.stdout
close_out = lambda : None
args = sys.argv[1:]
if args and args[0] != '-':
out = open(args[0], 'wb')
close_out = out.close
pk, sk = crypto_sign_keypair()
out.write(b'64:')
out.write(sk)
out.flush()
close_out()

@ -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)

@ -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

@ -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;
}

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- our size/viewbox is positioned such that 0,0 is the center of the image (to simplify scaling and rotation). -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="-512px" y="-512px"
viewBox="-512 -512 1024 1024" style="enable-background:new -512 -512 1024 1024;" xml:space="preserve">
<style type="text/css">
.bg{fill:#FFFFFF;}
</style>
<!--
Draw the background shape in a 2x2 box (from -1 to 1 in each dimension), then scale it up
(but not all the way to 512, because we want some padding around the outside.
-->
<g transform="scale(415)">
<path class="bg" d="
M 0.5 1
H -0.5
C -0.81,1 -1,0.81 -1,0.5
V -0.5
C -1,-0.81 -0.81,-1 -0.5,-1
H 0.5
C 0.81,-1 1,-0.81 1,-0.5
V 0.5
C 1,0.81 0.81,1 0.5,1
z
"/>
</g>
<g id="shape0">
<!--
Start with a simple 3x2 shape, where each unit we draw corresponds to 1 block edge length in the
final diagram, and shift it so that 2.5x2.5 becomes the new origin (around which we will rotate).
Then we rotate and scale it to the desired size.
We can then copy that at 90, 180, 270 degree rotations to complete the logo.
-->
<g transform="rotate(45) scale(85) translate(-2.5, -2.5)">
<polygon points="0,0 2,0 2,1 1,1 1,2 0,2"/>
<rect x="1" y="2" width="1" height="1"/>
</g>
</g>
<use xlink:href="#shape0" transform="rotate(90)"/>
<use xlink:href="#shape0" transform="rotate(180)"/>
<use xlink:href="#shape0" transform="rotate(270)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -1,21 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 189.4 189.4" style="enable-background:new 0 0 189.4 189.4;" xml:space="preserve">
<!-- our size/viewbox is positioned such that 0,0 is the center of the image (to simplify scaling and rotation). -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="-512px" y="-512px"
viewBox="-512 -512 1024 1024" style="enable-background:new -512 -512 1024 1024;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.bg{fill:#FFFFFF;}
</style>
<g>
<polygon class="st0" points="113.6,132.6 94.7,151.5 75.8,132.6 56.8,151.5 94.7,189.4 132.6,151.5 "/>
<polygon class="st0" points="132.6,113.6 151.5,94.7 132.6,75.8 151.5,56.8 189.4,94.7 151.5,132.6 "/>
<polygon class="st0" points="56.8,75.8 37.9,94.7 56.8,113.6 37.9,132.6 0,94.7 37.9,56.8 "/>
<polygon class="st0" points="75.8,56.8 94.7,37.9 113.6,56.8 132.6,37.9 94.7,0 56.8,37.9 "/>
<rect x="100.2" y="100.2" transform="matrix(0.7071 0.7071 -0.7071 0.7071 113.6329 -47.0683)" class="st0" width="26.8" height="26.8"/>
<rect x="62.4" y="62.4" transform="matrix(0.7071 0.7071 -0.7071 0.7071 75.7552 -31.3789)" class="st0" width="26.8" height="26.8"/>
<rect x="100.2" y="62.4" transform="matrix(0.7071 0.7071 -0.7071 0.7071 86.8493 -58.1624)" class="st0" width="26.8" height="26.8"/>
<rect x="62.4" y="100.2" transform="matrix(0.7071 0.7071 -0.7071 0.7071 102.5388 -20.2848)" class="st0" width="26.8" height="26.8"/>
<!--
Draw the background shape in a 2x2 box (from -1 to 1 in each dimension), then scale it up
(but not all the way to 512, because we want some padding around the outside.
-->
<g transform="scale(512)">
<circle r="1" class="bg"/>
</g>
<g id="shape0">
<!--
Start with a simple 3x2 shape, where each unit we draw corresponds to 1 block edge length in the
final diagram, and shift it so that 2.5x2.5 becomes the new origin (around which we will rotate).
Then we rotate and scale it to the desired size.
We can then copy that at 90, 180, 270 degree rotations to complete the logo.
-->
<g transform="rotate(45) scale(105) translate(-2.5, -2.5)">
<polygon points="0,0 2,0 2,1 1,1 1,2 0,2"/>
<rect x="1" y="2" width="1" height="1"/>
</g>
</g>
<use xlink:href="#shape0" transform="rotate(90)"/>
<use xlink:href="#shape0" transform="rotate(180)"/>
<use xlink:href="#shape0" transform="rotate(270)"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,28 @@
#!/bin/bash
set -e
set -x
if ! [ -f LICENSE ] || ! [ -d llarp ]; then
echo "You need to run this as ./contrib/mac.sh from the top-level lokinet project directory" >&2
exit 1
fi
mkdir -p build-mac
cd build-mac
cmake \
-G Ninja \
-DBUILD_STATIC_DEPS=ON \
-DBUILD_LIBLOKINET=OFF \
-DWITH_TESTS=OFF \
-DWITH_BOOTSTRAP=OFF \
-DNATIVE_BUILD=OFF \
-DWITH_LTO=ON \
-DCMAKE_BUILD_TYPE=Release \
-DMACOS_SYSTEM_EXTENSION=ON \
-DCODESIGN=ON \
-DBUILD_PACKAGE=ON \
"$@" \
..
echo "cmake build configured in build-mac"

@ -8,32 +8,20 @@
#
set -e
set +x
if ! [ -f LICENSE.txt ] || ! [ -d llarp ]; then
echo "You need to run this as ./contrib/mac.sh from the top-level lokinet project directory"
set -x
if ! [ -f LICENSE ] || ! [ -d llarp ]; then
echo "You need to run this as ./contrib/mac.sh from the top-level lokinet project directory" >&2
exit 1
fi
mkdir -p build-mac
./contrib/mac-configure.sh "$@"
cd build-mac
cmake \
-G Ninja \
-DBUILD_STATIC_DEPS=ON \
-DBUILD_PACKAGE=ON \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTING=OFF \
-DBUILD_LIBLOKINET=OFF \
-DWITH_TESTS=OFF \
-DNATIVE_BUILD=OFF \
-DSTATIC_LINK=ON \
-DWITH_SYSTEMD=OFF \
-DFORCE_OXENMQ_SUBMODULE=ON \
-DSUBMODULE_CHECK=OFF \
-DWITH_LTO=ON \
-DCMAKE_BUILD_TYPE=Release \
"$@" \
..
ninja sign
rm -rf Lokinet\ *
ninja -j${JOBS:-1} package
cd ..
echo -e "Build complete, your app is here:\n"
ls -lad $(pwd)/daemon/lokinet.app
ls -lad $(pwd)/build-mac/Lokinet\ *
echo ""

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Lokinet</string>
<key>CFBundleExecutable</key>
<string>MacOS/lokinet</string>
<key>CFBundleIdentifier</key>
<string>com.loki-project.lokinet</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>lokinet</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>@lokinet_VERSION@</string>
<key>CFBundleVersion</key>
<string>@lokinet_VERSION@.@LOKINET_APPLE_BUILD@</string>
</dict>
</plist>

Binary file not shown.

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>Lokinet</string>
<key>CFBundleExecutable</key>
<string>lokinet-extension</string>
<key>CFBundleIdentifier</key>
<string>com.loki-project.lokinet.network-extension</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleName</key>
<string>lokinet</string>
<key>CFBundleVersion</key>
<string>@lokinet_VERSION@</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSMinimumSystemVersion</key>
<string>11.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.packet-tunnel</string>
<key>NSExtensionPrincipalClass</key>
<string>LLARPPacketTunnel</string>
</dict>
</dict>
</plist>

@ -1,38 +0,0 @@
This directory contains the magical incantations and random voodoo symbols needed to coax an Apple
build. There's no reason builds have to be this stupid, except that Apple wants to funnel everyone
into the no-CI, no-help, undocumented, non-toy-apps-need-not-apply modern Apple culture.
This is disgusting.
But it gets worse.
The following two files, in particular, are the very worst manifestations of this already toxic
Apple cancer: they are required for proper permissions to run on macOS, are undocumented, and can
only be regenerated through the entirely closed source Apple Developer backend, for which you have
to pay money first to get a team account (a personal account will not work), and they lock the
resulting binaries to only run on individually selected Apple computers selected at the time the
profile is provisioned (with no ability to allow it to run anywhere).
lokinet.provisionprofile
lokinet-extension.provisionprofile
This is actively hostile to open source development, but that is nothing new for Apple.
In order to make things work, you'll have to replace these provisioning profiles with your own
(after paying Apple for the privilege of developing on their platform, of course) and change all the
team/application/bundle IDs to reference your own team, matching the provisioning profiles. The
provisioning profiles must be a "macOS Development" provisioning profile, and must include the
signing keys and the authorized devices on which you want to run it. (The profiles bundled in this
repository contains the lokinet team's "Apple Development" keys associated with the Oxen project,
and mac dev boxes. This is *useless* for anyone else).
Also take note that you *must not* put a development build `lokinet.app` inside /Applications
because if you do, it won't work because *on top* of the ridiculous signing and entitlement bullshit
that Apple makes you jump through, the rules *also* differ for binaries placed in /Applications
versus binaries placed elsewhere, but like everything else here, it is entirely undocumented.
If you are reading this to try to build Lokinet for yourself for an Apple operating system and
simultaneously care about open source, privacy, or freedom then you, my friend, are a walking
contradiction: you are trying to get Lokinet to work on a platform that actively despises open
source, privacy, and freedom. Even Windows is a better choice in all of these categories than
Apple.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Lokinet Network Extension</string>
<key>CFBundleExecutable</key>
<string>org.lokinet.network-extension</string>
<key>CFBundleIdentifier</key>
<string>org.lokinet.network-extension</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>SYSX</string>
<key>CFBundleName</key>
<string>org.lokinet.network-extension</string>
<key>CFBundleVersion</key>
<string>@lokinet_VERSION@.@LOKINET_APPLE_BUILD@</string>
<key>CFBundleShortVersionString</key>
<string>@lokinet_VERSION@</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2022 The Oxen Project, licensed under GPLv3-or-later</string>
<key>NSSystemExtensionUsageDescription</key>
<string>Provides Lokinet Network connectivity.</string>
<key>NetworkExtension</key>
<dict>
<key>NEMachServiceName</key>
<string>SUQ8J2PCT7.org.lokinet.network-extension</string>
<key>NEProviderClasses</key>
<dict>
<key>com.apple.networkextension.packet-tunnel</key>
<string>LLARPPacketTunnel</string>
<key>com.apple.networkextension.dns-proxy</key>
<string>LLARPDNSProxy</string>
</dict>
</dict>
</dict>
</plist>

@ -3,11 +3,12 @@
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>SUQ8J2PCT7.com.loki-project.lokinet.network-extension</string>
<string>SUQ8J2PCT7.org.lokinet.network-extension</string>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
<string>dns-proxy</string>
</array>
<key>com.apple.developer.team-identifier</key>
@ -16,9 +17,6 @@
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.get-task-allow</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>SUQ8J2PCT7.org.lokinet.network-extension</string>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider-systemextension</string>
<string>dns-proxy-systemextension</string>
</array>
<key>com.apple.developer.team-identifier</key>
<string>SUQ8J2PCT7</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>SUQ8J2PCT7.org.lokinet</string>
</array>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>Lokinet</string>
<key>CFBundleIdentifier</key>
<string>org.lokinet</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Lokinet</string>
<key>CFBundleIconFile</key>
<string>icon.icns</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>@lokinet_VERSION@</string>
<key>CFBundleVersion</key>
<string>@lokinet_VERSION@.@LOKINET_APPLE_BUILD@</string>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2022 The Oxen Project, licensed under GPLv3-or-later</string>
<key>LSUIElement</key>
<true/>
<key>LSHasLocalizedDisplayName</key>
<true/>
</dict>
</plist>

@ -3,13 +3,13 @@
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>SUQ8J2PCT7.com.loki-project.lokinet</string>
<string>SUQ8J2PCT7.org.lokinet</string>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
<string>dns-proxy</string>
<string>dns-settings</string>
<string>dns-proxy</string>
<string>dns-settings</string>
</array>
<key>com.apple.developer.team-identifier</key>
@ -18,13 +18,10 @@
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.get-task-allow</key>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<key>com.apple.security.network.server</key>
<true/>
</dict>

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>SUQ8J2PCT7.org.lokinet</string>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider-systemextension</string>
<string>dns-proxy-systemextension</string>
<string>dns-settings</string>
</array>
<key>com.apple.developer.team-identifier</key>
<string>SUQ8J2PCT7</string>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>SUQ8J2PCT7.org.lokinet</string>
</array>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>

@ -1,45 +0,0 @@
#!/bin/sh
scutil_query()
{
key=$1
scutil<<EOT
open
get $key
d.show
close
EOT
}
SERVICE_GUID=`scutil_query State:/Network/Global/IPv4 \
| grep "PrimaryService" \
| awk '{print $3}'`
SERVICE_NAME=`scutil_query Setup:/Network/Service/$SERVICE_GUID \
| grep "UserDefinedName" \
| awk -F': ' '{print $2}'`
OLD_SERVERS="$(networksetup -getdnsservers "$SERVICE_NAME" \
| tr '\n' ' ' \
| sed 's/ $//')"
# <3 Apple
#
# if there were no explicit DNS servers, this will return:
# "There aren't any DNS Servers set on Ethernet."
# This might be internationalized, so we'll suffice it to see if there's a space
pattern=" |'"
if [[ $OLD_SERVERS =~ $pattern ]]
then
# and when there aren't any explicit servers set, we want to pass the literal
# string "empty"
OLD_SERVERS="empty"
fi
networksetup -setdnsservers "$SERVICE_NAME" 127.0.0.1
trap "networksetup -setdnsservers \"$SERVICE_NAME\" $OLD_SERVERS" INT TERM EXIT
/opt/lokinet/bin/lokinet /var/lib/lokinet/lokinet.ini

@ -1,53 +0,0 @@
#!/bin/sh
set -x
test `whoami` == root || exit 1
# this is for dns tomfoolery
scutil_query()
{
key=$1
scutil<<EOT
open
get $key
d.show
close
EOT
}
# get guid for service
SERVICE_GUID=`scutil_query State:/Network/Global/IPv4 \
| grep "PrimaryService" \
| awk '{print $3}'`
# get name of network service
SERVICE_NAME=`scutil_query Setup:/Network/Service/$SERVICE_GUID \
| grep "UserDefinedName" \
| awk -F': ' '{print $2}'`
# tell dns to be "empty" so that it's reset
networksetup -setdnsservers "$SERVICE_NAME" empty
# Prevent restarting on exit
touch /var/lib/lokinet/suspend-launchd-service
# shut off lokinet gracefully
pgrep lokinet$ && /opt/lokinet/bin/lokinet-vpn --kill
# kill the gui and such
killall LokinetGUI
killall lokinet
# if the launch daemon is there kill it
/bin/launchctl stop network.loki.lokinet.daemon
/bin/launchctl unload /Library/LaunchDaemons/network.loki.lokinet.daemon.plist
# kill it and make sure it's dead
killall -9 lokinet
rm -rf /Library/LaunchDaemons/network.loki.lokinet.daemon.plist
rm -rf /Applications/Lokinet/
rm -rf /Applications/LokinetGUI.app
rm -rf /var/lib/lokinet
rm -rf /usr/local/lokinet/
rm -rf /opt/lokinet
rm -f /etc/newsyslog.d/lokinet.conf

@ -7,14 +7,73 @@ outdir="${out/%.icns/.iconset}"
set -e
# Apple's PNG encoding/decoding is buggy and likes to inject yellow lines, particularly for the
# smaller images. This is apparently a known issue since macOS 11 that apple just doesn't give a
# shit about fixing (https://en.wikipedia.org/wiki/Apple_Icon_Image_format#Known_issues).
#
# So moral of the story: we have to arse around and edit the png to put a tranparent pixel in the
# bottom-left corner but that pixel *must* be different from the preceeding color, otherwise Apple's
# garbage breaks exposing the dumpster fire that lies beneath and drops the blue channel from the
# last pixel (or run of pixels, if they are the same color (ignoring transparency). So, just to be
# consistent, we make *all* 4 corners transparent yellow, because it seems unlikely for our logo to
# have full-on yellow in the corner, and the color itself is irrelevant because it is fully
# transparent.
#
# Why is there so much broken, buggy crap in the macOS core???
no_r_kelly() {
size=$1
last=$((size - 1))
for x in 0 $last; do
for y in 0 $last; do
echo -n "color $x,$y point "
done
done
}
mkdir -p "${outdir}"
for size in 16 32 64 128 256 512 1024; do
convert -background none -resize "${size}x${size}" "$svg" -strip "png32:${outdir}/icon_${size}x${size}.png"
for size in 32 64 128 256 512 1024; do
# Yay Apple thanks for this utter trash OS.
last=$((size - 1))
convert -background none -resize "${size}x${size}" "$svg" \
-fill '#ff00' -draw "$(no_r_kelly $size)" \
-strip "png32:${outdir}/icon_${size}x${size}.png"
done
# Outputs the imagemagick -draw command to color the corner-adjacent pixels as half-transparent
# white. We use this for the 16x16 (the others pick up corner transparency from the svg).
semitransparent_off_corners() {
size=$1
for x in 1 $((size - 2)); do
for y in 0 $((size - 1)); do
echo -n "color $x,$y point "
done
done
for x in 0 $((size -1)); do
for y in 1 $((size - 2)); do
echo -n "color $x,$y point "
done
done
}
# For 16x16 we crop the image to 5/8 of its regular size before resizing which effectively zooms in
# on it a bit because if we resize the full icon it ends up a fuzzy mess, while the crop and resize
# lets us retain some detail of the logo. (We don't do this for the 16x16@2x because that is really
# 32x32 where it retains enough detail).
convert -background none -resize 512x512 "$svg" -gravity Center -extent 320x320 -resize 16x16 \
-fill '#ff00' -draw "$(no_r_kelly 16)" \
-fill '#fff8' -draw "$(semitransparent_off_corners 16)" \
-strip "png32:$outdir/icon_16x16.png"
# Create all the "@2x" versions which are just the double-size versions
rm -f "${outdir}/icon_*@2x.png"
mv "${outdir}/icon_1024x1024.png" "${outdir}/icon_512x512@2x.png"
for size in 16 32 128 256; do
double=$((size * 2))
cp "${outdir}/icon_${double}x${double}.png" "${outdir}/icon_${size}x${size}@2x.png"
ln -f "${outdir}/icon_${double}x${double}.png" "${outdir}/icon_${size}x${size}@2x.png"
done
iconutil -c icns "${outdir}"

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>network.loki.lokinet.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/var/lib/lokinet/lokinet_macos_daemon_script.sh</string>
</array>
<!-- Keep Lokinet alive unless magic file exists -->
<key>KeepAlive</key>
<dict>
<key>PathState</key>
<dict>
<key>/var/lib/lokinet/suspend-launchd-service</key>
<false/>
</dict>
</dict>
<key>StandardOutPath</key>
<string>/var/log/lokinet.log</string>
</dict>
</plist>

@ -4,21 +4,47 @@ import sys
import plistlib
import subprocess
import time
import os
import os.path
def bold_red(x):
return "\x1b[31;1m" + x + "\x1b[0m"
if not @notarize_py_is_sysext@:
print(bold_red("\nUnable to notarize: this lokinet is not built as a system extension\n"), file=sys.stderr)
sys.exit(1)
if not all(("@MACOS_NOTARIZE_USER@", "@MACOS_NOTARIZE_PASS@", "@MACOS_NOTARIZE_ASC@")):
print(bold_red("\nUnable to notarize: one or more required notarization variable not set; see contrib/macos/README.txt\n") +
" Called with -DMACOS_NOTARIZE_USER=@MACOS_NOTARIZE_USER@\n"
" -DMACOS_NOTARIZE_PASS=@MACOS_NOTARIZE_PASS@\n"
" -DMACOS_NOTARIZE_ASC=@MACOS_NOTARIZE_ASC@\n",
file=sys.stderr)
sys.exit(1)
os.chdir("@PROJECT_BINARY_DIR@")
app = "@lokinet_app@"
zipfile = f"Lokinet.app.notarize.zip"
print(f"Creating {zipfile} from {app}")
if os.path.exists(zipfile):
os.remove(zipfile)
subprocess.run(['ditto', '-v', '-c', '-k', '--sequesterRsrc', '--keepParent', app, zipfile])
pkg = "lokinet-@PROJECT_VERSION@-Darwin.pkg"
userpass = ('--username', "@MACOS_NOTARIZE_USER@", '--password', "@MACOS_NOTARIZE_PASS@")
print("Submitting {} for notarization; this may take a minute...".format(pkg))
print("Submitting {} for notarization; this may take a minute...".format(zipfile))
started = time.time()
result = subprocess.run([
command = [
'xcrun', 'altool',
'--notarize-app',
'--primary-bundle-id', 'org.lokinet.lokinet.pkg.@PROJECT_VERSION@',
'--primary-bundle-id', 'org.lokinet.@PROJECT_VERSION@',
*userpass,
'--asc-provider', "@MACOS_NOTARIZE_ASC@",
'--file', pkg,
'--file', zipfile,
'--output-format', 'xml'
], stdout=subprocess.PIPE)
]
print(command)
result = subprocess.run(command, stdout=subprocess.PIPE)
data = plistlib.loads(result.stdout)
if 'success-message' not in data or 'notarization-upload' not in data or 'RequestUUID' not in data['notarization-upload']:
@ -42,24 +68,27 @@ while not done:
'--notarization-info', uuid,
*userpass,
'--output-format', 'xml'
], stdout=subprocess.PIPE)
result.check_returncode()
data = plistlib.loads(result.stdout)
if 'notarization-info' not in data or 'Status' not in data['notarization-info']:
status = 'Request failed'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode == 1 and b'Gateway Timeout' in result.stderr:
status = "Apple's servers are trash (aka Gateway Timeout)"
else:
status = data['notarization-info']['Status Message'] if 'Status Message' in data['notarization-info'] else ''
st = data['notarization-info']['Status']
if st == 'success':
success = True
done = True
elif st == 'invalid':
done = True
elif st == 'in progress' and len(status) == 0:
status = 'Notarization in progress'
if done and 'LogFileURL' in data['notarization-info']:
status += '\n\nlog file: {}'.format(data['notarization-info']['LogFileURL'])
result.check_returncode()
data = plistlib.loads(result.stdout)
if 'notarization-info' not in data or 'Status' not in data['notarization-info']:
status = 'Request failed'
else:
status = data['notarization-info']['Status Message'] if 'Status Message' in data['notarization-info'] else ''
st = data['notarization-info']['Status']
if st == 'success':
success = True
done = True
elif st == 'invalid':
done = True
elif st == 'in progress' and len(status) == 0:
status = 'Notarization in progress'
if done and 'LogFileURL' in data['notarization-info']:
status += '\n\nlog file: {}'.format(data['notarization-info']['LogFileURL'])
elapsed = time.time() - started_waiting
mins, secs = int(elapsed // 60), int(elapsed % 60)
@ -70,7 +99,15 @@ print("\n")
if not success:
sys.exit(42)
print("Stapling {}".format(pkg))
result = subprocess.run(['xcrun', 'stapler', 'staple', pkg])
if os.path.exists(zipfile):
os.remove(zipfile)
print("Stapling {}...".format(app), end='')
result = subprocess.run(['xcrun', 'stapler', 'staple', app])
result.check_returncode()
with open("macos-notarized.stamp", 'w'):
pass
print(" success.\n")

@ -1,38 +0,0 @@
#!/bin/sh
PERMS_OWNER=root
PERMS_GROUP=admin
CHOWN=$PERMS_OWNER:$PERMS_GROUP
# set up lokinet data dir
[ -e /var/lib/lokinet/ ] || mkdir /var/lib/lokinet
chown $CHOWN /var/lib/lokinet
chmod g+w /var/lib/lokinet
# mv files copied into $INSTALL_PREFIX/extra/ to their proper locations
mv /opt/lokinet/extra/lokinet_macos_daemon_script.sh /var/lib/lokinet
chown $CHOWN /var/lib/lokinet/lokinet_macos_daemon_script.sh
chmod 770 /var/lib/lokinet/lokinet_macos_daemon_script.sh
mv /opt/lokinet/extra/network.loki.lokinet.daemon.plist /Library/LaunchDaemons/
chown $CHOWN /Library/LaunchDaemons/network.loki.lokinet.daemon.plist
chmod 640 /Library/LaunchDaemons/network.loki.lokinet.daemon.plist
mv /opt/lokinet/extra/lokinet-newsyslog.conf /etc/newsyslog.d/lokinet.conf
chown $CHOWN /etc/newsyslog.d/lokinet.conf
chmod 640 /etc/newsyslog.d/lokinet.conf
# clean up by removing 'extra/' (so long as it's empty)
rmdir /opt/lokinet/extra/
# bootstrap
/opt/lokinet/bin/lokinet-bootstrap mainnet /var/lib/lokinet/bootstrap.signed
chown $CHOWN /var/lib/lokinet/bootstrap.signed
# generate configs
/opt/lokinet/bin/lokinet -g /var/lib/lokinet/lokinet.ini
chown $CHOWN /var/lib/lokinet/lokinet.ini
# register with launchd and start
launchctl load /Library/LaunchDaemons/network.loki.lokinet.daemon.plist
launchctl start network.loki.lokinet.daemon

@ -1,46 +0,0 @@
#!/bin/sh
# this is for dns tomfoolery
scutil_query()
{
key=$1
scutil<<EOT
open
get $key
d.show
close
EOT
}
# get guid for service
SERVICE_GUID=`scutil_query State:/Network/Global/IPv4 \
| grep "PrimaryService" \
| awk '{print $3}'`
# get name of network service
SERVICE_NAME=`scutil_query Setup:/Network/Service/$SERVICE_GUID \
| grep "UserDefinedName" \
| awk -F': ' '{print $2}'`
# tell dns to be "empty" so that it's reset
networksetup -setdnsservers "$SERVICE_NAME" empty
# suspend existing lokinet if it's there
[ -e /var/lib/lokinet ] && touch /var/lib/lokinet/suspend-launchd-service
# kill it
killall lokinet || true
# wait a sec
sleep 1
# make sure it's fucking dead
killall -9 lokinet || true
# check for prexisting lokinet and kill it if it's there
[ -e /Library/LaunchDaemons/network.loki.lokinet.daemon.plist ] && (
launchctl stop network.loki.lokinet.daemon ;
launchctl unload /Library/LaunchDaemons/network.loki.lokinet.daemon.plist ;
rm -rf /Library/LaunchDaemons/network.loki.lokinet.daemon.plist
)
# clear out the install dir beforehand
rm -rf /opt/lokinet

@ -0,0 +1,26 @@
import Foundation
import AppKit
// Apple deprecated their command line tools to set images on things and replaced them with a
// barely-documented swift function. Yay!
// Usage: ./seticon /path/to/my.icns /path/to/some.dmg
let args = CommandLine.arguments
if args.count != 3 {
print("Error: usage: ./seticon /path/to/my.icns /path/to/some.dmg")
exit(1)
}
var icns = args[1]
var dmg = args[2]
var img = NSImage(byReferencingFile: icns)!
if NSWorkspace.shared.setIcon(img, forFile: dmg) {
print("Set \(dmg) icon to \(icns) [\(img.size)]")
} else {
print("Setting icon failed, don't know why")
exit(2)
}

@ -1,10 +1,74 @@
#!/usr/bin/env bash
set -e
codesign --verbose=4 --force -s "@CODESIGN_APPEX@" \
--entitlements "@PROJECT_SOURCE_DIR@/contrib/macos/lokinet-extension.entitlements.plist" \
--deep --strict --timestamp --options=runtime "@SIGN_TARGET@/Contents/PlugIns/lokinet-extension.appex"
for file in "@SIGN_TARGET@/Contents/MacOS/lokinet" "@SIGN_TARGET@" ; do
codesign --verbose=4 --force -s "@CODESIGN_APP@" \
--entitlements "@PROJECT_SOURCE_DIR@/contrib/macos/lokinet.entitlements.plist" \
--deep --strict --timestamp --options=runtime "$file"
if [ "@CODESIGN@" != "ON" ]; then
echo "Cannot codesign: this build was not configured with codesigning" >&2
exit 1
fi
signit() {
target="$1"
entitlements="$2"
echo -e "\n\e[33;1mSigning ${target/*\/Lokinet.app/Lokinet.app}...\e[0m" >&2
codesign \
--verbose=4 \
--force \
-s "@CODESIGN_ID@" \
--entitlements "$entitlements" \
--strict \
--timestamp \
--options=runtime \
"$target"
}
gui_entitlements="@PROJECT_SOURCE_DIR@/gui/node_modules/app-builder-lib/templates/entitlements.mac.plist"
ext_entitlements="@PROJECT_SOURCE_DIR@/contrib/macos/lokinet-extension.@LOKINET_ENTITLEMENTS_TYPE@.entitlements.plist"
app_entitlements="@PROJECT_SOURCE_DIR@/contrib/macos/lokinet.@LOKINET_ENTITLEMENTS_TYPE@.entitlements.plist"
SIGN_TARGET="@PROJECT_BINARY_DIR@/Lokinet @PROJECT_VERSION@/Lokinet.app"
for ext in systemextension appex; do
netext="$SIGN_TARGET/@lokinet_ext_dir@/org.lokinet.network-extension.$ext"
if [ -e "$netext" ]; then
signit "$netext" "$ext_entitlements"
fi
done
if [ "@BUILD_GUI@" == "ON" ]; then
gui_app="$SIGN_TARGET"/Contents/Helpers/Lokinet-GUI.app
gui_sign_targets=()
for bundle in \
"$gui_app"/Contents/Frameworks/*.framework \
"$gui_app"/Contents/Frameworks/*.app
do
if [ -d "$bundle/Libraries" ]; then
gui_sign_targets+=("$bundle"/Libraries/*.dylib)
fi
if [ -d "$bundle/Helpers" ]; then
gui_sign_targets+=("$bundle"/Helpers/*)
fi
if [ -d "$bundle/Resources" ]; then
for f in "$bundle/Resources"/*; do
if [[ -f "$f" && -x "$f" && "$(file -b "$f")" == Mach-O* ]]; then
gui_sign_targets+=("$f")
fi
done
fi
gui_sign_targets+=("$bundle")
done
gui_sign_targets+=("$gui_app")
for target in "${gui_sign_targets[@]}"; do
signit "$target" "$gui_entitlements"
done
signit "$SIGN_TARGET"/Contents/MacOS/Lokinet "$app_entitlements"
fi
signit "$SIGN_TARGET" "$app_entitlements"
touch "@PROJECT_BINARY_DIR@"/macos-signed.stamp

@ -1,85 +0,0 @@
cmake_minimum_required(VERSION 3.10) # bionic's cmake version
# 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)")
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
foreach(lang C CXX)
if(NOT DEFINED CMAKE_${lang}_COMPILER_LAUNCHER AND NOT CMAKE_${lang}_COMPILER MATCHES ".*/ccache")
message(STATUS "Enabling ccache for ${lang}")
set(CMAKE_${lang}_COMPILER_LAUNCHER ${CCACHE_PROGRAM} CACHE STRING "")
endif()
endforeach()
endif()
set(PROJECT_NAME lokinet-uninstaller)
project(${PROJECT_NAME}
VERSION 0.0.1
DESCRIPTION "lokinet uninstaller for macos"
LANGUAGES CXX)
add_executable(${PROJECT_NAME}
main.cpp)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE
"-framework Security"
Qt5::Core Qt5::Widgets)
set_target_properties(${PROJECT_NAME}
PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
CXX_STANDARD_REQUIRED ON
)
set(MACOS_SIGN ""
CACHE STRING "enable codesigning -- use a 'Apple Distribution' key (or key description) from `security find-identity -v`")
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lokinet-uninstall.icns
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/mk-icns.sh ${CMAKE_CURRENT_SOURCE_DIR}/icon.svg ${CMAKE_CURRENT_BINARY_DIR}/lokinet-uninstall.icns
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/icon.svg ${CMAKE_CURRENT_SOURCE_DIR}/mk-icns.sh)
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/lokinet-uninstall.icns)
set_target_properties(${PROJECT_NAME}
PROPERTIES
MACOSX_BUNDLE TRUE
OUTPUT_NAME UninstallLokinet
RESOURCE "${CMAKE_CURRENT_BINARY_DIR}/lokinet-uninstall.icns")
set(MACOSX_BUNDLE_BUNDLE_NAME UninstallLokinet)
set(MACOSX_BUNDLE_GUI_IDENTIFIER org.lokinet.lokinet-uninstaller)
set(MACOSX_BUNDLE_INFO_STRING "Lokinet uninstaller")
set(MACOSX_BUNDLE_ICON_FILE lokinet-uninstall.icns)
set(MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION})
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "© 2020, The Loki Project")
get_target_property(uic_location Qt5::uic IMPORTED_LOCATION)
get_filename_component(qt_dir ${uic_location} DIRECTORY)
if(MACOS_SIGN)
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND echo "Running qt magic macos deploy script"
COMMAND "${qt_dir}/macdeployqt" UninstallLokinet.app -always-overwrite
COMMAND echo "Signing app bundle and everything inside it"
COMMAND codesign -s "${MACOS_SIGN}" --deep --strict --options runtime --force -vvv UninstallLokinet.app
)
else()
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND echo "Running qt magic macos deploy script"
COMMAND "${qt_dir}/macdeployqt" UninstallLokinet.app -always-overwrite
)
endif()
install(TARGETS lokinet-uninstaller
RUNTIME DESTINATION bin
BUNDLE DESTINATION .
RESOURCE DESTINATION .)

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg data-name="Layer 1" version="1.1" viewBox="0 0 1e3 1e3" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title>lokinet icon</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs>
<style type="text/css">.cls-1{fill:#fff;}.cls-2{fill:#6cbe45;}.cls-3{fill:none;stroke:#fff;stroke-linecap:round;stroke-miterlimit:10;stroke-width:9px;}.cls-4{fill:#1c1c1c;}</style>
</defs>
<title>lokinet icon</title>
<circle class="cls-1" cx="500" cy="500" r="500"/>
<path class="cls-2" transform="translate(.02 .11)" d="M502.6,560.44l8,7.34,14.5,13.09c.74.67,1.42,1.38,2.09,2.09L541,595.54a20.87,20.87,0,0,1,0,31l-16.8,15.2a38.3,38.3,0,0,0,4-3.08l94.71-85.73-55.92-50.64Z"/>
<path class="cls-2" transform="translate(.02 .11)" d="m754.35 415.61v-0.52a69.39 69.39 0 0 0-23.13-50.47l-187.92-167.57a20.88 20.88 0 0 1-3.77 26.39l-14.07 12.73c-0.09 0.08-0.16 0.17-0.25 0.25l-25.1 22.71 168.94 150.65-46.22 41.83 116.27 105.29a46.54 46.54 0 0 1 15.28 34.54c0 1.28-0.1 2.55-0.21 3.82a38.26 38.26 0 0 0 0.23-4v-174.88c0-0.26-0.04-0.52-0.05-0.77z"/>
<path class="cls-2" transform="translate(.02 .11)" d="m500 441.68-38.63-35a20.88 20.88 0 0 1 0-31l10.49-9.49 0.35-0.43a37.93 37.93 0 0 1 6.07-5.38 39 39 0 0 0-3.46 2.75l-95.23 86.2 56 50.57z"/>
<path class="cls-2" transform="translate(.02 .11)" d="m460.61 776.35 11.83-10.7a32.29 32.29 0 0 1 2.34-2.34l25-22.59-166.32-148.34 46.15-41.77-118.72-107.23a46.58 46.58 0 0 1-15.31-34.47c0-1.48 0.09-3 0.23-4.43a36.09 36.09 0 0 0-0.25 4.18v174.85a69.42 69.42 0 0 0 23.19 51.75l188.46 168.07a20.86 20.86 0 0 1 3.4-26.98z"/>
<path class="cls-3" transform="translate(.02 .11)" d="m525 422.75"/>
<path class="cls-4" transform="translate(.02 .11)" d="M754.38,591.44A46.54,46.54,0,0,0,739.1,556.9L525.19,363.21c-.24-.22-.51-.41-.76-.62l-10.26-9.29a20.86,20.86,0,0,0-28,0l-7.92,7.16a37.93,37.93,0,0,0-6.07,5.38l-.35.43-10.49,9.49a20.88,20.88,0,0,0,0,31l38.83,35.15,0,0,165.1,149.5-190.51,172a32.29,32.29,0,0,0-2.34,2.34l-11.83,10.7a20.87,20.87,0,0,0,0,30.95l24.82,22.48a20.87,20.87,0,0,0,28,0l41.08-37.17-.08-.08L739,625.91A46.58,46.58,0,0,0,754.38,591.44Z"/>
<path class="cls-4" transform="translate(.02 .11)" d="M541,595.54,527.21,583c-.67-.71-1.35-1.42-2.09-2.09l-14.5-13.09-8.68-7.95-.06,0-167.22-151L525.21,236.42c.09-.08.16-.17.25-.25l14.07-12.73a20.88,20.88,0,0,0,0-31L514.71,170a20.87,20.87,0,0,0-28,0l-41.08,37.18h0L260.85,374.39a46.56,46.56,0,0,0,0,69L445.27,609.91l-.06.05,42.89,39a20.87,20.87,0,0,0,28,0l24.83-22.47A20.87,20.87,0,0,0,541,595.54Z"/>
<path d="m173.66 173.36 646.24 642.31" fill="#f00" stroke="#f00" stroke-linecap="round" stroke-width="50"/>
<path d="m824.02 175.25-648.03 648.03" fill="none" stroke="#f00" stroke-linecap="round" stroke-width="50"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

@ -1,45 +0,0 @@
#include <QApplication>
#include <QMessageBox>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
int uninstall();
int main(int argc, char * argv[])
{
QApplication app{argc, argv};
if(QMessageBox::question(nullptr, "Lokinet Uninstaller", "Do You want to uninstall Lokinet?",
QMessageBox::Yes|QMessageBox::No)
== QMessageBox::Yes)
{
QMessageBox msgBox;
const auto retcode = uninstall();
if(retcode == 0)
{
msgBox.setText("Lokinet has been successfully uninstalled, you may now remove the uninstaller if you wish.");
}
else
{
msgBox.setText("Failed to uninstall lokinet");
}
msgBox.exec();
}
return 0;
}
int uninstall()
{
AuthorizationRef authorizationRef;
OSStatus status;
status = AuthorizationCreate(nullptr, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
if(status != 0)
return status;
char* tool = "/bin/sh";
char* args[] = {"/opt/lokinet/bin/lokinet_uninstall.sh", nullptr};
FILE* pipe = stdout;
return AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe);
}

@ -0,0 +1,31 @@
#!/bin/bash
# Invoked from cmake as make-ico.sh /path/to/icon.svg /path/to/output.ico
svg="$1"
out="$2"
outdir="$out.d"
set -e
sizes=(16 24 32 40 48 64 96 192 256)
outs=""
mkdir -p "${outdir}"
for size in "${sizes[@]}"; do
outf="${outdir}/${size}x${size}.png"
if [ $size -lt 32 ]; then
# For 16x16 and 24x24 we crop the image to 2/3 of its regular size make it all white
# (instead of transparent) to zoom in on it a bit because if we resize the full icon to the
# target size it ends up a fuzzy mess, while the crop and resize lets us retain some detail
# of the logo.
rsvg-convert -b white \
--page-height $size --page-width $size \
-w $(($size*3/2)) -h $(($size*3/2)) --left " -$(($size/4))" --top " -$(($size/4))" \
"$svg" >"$outf"
else
rsvg-convert -b transparent -w $size -h $size "$svg" >"$outf"
fi
outs="-r $outf $outs"
done
icotool -c -b 32 -o "$out" $outs

@ -1,79 +0,0 @@
#!/usr/bin/env python3
#
# requires python3-requests
#
import requests
import json
import os
import sys
from collections import defaultdict as Dict
from requests.exceptions import RequestException
def jsonrpc(method, **args):
return requests.post('http://127.0.0.1:1190/', data=json.dumps(
{'method': method, 'params': args, 'id': 'munin'}), headers={'content-type': 'application/json'}).json()
def exit_sessions_main():
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print("graph_title lokinet exit sessions")
print("graph_vlabel sessions")
print("graph_category network")
print("graph_info This graph shows the number of exit sessions on a lokinet exit")
print("_exit_sessions.info Number of exit sessions")
print("_exit_sessions.label sessions")
else:
count = 0
try:
j = jsonrpc("llarp.admin.exit.list")
count = len(j['result'])
except RequestException:
pass
print("_exit_sessions.value {}".format(count))
def peers_main():
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print("graph_title lokinet peers")
print("graph_vlabel peers")
print("graph_category network")
print("graph_info This graph shows the number of node to node sessions of this lokinet router")
print("_peers_outbound.info Number of outbound lokinet peers")
print("_peers_inbound.info Number of inbound lokinet peers")
print("_peers_outbound.label outbound peers")
print("_peers_inbound.label inbound peers")
print("_peers_clients.info Number of lokinet client peers")
print("_peers_clients.label lokinet client peers")
else:
inbound = Dict(int)
outbound = Dict(int)
clients = Dict(int)
try:
j = jsonrpc("llarp.admin.link.neighboors")
for peer in j['result']:
if peer["svcnode"]:
if peer["outbound"]:
outbound[peer['ident']] += 1
else:
inbound[peer['ident']] += 1
else:
clients[peer['ident']] += 1
except RequestException:
pass
print("_peers_outbound.value {}".format(len(outbound)))
print("_peers_inbound.value {}".format(len(inbound)))
print("_peers_clients.value {}".format(len(clients)))
if __name__ == '__main__':
exe = os.path.basename(sys.argv[0]).lower()
if exe == 'lokinet_peers':
peers_main()
elif exe == 'lokinet_exit':
exit_sessions_main()
else:
print(
'please symlink this as `lokinet_peers` or `lokinet_exit` in munin plugins dir')

@ -1,12 +0,0 @@
diff --git a/tests/testutil.hpp b/tests/testutil.hpp
index c6f5e4de..6a1c8bb8 100644
--- a/tests/testutil.hpp
+++ b/tests/testutil.hpp
@@ -102,7 +102,6 @@ const uint8_t zmtp_ready_sub[27] = {
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdexcept>
-#define close closesocket
typedef int socket_size_t;
inline const char *as_setsockopt_opt_t (const void *opt)
{

@ -0,0 +1,14 @@
diff --git a/tests/testutil.hpp b/tests/testutil.hpp
index c6f5e4de78..09b9fa77e5 100644
--- a/tests/testutil.hpp
+++ b/tests/testutil.hpp
@@ -41,6 +41,9 @@
// For AF_INET and IPPROTO_TCP
#if defined _WIN32
#include "../src/windows.hpp"
+#if defined(__MINGW32__)
+#include <unistd.h>
+#endif
#else
#include <arpa/inet.h>
#include <unistd.h>

@ -0,0 +1,33 @@
commit 56d816014d5e8a7eb055169c7e13a303dad5e50f
Author: Jason Rhinelander <jason@imaginary.ca>
Date: Mon Oct 31 22:07:03 2022 -0300
Set tube->ev_listen to NULL to prevent double unregister
On windows when using threaded mode (i.e. `ub_ctx_async(ctx, 1)`)
tube_remove_bg_listen gets called twice: once when the thread does its
own cleanup, then again in `tube_delete()`. Because `ev_listen` doesn't
get cleared, however, we end we calling ub_winsock_unregister_wsaevent
with a freed pointer.
This doesn't always manifest because, apparently, for various compilers
and settings that memory *might* be overwritten in which case the
additional check for ev->magic will prevent anything actually happening,
but in my case under mingw32 that doesn't happen and we end up
eventually crashing.
This fixes the crash by properly NULLing the pointer so that the second
ub_winsock_unregister_wsaevent(...) becomes a no-op.
diff --git a/util/tube.c b/util/tube.c
index 43455fee..a92dfa77 100644
--- a/util/tube.c
+++ b/util/tube.c
@@ -570,6 +570,7 @@ void tube_remove_bg_listen(struct tube* tube)
{
verbose(VERB_ALGO, "tube remove_bg_listen");
ub_winsock_unregister_wsaevent(tube->ev_listen);
+ tube->ev_listen = NULL;
}
void tube_remove_bg_write(struct tube* tube)

@ -1,4 +0,0 @@
#!/usr/bin/env python3
from pylokinet.instance import main
main()

@ -1,111 +0,0 @@
#
# super freaking dead simple wicked awesome bencode library
#
from io import BytesIO
class BCodec:
encoding = 'utf-8'
def __init__(self, fd):
self._fd = fd
def _write_bytestring(self, bs):
self._fd.write('{}:'.format(len(bs)).encode('ascii'))
self._fd.write(bs)
def _write_list(self, l):
self._fd.write(b'l')
for item in l:
self.encode(item)
self._fd.write(b'e')
def _write_dict(self, d):
self._fd.write(b'd')
keys = list(d.keys())
keys.sort()
for k in keys:
if isinstance(k, str):
self._write_bytestring(k.encode(self.encoding))
elif isinstance(k, bytes):
self._write_bytestring(k)
else:
self._write_bytestring('{}'.format(k).encode(self.encoding))
self.encode(d[k])
self._fd.write(b'e')
def _write_int(self, i):
self._fd.write('i{}e'.format(i).encode(self.encoding))
def encode(self, obj):
if isinstance(obj, dict):
self._write_dict(obj)
elif isinstance(obj, list):
self._write_list(obj)
elif isinstance(obj, int):
self._write_int(obj)
elif isinstance(obj, str):
self._write_bytestring(obj.encode(self.encoding))
elif isinstance(obj, bytes):
self._write_bytestring(obj)
elif hasattr(obj, bencode):
obj.bencode(self._fd)
else:
raise ValueError("invalid object type")
def _readuntil(self, delim):
b = bytes()
while True:
ch = self._fd.read(1)
if ch == delim:
return b
b += ch
def _decode_list(self):
l = list()
while True:
b = self._fd.read(1)
if b == b'e':
return l
l.append(self._decode(b))
def _decode_dict(self):
d = dict()
while True:
ch = self._fd.read(1)
if ch == b'e':
return d
k = self._decode_bytestring(ch)
d[k] = self.decode()
def _decode_int(self):
return int(self._readuntil(b'e'), 10)
def _decode_bytestring(self, ch):
ch += self._readuntil(b':')
l = int(ch, base=10)
return self._fd.read(l)
def _decode(self, ch):
if ch == b'd':
return self._decode_dict()
elif ch == b'l':
return self._decode_list()
elif ch == b'i':
return self._decode_int()
elif ch in [b'0',b'1',b'2',b'3',b'4',b'5',b'6',b'7',b'8',b'9']:
return self._decode_bytestring(ch)
else:
raise ValueError(ch)
def decode(self):
return self._decode(self._fd.read(1))
def bencode(obj):
buf = BytesIO()
b = BCodec(buf)
b.encode(obj)
return buf.getvalue()
def bdecode(bytestring):
buf = BytesIO(bytestring)
return BCodec(buf).decode()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save