mirror of https://github.com/oxen-io/lokinet
Merge remote-tracking branch 'origin/stable' into opensuse/tumbleweed
commit
58c278a866
@ -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
|
||||
|
@ -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) )
|
||||
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()
|
||||
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}"
|
||||
"-D" "GIT=${GIT_EXECUTABLE}"
|
||||
${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()
|
||||
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")
|
||||
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()
|
@ -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()
|
@ -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
|
@ -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,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)
|
||||
|
@ -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,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 <<< `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,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"/>
|
||||
<!--
|
||||
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>
|
||||
|
||||
<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"/>
|
||||
<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.
|
||||
|
||||
<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"/>
|
||||
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"
|
@ -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>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
@ -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>
|
@ -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…
Reference in New Issue