Skip to content

05nelsonm/kmp-tor

Repository files navigation

kmp-tor

badge-license badge-latest-release

badge-kotlin badge-atomicfu badge-coroutines badge-encoding badge-parcelize badge-kmp-tor-binary

badge-platform-android badge-platform-jvm

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.

Get Started

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's README 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 your TorConfig.
Configuring a Java Project
  • See the Java section of the kmp-tor-binary project's README.
  • 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.

Extensions

Unix Domain Sockets

Tor supports use of unix domain sockets on Darwin and Linux (also Android) for the following:

  • ControlPort
  • SocksPort
  • HiddenServicePort

How to enable unix domain socket support for the ControlPort:

  • 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");
                            }
                        }
                    );
                }
            );
        }
    );
}

About

Kotlin Multiplatform Library for embedding Tor into your applications

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages