Kotlin Multiplatform support for embedding Tor into your application.
NOTICE: kmp-tor
is being overhauled. This branch is for the 1.x.x
version. See
HERE for the latest and greatest.
Add dependency
// build.gradle.kts
dependencies {
val vTor = "4.8.10-0"
val vKmpTor = "1.4.4"
implementation("io.matthewnelson.kotlin-components:kmp-tor:$vTor-$vKmpTor")
}
// build.gradle
dependencies {
def vTor = '4.8.10-0'
def vKmpTor = '1.4.4'
implementation "io.matthewnelson.kotlin-components:kmp-tor:$vTor-$vKmpTor"
}
Configuring an Android Project
-
Ensure that the Kotlin Gradle Plugin is applied to your project
-
See the
Android
section of the kmp-tor-binary project'sREADME
to set things up so the Tor binaries are properly extracted upon app install. -
By default,
TorService
needs no configuration and runs in the background. For configuring it to run as a Foreground service, see the following:
- See the Sample App for a basic setup of
TorManager
and yourTorConfig
.
Configuring a Java Project
- See the
Java
section of the kmp-tor-binary project'sREADME
. - See the JavaFX Sample App Gradle Configuration for a basic gradle/dependency configuration.
- See the JavaFx Sample App for a basic setup example.
- Run the JavaFx Sample via
./gradlew :samples:kotlin:javafx:run -PKMP_TARGETS=JVM
from terminal or cmd prompt.- Note: Be sure to run
git submodule update --init
if you haven't yet so git submodules are initialized.
- Note: Be sure to run
Unix Domain Sockets
- ControlPort
- SocksPort
- HiddenServicePort
- For Android, nothing is needed
- For JVM
- If JDK 16+, nothing is needed
- Otherwise, add the following dependency to your darwin/linux builds:
// build.gradlew.kts dependencies { val vTor = "4.8.10-0" val vKmpTor = "1.4.4" implementation("io.matthewnelson.kotlin-components:kmp-tor:$vTor-$vKmpTor") if (isLinuxBuild || isDarwinBuild) { // Unix Domain Socket support extension (JDK 15 and below) implementation("io.matthewnelson.kotlin-components:kmp-tor-ext-unix-socket:$vKmpTor") } }
See the JavaFX Sample App Gradle Configuration
dependencies
block for more info.
If neither TorConfig.Setting.Ports.Control
or TorConfig.Setting.UnixSockets.Control
are expressed in
your config, TorConfig.Setting.UnixSockets.Control
will always be the preferred setting for establishing
a connection to Tor's control port, if support is had (as noted above). To override this behavior, you
can express the TorConfig.Setting.Ports.Control
setting when providing your config at startup.
How to enable unix domain socket support for the SocksPort
and HiddenServicePort
settings:
- Be running on Darwin or Linux (also Android)
Callbacks (non-kotlin consumers)
- For Java projects (who can't use coroutines), you can "wrap"
TorManager
in an implementation that uses callbacks (i.e.CallbackTorManager
).
// build.gradle
dependencies {
def vTor = '4.8.10-0'
def vKmpTor = '1.4.4'
implementation "io.matthewnelson.kotlin-components:kmp-tor:$vTor-$vKmpTor"
// Add the callback extension
implementation "io.matthewnelson.kotlin-components:kmp-tor-ext-callback-manager:$vKmpTor"
// You will also need to add the Kotlin Gradle Plugin, and Coroutines dependency.
// If not Android, you will also need to import the binaries for the platforms you wish to
// support.
}
// Wrapping TorManager instance in its Callback instance (Java)
public class Example1 {
// ..
TorManager instance = TorManager.newInstance(/* ... */);
// Wrap that mug...
CallbackTorManager torManager = new CallbackTorManager(
instance,
uncaughtException -> {
Log.e("MyJavaApp", "Some TorCallback isn't handling an exception...", uncaughtException);
}
);
}
- All requests use coroutines under the hood and are Main thread safe. Results will be dispatched to the supplied callback on the Main thread.
// Multiple callbacks of different styles (Java)
public class Example2 {
// ...
Task startTask = torManager.start(
t -> Log.e(TAG, "Failed to start Tor", t),
startSuccess -> {
Log.d(TAG, "Tor started successfully");
Task restartTask = torManager.restart(
null, // fail silently by omitting failure callback
(TorCallback<Object>) restartSuccess -> {
Log.d(TAG, "Tor restarted successfully");
Task restartTask2 = torManager.restart(
// Use the provided instance that will automatically throw
// the exception, which will pipe it to the handler.
TorCallback.THROW,
new TorCallback<Object>() {
@Override
public void invoke(Object o) {
Log.d(TAG, "Tor restarted successfully");
}
}
);
}
);
}
);
}
- Android (Java):
- JavaFx (Java):
- JavaFx Sample App
- JavaFx Sample Gradle
- Run the sample via
./gradlew :samples:java:javafx:run -PKMP_TARGETS=JVM
from terminal or cmd prompt.- Note: Be sure to run
git submodule update --init
if you haven't yet so git submodules are initialized.
- Note: Be sure to run