removed legacy socks5 listener (#5259)

This commit is contained in:
Jędrzej Stuczyński
2024-12-13 10:03:43 +00:00
committed by GitHub
parent b813044360
commit 684d7ac1a2
15 changed files with 0 additions and 1324 deletions
@@ -56,14 +56,6 @@ jobs:
rustup target add aarch64-linux-android \
x86_64-linux-android
- name: Build lib nym-socks5-listener
working-directory: sdk/lib/socks5-listener/
env:
RELEASE: true
RUSTFLAGS: "-C link-args=-Wl,--hash-style=gnu"
# build for arm64 and x86_64
run: ./build-android.sh aarch64 x86_64
- name: Build APKs (unsigned)
working-directory: nym-connect/native/android
env:
Generated
-245
View File
@@ -140,23 +140,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_log-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937"
[[package]]
name = "android_logger"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826"
dependencies = [
"android_log-sys",
"env_filter",
"log",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -981,12 +964,6 @@ dependencies = [
"serde",
]
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -1182,16 +1159,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "combine"
version = "4.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
dependencies = [
"bytes",
"memchr",
]
[[package]]
name = "comfy-table"
version = "7.1.1"
@@ -2482,26 +2449,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "ext-trait"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5"
dependencies = [
"ext-trait-proc_macros",
]
[[package]]
name = "ext-trait-proc_macros"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "extension-storage"
version = "1.3.0-rc.0"
@@ -2518,21 +2465,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "extension-traits"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537"
dependencies = [
"ext-trait",
]
[[package]]
name = "extern-c"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320bea982e85d42441eb25c49b41218e7eaa2657e8f90bc4eca7437376751e23"
[[package]]
name = "eyre"
version = "0.6.12"
@@ -3730,28 +3662,6 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jni"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
dependencies = [
"cesu8",
"cfg-if",
"combine",
"jni-sys",
"log",
"thiserror",
"walkdir",
"windows-sys 0.45.0",
]
[[package]]
name = "jni-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
version = "0.3.72"
@@ -3941,22 +3851,6 @@ dependencies = [
"tracing-subscriber",
]
[[package]]
name = "macro_rules_attribute"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf0c9b980bf4f3a37fd7b1c066941dd1b1d0152ce6ee6e8fe8c49b9f6810d862"
dependencies = [
"macro_rules_attribute-proc_macro",
"paste",
]
[[package]]
name = "macro_rules_attribute-proc_macro"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58093314a45e00c77d5c508f76e77c3396afbbc0d01506e7fae47b018bac2b1d"
[[package]]
name = "macroific"
version = "1.3.1"
@@ -6394,28 +6288,6 @@ dependencies = [
"url",
]
[[package]]
name = "nym-socks5-listener"
version = "0.1.0"
dependencies = [
"android_logger",
"anyhow",
"futures",
"jni",
"lazy_static",
"log",
"nym-bin-common",
"nym-client-core",
"nym-config",
"nym-credential-storage",
"nym-crypto",
"nym-socks5-client-core",
"rand",
"safer-ffi",
"serde",
"tokio",
]
[[package]]
name = "nym-socks5-proxy-helpers"
version = "0.1.0"
@@ -7548,16 +7420,6 @@ dependencies = [
"log",
]
[[package]]
name = "prettyplease"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
dependencies = [
"proc-macro2",
"syn 1.0.109",
]
[[package]]
name = "proc-macro-crate"
version = "3.1.0"
@@ -8455,38 +8317,6 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "safer-ffi"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435fdd58b61a6f1d8545274c1dfa458e905ff68c166e65e294a0130ef5e675bd"
dependencies = [
"extern-c",
"inventory",
"libc",
"macro_rules_attribute",
"paste",
"safer_ffi-proc_macros",
"scopeguard",
"stabby",
"uninit",
"unwind_safe",
"with_builtin_macros",
]
[[package]]
name = "safer_ffi-proc_macros"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f25be5ba5f319542edb31925517e0380245ae37df50a9752cdbc05ef948156"
dependencies = [
"macro_rules_attribute",
"prettyplease",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "same-file"
version = "1.0.6"
@@ -8919,12 +8749,6 @@ dependencies = [
"digest 0.10.7",
]
[[package]]
name = "sha2-const-stable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9"
[[package]]
name = "sharded-slab"
version = "0.1.7"
@@ -9325,40 +9149,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "stabby"
version = "36.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "311d6bcf0070c462ff626122ec2246f42bd2acd44b28908eedbfd07d500c7d99"
dependencies = [
"rustversion",
"stabby-abi",
]
[[package]]
name = "stabby-abi"
version = "36.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6daae1a0707399f56d27fce7f212e50e31d215112a447e1bbcd837ae1bf5f49"
dependencies = [
"rustversion",
"sha2-const-stable",
"stabby-macros",
]
[[package]]
name = "stabby-macros"
version = "36.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43cf89a0cc9131279235baf8599b0e073fbcb096419204de0cc5d1a48ae73f74"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"rand",
"syn 1.0.109",
]
[[package]]
name = "stable-pattern"
version = "0.1.0"
@@ -10677,15 +10467,6 @@ dependencies = [
"weedle2",
]
[[package]]
name = "uninit"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e130f2ed46ca5d8ec13c7ff95836827f92f5f5f37fd2b2bf16f33c408d98bb6"
dependencies = [
"extension-traits",
]
[[package]]
name = "universal-hash"
version = "0.5.1"
@@ -10708,12 +10489,6 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "unwind_safe"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3"
[[package]]
name = "url"
version = "2.5.2"
@@ -11441,26 +11216,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "with_builtin_macros"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a59d55032495429b87f9d69954c6c8602e4d3f3e0a747a12dea6b0b23de685da"
dependencies = [
"with_builtin_macros-proc_macros",
]
[[package]]
name = "with_builtin_macros-proc_macros"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15bd7679c15e22924f53aee34d4e448c45b674feb6129689af88593e129f8f42"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "wyz"
version = "0.5.1"
-5
View File
@@ -107,7 +107,6 @@ members = [
"sdk/ffi/cpp",
"sdk/ffi/go",
"sdk/ffi/shared",
"sdk/lib/socks5-listener",
"sdk/rust/nym-sdk",
"service-providers/authenticator",
"service-providers/common",
@@ -417,10 +416,6 @@ web-sys = "0.3.72"
[profile.dev.package.sqlx-macros]
opt-level = 3
[profile.release.package.nym-socks5-listener]
strip = true
codegen-units = 1
[profile.release.package.nym-client-wasm]
# lto = true
opt-level = 'z'
-39
View File
@@ -1,39 +0,0 @@
[package]
name = "nym-socks5-listener"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "generate-headers"
required-features = ["headers"]
[lib]
crate-type = ["cdylib", "staticlib", "rlib"]
[dependencies]
anyhow = { workspace = true }
futures = { workspace = true }
lazy_static = { workspace = true }
nym-bin-common = { path = "../../../common/bin-common"}
nym-client-core = { path = "../../../common/client-core", default-features = false }
nym-config-common = { path = "../../../common/config", package = "nym-config" }
nym-credential-storage = { path = "../../../common/credential-storage" }
nym-crypto = { path = "../../../common/crypto" }
nym-socks5-client-core = { path = "../../../common/socks5-client-core", default-features = false }
serde = { workspace = true }
tokio = { workspace = true, features = ["sync", "time"] }
log = { workspace = true }
rand = { workspace = true }
safer-ffi = { workspace = true }
[target.'cfg(target_os="android")'.dependencies]
jni = { version = "0.21", default-features = false }
android_logger = "0.14.1"
[features]
headers = ["safer-ffi/headers"]
-47
View File
@@ -1,47 +0,0 @@
UNAME_S := $(shell uname -s)
# Default arch
ANDROID_TOOLCHAIN_ARCH=linux-x86_64
ifeq ($(UNAME_S),Linux)
ANDROID_TOOLCHAIN_ARCH=linux-x86_64
endif
ifeq ($(UNAME_S),Darwin)
ANDROID_TOOLCHAIN_ARCH=darwin-x86_64
endif
ANDROID_TOOLCHAIN=$(NDK_HOME)/toolchains/llvm/prebuilt/$(ANDROID_TOOLCHAIN_ARCH)
ANDROID_API=33
ANDROID_TARGET_CC=$(ANDROID_TOOLCHAIN)/bin/x86_64-linux-android$(ANDROID_API)-clang
ANDROID_TARGET_AR=$(ANDROID_TOOLCHAIN)/bin/llvm-ar
ANDROID_TARGET_RANLIB=$(ANDROID_TOOLCHAIN)/bin/llvm-ranlib
ANDROID_CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=$(ANDROID_TOOLCHAIN)/bin/x86_64-linux-android$(ANDROID_API)-clang
# Common environment
ANDROID_ENV = \
TARGET_CC=$(ANDROID_TARGET_CC) \
TARGET_AR=$(ANDROID_TARGET_AR) \
TARGET_RANLIB=$(ANDROID_TARGET_RANLIB) \
CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=$(ANDROID_CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER)
ANDROID_TARGET=x86_64-linux-android
none:
@echo "No default target. Please specify a target."
gen-headers:
cargo run --features headers --bin generate-headers
#gen-header:
# cbindgen --lang c --crate socks5-c --output socks5_c.h
android:
$(ANDROID_ENV) cargo build --lib --target $(ANDROID_TARGET)
android-release:
$(ANDROID_ENV) cargo build --lib --target $(ANDROID_TARGET) --release
ios:
cargo lipo
ios-release:
cargo lipo --release
@@ -1,10 +0,0 @@
#!/bin/sh
export API=33
export TOOLCHAIN="$NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64"
export TARGET_CC="$TOOLCHAIN/bin/x86_64-linux-android$API-clang"
export TARGET_AR="$TOOLCHAIN/bin/llvm-ar"
export TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib"
export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/x86_64-linux-android$API-clang"
cargo build --lib --target x86_64-linux-android --release
-78
View File
@@ -1,78 +0,0 @@
#!/bin/bash
#
# Usage
#
# build-android.sh [ARCH ...]
#
# This script builds the lib for android and moves the shared
# objects (*.so) into the right app's directories
#
# ARCH:
# - aarch64 (arm 64)
# - x86_64 (classic PC 64)
# - i686 (x86)
# - armv7
#
# ⚠ to build for release set the env var `RELEASE=true`
set -E
set -o pipefail
trap 'catch $? ${FUNCNAME[0]:-main} $LINENO' ERR
# ANSI style codes
RED="\e[38;5;1m" # red
GRN="\e[38;5;2m" # green
YLW="\e[38;5;3m" # yellow
BLD="\e[1m" # bold
RS="\e[0m" # style reset
# bold variants
B_RED="$BLD$RED"
B_GRN="$BLD$GRN"
B_YLW="$BLD$YLW"
catch() {
echo -e " $B_RED$RS unexpected error, $BLD$2$RS [$BLD$1$RS] L#$BLD$3$RS"
exit 1
}
export API=33
export TOOLCHAIN="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64"
export TARGET_AR="$TOOLCHAIN/bin/llvm-ar"
export TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib"
export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/x86_64-linux-android$API-clang"
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/aarch64-linux-android$API-clang"
# arch mapping between Rust targets (keys) and Android ABIs (values)
# https://developer.android.com/ndk/guides/abis.html
declare -A arch_map=([x86_64]="x86_64" [aarch64]="arm64-v8a" [armv7]="armeabi-v7a" [i686]="x86")
output_dir=../../../target
jni_dir=../../../nym-connect/native/android/app/src/main/jniLibs
lib=libnym_socks5_listener.so
build () {
abi="${arch_map[$1]}"
echo -e " $B_YLW$RS building for arch $BLD$1$RS"
export TARGET_CC="$TOOLCHAIN/bin/$1-linux-android$API-clang"
if [ -a "$jni_dir/$abi/$lib" ]; then
# remove any previously built library
rm "$jni_dir/$abi/$lib"
fi
if [ "$RELEASE" = true ]; then
cargo build --lib --target "$1-linux-android" --release
mv "$output_dir/$1-linux-android/release/$lib" "$jni_dir/$abi/"
else
cargo build --lib --target "$1-linux-android"
mv "$output_dir/$1-linux-android/debug/$lib" "$jni_dir/$abi/"
fi
echo -e " $B_GRN$RS lib built successfully for $BLD$1$RS, moved under app's dir$BLD jniLibs/$abi/$RS"
}
for arch in "$@"; do
if [ "${arch_map[$arch]}" ]; then
build "$arch"
else
echo -e " $B_RED$RS unknown arch $BLD$arch$RS"
exit 1
fi
done
-108
View File
@@ -1,108 +0,0 @@
/*! \file */
/*******************************************
* *
* File auto-generated by `::safer_ffi`. *
* *
* Do not manually edit this file. *
* *
*******************************************/
#ifndef __RUST_NYM_SOCKS5_LISTENER__
#define __RUST_NYM_SOCKS5_LISTENER__
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
/** <No documentation available> */
/** \remark Has the same ABI as `uint8_t` **/
#ifdef DOXYGEN
typedef
#endif
enum ClientState {
/** <No documentation available> */
CLIENT_STATE_UNINITIALISED,
/** <No documentation available> */
CLIENT_STATE_CONNECTED,
/** <No documentation available> */
CLIENT_STATE_DISCONNECTED,
}
#ifndef DOXYGEN
; typedef uint8_t
#endif
ClientState_t;
/** \brief
* `&'lt mut (dyn 'lt + Send + FnMut(A1) -> Ret)`
*/
typedef struct RefDynFnMut1_void_char_ptr {
/** <No documentation available> */
void * env_ptr;
/** <No documentation available> */
void (*call)(void *, char *);
} RefDynFnMut1_void_char_ptr_t;
/** \brief
* `&'lt mut (dyn 'lt + Send + FnMut() -> Ret)`
*/
typedef struct RefDynFnMut0_void {
/** <No documentation available> */
void * env_ptr;
/** <No documentation available> */
void (*call)(void *);
} RefDynFnMut0_void_t;
/** <No documentation available> */
void
blocking_run_client (
char const * storage_directory,
char const * service_provider,
RefDynFnMut1_void_char_ptr_t on_start_callback,
RefDynFnMut0_void_t on_shutdown_callback);
/** <No documentation available> */
char *
existing_service_provider (
char const * storage_directory);
/** <No documentation available> */
ClientState_t
get_client_state (void);
/** <No documentation available> */
void
initialise_logger (void);
/** <No documentation available> */
void
reset_client_data (
char const * root_directory);
/** <No documentation available> */
void
rust_free_string (
char * string);
/** <No documentation available> */
void
start_client (
char const * storage_directory,
char const * service_provider,
RefDynFnMut1_void_char_ptr_t on_start_callback,
RefDynFnMut0_void_t on_shutdown_callback);
/** <No documentation available> */
void
stop_client (void);
#ifdef __cplusplus
} /* extern \"C\" */
#endif
#endif /* __RUST_NYM_SOCKS5_LISTENER__ */
-97
View File
@@ -1,97 +0,0 @@
use crate::ClientState;
use ::safer_ffi::prelude::*;
use jni::{
objects::{JClass, JObject, JString},
sys::jint,
JNIEnv,
};
use std::sync::{Arc, Mutex};
fn init_jni_logger() {
use android_logger::{Config, FilterBuilder};
use log::LevelFilter;
android_logger::init_once(
Config::default()
.with_max_level(LevelFilter::Trace)
.with_tag("libnyms5")
.with_filter(
FilterBuilder::new()
.parse("debug,tungstenite=warn,mio=warn,tokio_tungstenite=warn")
.build(),
),
);
log::debug!("Logger initialized");
}
/// Blocking call that starts the socks5 listener
#[no_mangle]
pub unsafe extern "C" fn Java_net_nymtech_nyms5_NymProxy_startClient(
mut env: JNIEnv,
_class: JClass,
service_provider: JString,
start_cb: JObject,
stop_cb: JObject,
) {
init_jni_logger();
let sp_input: String = env
.get_string(&service_provider)
.expect("Couldn't get java string!")
.into();
log::debug!("using sp {}", sp_input);
let service_provider = char_p::new(sp_input.as_str());
let arced = Arc::new(Mutex::new(env));
let env_start = arced.clone();
let env_stop = arced.clone();
crate::blocking_run_client(
None,
Some(service_provider.as_ref()),
move |_| {
log::debug!("client connected");
env_start
.lock()
.unwrap()
.call_method(&start_cb, "onStart", "()V", &[])
.expect("failed to call Java callbacks");
},
move || {
log::debug!("client disconnected");
env_stop
.lock()
.unwrap()
.call_method(&stop_cb, "onStop", "()V", &[])
.expect("failed to call Java callbacks");
},
);
}
#[no_mangle]
pub unsafe extern "C" fn Java_net_nymtech_nyms5_NymProxy_stopClient(_env: JNIEnv, _class: JClass) {
crate::stop_client();
}
#[no_mangle]
pub unsafe extern "C" fn Java_net_nymtech_nyms5_NymProxy_getClientState(
_env: JNIEnv,
_class: JClass,
) -> jint {
let state = crate::get_client_state();
log::debug!("client state {:?}", state);
match state {
ClientState::Uninitialised => 0,
ClientState::Connected => 1,
ClientState::Disconnected => 2,
}
}
#[no_mangle]
pub unsafe extern "C" fn Java_net_nymtech_nyms5_NymProxy_pingClient(_env: JNIEnv, _class: JClass) {
log::debug!("pong");
crate::ping_client();
}
@@ -1,6 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
fn main() -> ::std::io::Result<()> {
::nym_socks5_listener::generate_headers()
}
-101
View File
@@ -1,101 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::persistence::MobileSocksClientPaths;
use crate::config::template::CONFIG_TEMPLATE;
use nym_bin_common::logging::LoggingSettings;
use nym_config_common::{
read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
};
use nym_socks5_client_core::config::Config as CoreConfig;
use serde::{Deserialize, Serialize};
use std::io;
use std::path::{Path, PathBuf};
mod persistence;
mod template;
const DEFAULT_SOCKS5_CLIENTS_DIR: &str = "socks5-clients";
/// Derive default path to clients's config directory.
/// It should get resolved to `$HOME/.nym/socks5-clients/<id>/config`
pub fn config_directory_from_root<P: AsRef<Path>, R: AsRef<Path>>(root: P, id: R) -> PathBuf {
root.as_ref()
.join(NYM_DIR)
.join(DEFAULT_SOCKS5_CLIENTS_DIR)
.join(id)
.join(DEFAULT_CONFIG_DIR)
}
/// Derive default path to client's config file.
/// It should get resolved to `$HOME/.nym/socks5-clients/<id>/config/config.toml`
pub fn config_filepath_from_root<P: AsRef<Path>, R: AsRef<Path>>(root: P, id: R) -> PathBuf {
config_directory_from_root(root, id).join(DEFAULT_CONFIG_FILENAME)
}
/// Derive default path to client's data directory where files, such as keys, are stored.
/// It should get resolved to `$HOME/.nym/socks5-clients/<id>/data`
pub fn data_directory_from_root<P: AsRef<Path>, R: AsRef<Path>>(root: P, id: R) -> PathBuf {
root.as_ref()
.join(NYM_DIR)
.join(DEFAULT_SOCKS5_CLIENTS_DIR)
.join(id)
.join(DEFAULT_DATA_DIR)
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
pub core: CoreConfig,
pub storage_paths: Option<MobileSocksClientPaths>,
pub logging: LoggingSettings,
}
impl NymConfigTemplate for Config {
fn template(&self) -> &'static str {
CONFIG_TEMPLATE
}
}
impl Config {
pub fn new<P, S>(storage_root: Option<P>, id: S, provider_mix_address: S) -> Self
where
P: AsRef<Path>,
S: AsRef<str>,
{
Config {
core: CoreConfig::new(
id.as_ref(),
env!("CARGO_PKG_VERSION"),
provider_mix_address.as_ref(),
),
storage_paths: storage_root.map(|storage_root| {
MobileSocksClientPaths::new_default(data_directory_from_root(
storage_root,
id.as_ref(),
))
}),
logging: Default::default(),
}
}
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
read_config_from_toml_file(path)
}
pub fn read_from_default_path<P: AsRef<Path>, R: AsRef<Path>>(
storage_root: P,
id: R,
) -> io::Result<Self> {
Self::read_from_toml_file(config_filepath_from_root(storage_root, id))
}
pub fn save_to_default_location<P: AsRef<Path>>(&self, storage_root: P) -> io::Result<()> {
let config_save_location: PathBuf =
config_filepath_from_root(storage_root, &self.core.base.client.id);
save_formatted_config_to_file(self, config_save_location)
}
}
@@ -1,26 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::data_directory_from_root;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use serde::{Deserialize, Serialize};
use std::path::Path;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
pub struct MobileSocksClientPaths {
#[serde(flatten)]
pub common_paths: CommonClientPaths,
}
impl MobileSocksClientPaths {
pub fn new_default<P: AsRef<Path>>(base_data_directory: P) -> Self {
MobileSocksClientPaths {
common_paths: CommonClientPaths::new_base(base_data_directory),
}
}
pub fn change_root<P: AsRef<Path>, R: AsRef<Path>>(&mut self, new_root: P, id: R) {
let new_data_dir = data_directory_from_root(new_root, id);
self.common_paths = CommonClientPaths::new_base(new_data_dir)
}
}
@@ -1,111 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// While using normal toml marshalling would have been way simpler with less overhead,
// I think it's useful to have comments attached to the saved config file to explain behaviour of
// particular fields.
// Note: any changes to the template must be reflected in the appropriate structs.
pub(crate) const CONFIG_TEMPLATE: &str = r#"
# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
##### main base client config options #####
[core.client]
# Version of the client for which this configuration was created.
version = '{{ core.client.version }}'
# Human readable ID of this particular client.
id = '{{ core.client.id }}'
# Indicates whether this client is running in a disabled credentials mode, thus attempting
# to claim bandwidth without presenting bandwidth credentials.
disabled_credentials_mode = {{ core.client.disabled_credentials_mode }}
# Addresses to nyxd validators via which the client can communicate with the chain.
nyxd_urls = [
{{#each core.client.nyxd_urls }}
'{{this}}',
{{/each}}
]
# Addresses to APIs running on validator from which the client gets the view of the network.
nym_api_urls = [
{{#each core.client.nym_api_urls }}
'{{this}}',
{{/each}}
]
[storage_paths]
# Path to file containing private identity key.
keys.private_identity_key_file = '{{ storage_paths.keys.private_identity_key_file }}'
# Path to file containing public identity key.
keys.public_identity_key_file = '{{ storage_paths.keys.public_identity_key_file }}'
# Path to file containing private encryption key.
keys.private_encryption_key_file = '{{ storage_paths.keys.private_encryption_key_file }}'
# Path to file containing public encryption key.
keys.public_encryption_key_file = '{{ storage_paths.keys.public_encryption_key_file }}'
# Path to file containing key used for encrypting and decrypting the content of an
# acknowledgement so that nobody besides the client knows which packet it refers to.
keys.ack_key_file = '{{ storage_paths.keys.ack_key_file }}'
# Path to the database containing bandwidth credentials
credentials_database = '{{ storage_paths.credentials_database }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database = '{{ storage_paths.reply_surb_database }}'
# Path to the file containing information about gateways used by this client,
# i.e. details such as their public keys, owner addresses or the network information.
gateway_registrations = '{{ storage_paths.gateway_registrations }}'
##### socket config options #####
[core.socks5]
# The mix address of the provider to which all requests are going to be sent.
provider_mix_address = '{{ core.socks5.provider_mix_address }}'
# The address on which the client will be listening for incoming requests
# (default: 127.0.0.1:1080)
bind_address = '{{ core.socks5.bind_address }}'
# Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
# While this is going to hide its actual address information, it will make the actual communication
# slower and consume nearly double the bandwidth as it will require sending reply SURBs.
#
# Note that some service providers might not support this.
send_anonymously = {{ core.socks5.send_anonymously }}
##### logging configuration options #####
[logging]
# TODO
##### debug configuration options #####
# The following options should not be modified unless you know EXACTLY what you are doing
# as if set incorrectly, they may impact your anonymity.
# [core.socks5.socks5_debug]
[core.debug]
[core.debug.traffic]
average_packet_delay = '{{ core.debug.traffic.average_packet_delay }}'
message_sending_average_delay = '{{ core.debug.traffic.message_sending_average_delay }}'
[core.debug.acknowledgements]
average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
[core.debug.cover_traffic]
loop_cover_traffic_average_delay = '{{ core.debug.cover_traffic.loop_cover_traffic_average_delay }}'
"#;
-378
View File
@@ -1,378 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::{config_filepath_from_root, Config};
use crate::persistence::MobileClientStorage;
use ::safer_ffi::prelude::*;
use anyhow::{anyhow, Result};
use lazy_static::lazy_static;
use log::{debug, info, warn};
use nym_bin_common::logging::setup_logging;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup};
use nym_config_common::defaults::setup_env;
use nym_socks5_client_core::NymClient as Socks5NymClient;
use rand::rngs::OsRng;
use safer_ffi::char_p::char_p_boxed;
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tokio::runtime::Runtime;
use tokio::sync::{Mutex, Notify};
use tokio::time::{sleep, Instant};
#[cfg(target_os = "android")]
pub mod android;
mod config;
mod persistence;
static SOCKS5_CONFIG_ID: &str = "mobile-socks5-test";
const ANDROID_HEALTHCHECK_INTERVAL: Duration = Duration::from_secs(5);
const HEALTHCHECK_TIMEOUT: Duration = Duration::from_secs(10);
// hehe, this is so disgusting : )
lazy_static! {
static ref CLIENT_SHUTDOWN_HANDLE: Mutex<Option<Arc<Notify>>> = Mutex::new(None);
static ref RUNTIME: Runtime = Runtime::new().unwrap();
static ref LAST_HEALTHCHECK_PING: Mutex<Option<Instant>> = Mutex::new(None);
}
static ENV_SET: AtomicBool = AtomicBool::new(false);
async fn set_shutdown_handle(handle: Arc<Notify>) {
let mut guard = CLIENT_SHUTDOWN_HANDLE.lock().await;
if guard.is_some() {
panic!("client wasn't properly stopped")
}
*guard = Some(handle)
}
async fn stop_and_reset_shutdown_handle() {
let mut guard = CLIENT_SHUTDOWN_HANDLE.lock().await;
if let Some(sh) = &*guard {
sh.notify_waiters()
} else {
panic!("client wasn't properly started")
}
*guard = None
}
async fn is_shutdown_handle_set() -> bool {
CLIENT_SHUTDOWN_HANDLE.lock().await.is_some()
}
fn set_default_env() {
if !ENV_SET.swap(true, Ordering::SeqCst) {
setup_env::<&str>(None);
}
}
// to be used with the on startup callback which returns the address
#[ffi_export]
pub fn rust_free_string(string: char_p::Box) {
drop(string)
}
#[ffi_export]
pub fn initialise_logger() {
setup_logging();
info!("logger initialised");
}
#[derive_ReprC]
#[ffi_export]
#[repr(u8)]
#[derive(Eq, PartialEq, Debug)]
pub enum ClientState {
Uninitialised,
Connected,
Disconnected,
}
#[ffi_export]
pub fn get_client_state() -> ClientState {
// if the environment is not set, we never called start before
// if the shutdown was never set, the client can't possibly be running
// and similarly if it's set, it's most likely running
if !ENV_SET.load(Ordering::Relaxed) {
ClientState::Uninitialised
} else if RUNTIME.block_on(is_shutdown_handle_set()) {
ClientState::Connected
} else {
ClientState::Disconnected
}
}
pub fn start_client<F, S>(
storage_directory: Option<char_p::Ref<'_>>,
service_provider: Option<char_p::Ref<'_>>,
on_start_callback: F,
on_shutdown_callback: S,
) where
F: FnMut(String) + Send + 'static,
S: FnMut() + Send + 'static,
{
if get_client_state() == ClientState::Connected {
warn!("could not start the client as it's already running");
return;
}
let storage_dir = storage_directory.map(|s| s.to_string());
let service_provider = service_provider.map(|s| s.to_string());
RUNTIME.spawn(async move {
_async_run_client(
storage_dir,
SOCKS5_CONFIG_ID.to_string(),
service_provider,
on_start_callback,
on_shutdown_callback,
)
.await
});
}
#[ffi_export]
pub fn stop_client() {
if get_client_state() == ClientState::Disconnected {
warn!("could not stop the client as it's not running ");
return;
}
RUNTIME.block_on(async move { stop_and_reset_shutdown_handle().await });
}
#[ffi_export]
pub fn ping_client() {
RUNTIME.spawn(async {
let mut guard = LAST_HEALTHCHECK_PING.lock().await;
*guard = Some(Instant::now());
});
}
// Continusouly poll that we are being pinged from the outside. If the pings stop that means
// that the higher layer somehow terminated without telling us.
pub async fn health_check() {
// init the ping to now
let mut guard = LAST_HEALTHCHECK_PING.lock().await;
*guard = Some(Instant::now());
// release the mutex
drop(guard);
loop {
sleep(ANDROID_HEALTHCHECK_INTERVAL).await;
if !is_shutdown_handle_set().await {
debug!("client has been shutdown, cancelling healthcheck");
break;
}
let mut guard = LAST_HEALTHCHECK_PING.lock().await;
let Some(last_ping) = *guard else {
warn!("client has not been pinged yet - shutting down");
*guard = None;
stop_and_reset_shutdown_handle().await;
break;
};
if last_ping.elapsed() > HEALTHCHECK_TIMEOUT {
warn!(
"client has not been pinged for more than {} seconds - shutting down",
HEALTHCHECK_TIMEOUT.as_secs()
);
*guard = None;
stop_and_reset_shutdown_handle().await;
break;
}
debug!("✓ android app healthy");
}
}
pub fn blocking_run_client<'cb, F, S>(
storage_directory: Option<char_p::Ref<'_>>,
service_provider: Option<char_p::Ref<'_>>,
on_start_callback: F,
on_shutdown_callback: S,
) where
F: FnMut(String) + 'cb,
S: FnMut() + 'cb,
{
if get_client_state() == ClientState::Connected {
warn!("could not start the client as it's already running");
return;
}
// Spawn a task that monitors that we are continuously receiving pings from the outside,
// to make sure we don't end up with a runaway process
RUNTIME.spawn(async { health_check().await });
let storage_dir = storage_directory.map(|s| s.to_string());
let service_provider = service_provider.map(|s| s.to_string());
RUNTIME
.block_on(async move {
_async_run_client(
storage_dir,
SOCKS5_CONFIG_ID.to_string(),
service_provider,
on_start_callback,
on_shutdown_callback,
)
.await
})
.map_err(|err| {
warn!("failed to run client: {}", err);
})
.ok();
}
#[ffi_export]
pub fn reset_client_data(root_directory: char_p::Ref<'_>) {
if get_client_state() == ClientState::Connected {
return;
}
let root_dir = root_directory.to_string();
_reset_client_data(root_dir)
}
#[ffi_export]
pub fn existing_service_provider(storage_directory: char_p::Ref<'_>) -> Option<char_p_boxed> {
if let Ok(config) = Config::read_from_default_path(storage_directory.to_str(), SOCKS5_CONFIG_ID)
{
Some(config.core.socks5.provider_mix_address.try_into().unwrap())
} else {
None
}
}
fn _reset_client_data(root_directory: String) {
let client_storage_dir = PathBuf::new().join(root_directory).join(SOCKS5_CONFIG_ID);
std::fs::remove_dir_all(client_storage_dir).expect("failed to clear client data")
}
async fn _async_run_client<F, S>(
storage_dir: Option<String>,
client_id: String,
service_provider: Option<String>,
mut on_start_callback: F,
mut on_shutdown_callback: S,
) -> anyhow::Result<()>
where
F: FnMut(String),
S: FnMut(),
{
let mut rng = OsRng;
set_default_env();
let stop_handle = Arc::new(Notify::new());
set_shutdown_handle(stop_handle.clone()).await;
let config = load_or_generate_base_config(storage_dir, client_id, service_provider).await?;
let nym_apis = config.core.base.client.nym_api_urls.clone();
let storage = MobileClientStorage::new(&config);
let user_agent = nym_bin_common::bin_info!().into();
let socks5_client = Socks5NymClient::new(config.core, storage, user_agent, None)
.with_gateway_setup(GatewaySetup::New {
specification: GatewaySelectionSpecification::UniformRemote {
must_use_tls: false,
},
available_gateways: current_gateways(&mut rng, &nym_apis, None, 50).await?,
});
eprintln!("starting the socks5 client");
let started_client = socks5_client.start().await?;
eprintln!("the client has started!");
// invoke the callback since we've started!
on_start_callback(started_client.address.to_string());
// wait for notify to be set...
stop_handle.notified().await;
// and then do graceful shutdown of all tasks
let mut task_manager = started_client
.shutdown_handle
.try_into_task_manager()
.unwrap();
task_manager.signal_shutdown().ok();
task_manager.wait_for_shutdown().await;
// and the corresponding one for shutdown!
on_shutdown_callback();
Ok(())
}
// note: it does might not contain any gateway configuration and should not be persisted in that state!
async fn load_or_generate_base_config(
storage_dir: Option<String>,
client_id: String,
service_provider: Option<String>,
) -> Result<Config> {
let Some(storage_dir) = storage_dir else {
eprintln!("no storage path specified");
return setup_new_client_config(None, client_id, service_provider).await;
};
let expected_store_path = config_filepath_from_root(&storage_dir, &client_id);
eprintln!(
"attempting to load socks5 config from {}",
expected_store_path.display()
);
// simulator workaround
if let Ok(mut config) = Config::read_from_toml_file(expected_store_path) {
eprintln!("loaded config");
if let Some(storage_paths) = &mut config.storage_paths {
if !storage_paths
.common_paths
.keys
.public_identity_key_file
.starts_with(&storage_dir)
{
eprintln!("... but it seems to have been made for different container - fixing it up... (ASSUMING DEFAULT PATHS)");
storage_paths.change_root(storage_dir, &config.core.base.client.id);
}
}
return Ok(config);
};
eprintln!("creating new config");
setup_new_client_config(Some(storage_dir), client_id, service_provider).await
}
async fn setup_new_client_config(
storage_dir: Option<String>,
client_id: String,
service_provider: Option<String>,
) -> Result<Config> {
let service_provider = service_provider.ok_or(anyhow!(
"service provider was not specified for fresh config"
))?;
let mut new_config = Config::new(storage_dir.as_ref(), client_id, service_provider);
if let Ok(raw_validators) = std::env::var(nym_config_common::defaults::var_names::NYM_API) {
new_config
.core
.base
.set_custom_nym_apis(nym_config_common::parse_urls(&raw_validators));
}
if let Some(_storage_paths) = &new_config.storage_paths {
println!("persistent storage is not implemented");
};
if let Some(storage_dir) = storage_dir {
new_config.save_to_default_location(storage_dir)?;
}
Ok(new_config)
}
#[cfg(feature = "headers")] // c.f. the `Cargo.toml` section
pub fn generate_headers() -> ::std::io::Result<()> {
::safer_ffi::headers::builder()
.to_file("socks5_c.h")?
.generate()
}
@@ -1,65 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::Config;
use nym_client_core::client::base_client::storage::{InMemGatewaysDetails, MixnetClientStorage};
use nym_client_core::client::key_manager::persistence::InMemEphemeralKeys;
use nym_client_core::client::replies::reply_storage;
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
pub struct MobileClientStorage {
// the key storage is now useless without gateway details store. so use ephemeral for everything.
key_store: InMemEphemeralKeys,
gateway_details_store: InMemGatewaysDetails,
reply_store: reply_storage::Empty,
credential_store: EphemeralCredentialStorage,
}
impl MixnetClientStorage for MobileClientStorage {
type KeyStore = InMemEphemeralKeys;
type ReplyStore = reply_storage::Empty;
type CredentialStore = EphemeralCredentialStorage;
type GatewaysDetailsStore = InMemGatewaysDetails;
fn into_runtime_stores(
self,
) -> (
Self::ReplyStore,
Self::CredentialStore,
Self::GatewaysDetailsStore,
) {
(
self.reply_store,
self.credential_store,
self.gateway_details_store,
)
}
fn key_store(&self) -> &Self::KeyStore {
&self.key_store
}
fn reply_store(&self) -> &Self::ReplyStore {
&self.reply_store
}
fn credential_store(&self) -> &Self::CredentialStore {
&self.credential_store
}
fn gateway_details_store(&self) -> &Self::GatewaysDetailsStore {
&self.gateway_details_store
}
}
impl MobileClientStorage {
pub fn new(_config: &Config) -> Self {
MobileClientStorage {
key_store: Default::default(),
gateway_details_store: Default::default(),
reply_store: Default::default(),
credential_store: Default::default(),
}
}
}