Skip to content

Commit

Permalink
Use TorConfig as parameter for TorCmd.Config commands Load and …
Browse files Browse the repository at this point in the history
…`Set` (#527)
  • Loading branch information
05nelsonm authored Aug 24, 2024
1 parent 7b8e459 commit 0b08bf8
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 167 deletions.
12 changes: 8 additions & 4 deletions library/runtime-core/api/runtime-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -707,13 +707,15 @@ public final class io/matthewnelson/kmp/tor/runtime/core/config/IntervalUnit$WEE
public fun toString ()Ljava/lang/String;
}

public final class io/matthewnelson/kmp/tor/runtime/core/config/TorConfig {
public final class io/matthewnelson/kmp/tor/runtime/core/config/TorConfig : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
public static final field Companion Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig$Companion;
public final field settings Ljava/util/Set;
public synthetic fun <init> (Ljava/util/Set;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun Builder (Lio/matthewnelson/kmp/tor/runtime/core/ThisBlock;)Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun iterator ()Ljava/util/Iterator;
public static final fun toConfig (Lio/matthewnelson/kmp/tor/runtime/core/config/TorSetting;)Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;
public fun toString ()Ljava/lang/String;
}

Expand All @@ -735,6 +737,7 @@ protected final class io/matthewnelson/kmp/tor/runtime/core/config/TorConfig$Bui

public final class io/matthewnelson/kmp/tor/runtime/core/config/TorConfig$Companion {
public final fun Builder (Lio/matthewnelson/kmp/tor/runtime/core/ThisBlock;)Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;
public final fun toConfig (Lio/matthewnelson/kmp/tor/runtime/core/config/TorSetting;)Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;
}

public abstract class io/matthewnelson/kmp/tor/runtime/core/config/TorOption : java/lang/CharSequence, java/lang/Comparable {
Expand Down Expand Up @@ -3901,8 +3904,9 @@ public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Config$Get
}

public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Config$Load : io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Privileged {
public final field configText Ljava/lang/String;
public fun <init> (Ljava/lang/String;)V
public final field config Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;
public fun <init> (Lio/matthewnelson/kmp/tor/runtime/core/ThisBlock;)V
public fun <init> (Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;)V
}

public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Config$Reset : io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Unprivileged {
Expand All @@ -3919,7 +3923,7 @@ public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Config$Save
}

public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Config$Set : io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd$Unprivileged {
public final field settings Ljava/util/Set;
public final field config Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;
public fun <init> (Lio/matthewnelson/kmp/tor/runtime/core/ThisBlock;)V
public fun <init> (Lio/matthewnelson/kmp/tor/runtime/core/config/TorConfig;)V
public fun <init> (Lio/matthewnelson/kmp/tor/runtime/core/config/TorSetting;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.matthewnelson.kmp.tor.runtime.core.config

import io.matthewnelson.immutable.collections.immutableSetOf
import io.matthewnelson.immutable.collections.toImmutableSet
import io.matthewnelson.kmp.file.File
import io.matthewnelson.kmp.tor.core.api.annotation.InternalKmpTorApi
Expand All @@ -34,14 +35,16 @@ import kotlin.jvm.JvmSynthetic
* @see [TorSetting.filterByAttribute]
* @see [TorSetting.filterByOption]
* */
public class TorConfig private constructor(settings: Set<TorSetting>) {
public class TorConfig private constructor(settings: Set<TorSetting>): Iterable<TorSetting> {

/**
* All [TorSetting] which make up this configuration.
* */
@JvmField
public val settings: Set<TorSetting> = settings.toImmutableSet()

public override fun iterator(): Iterator<TorSetting> = settings.iterator()

public companion object {

/**
Expand All @@ -56,6 +59,14 @@ public class TorConfig private constructor(settings: Set<TorSetting>) {
@OptIn(InternalKmpTorApi::class)
return RealBuilderScopeTorConfig.build(::TorConfig, block)
}

/**
* Wraps a single [TorSetting] in [TorConfig].
* */
@JvmStatic
public fun TorSetting.toConfig(): TorConfig {
return TorConfig(immutableSetOf(this))
}
}

/**
Expand Down Expand Up @@ -314,6 +325,7 @@ public class TorConfig private constructor(settings: Set<TorSetting>) {
public override fun equals(other: Any?): Boolean = other is TorConfig && other.settings == settings
/** @suppress */
public override fun hashCode(): Int = 5 * 42 + settings.hashCode()
// TODO: Extras as code comments. Issue #526
/** @suppress */
public override fun toString(): String = buildString { settings.joinTo(this, separator = "\n") }
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ import kotlin.jvm.*
* Comparison of settings is done such that only the first [LineItem] (or
* "root" item) within [items] is considered.
*
* @see [Iterable.filterByAttribute]
* @see [Iterable.filterByOption]
* @see [filterByAttribute]
* @see [filterByOption]
* */
public class TorSetting private constructor(

Expand Down Expand Up @@ -260,24 +260,6 @@ public class TorSetting private constructor(

public companion object {

/**
* Returns a list containing all elements of [TorSetting] within
* the [Iterable] which contain a [LineItem], and is configured
* for, attribute [A].
*
* For example, if [TorOption.Attribute.UNIX_SOCKET] is parameter
* [A] and 2 declarations of [TorOption.ControlPort] are present
* (one configured as a Unix Socket, and the other as a TCP port),
* then only the one configured as a Unix Socket will be present
* in the returned list.
*
* @see [Iterable.filterByAttribute]
* */
@JvmStatic
public inline fun <reified A: TorOption.Attribute> TorConfig.filterByAttribute(): List<TorSetting> {
return settings.filterByAttribute<A>()
}

/**
* Returns a list containing all elements of [TorSetting] within
* the [Iterable] which contain a [LineItem], and is configured
Expand Down Expand Up @@ -329,17 +311,6 @@ public class TorSetting private constructor(
}
}

/**
* Returns a list containing all elements of [TorSetting] within
* the [TorConfig] which contain a [LineItem] for option [O].
*
* @see [Iterable.filterByOption]
* */
@JvmStatic
public inline fun <reified O: TorOption> TorConfig.filterByOption(): List<TorSetting> {
return settings.filterByOption<O>()
}

/**
* Returns a list containing all elements of [TorSetting] within
* the [Iterable] which contain a [LineItem] for option [O].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public abstract class BuilderScopeVirtualAddr: TorSetting.BuilderScope {
@JvmField
protected var _address: IPAddress = argument.toIPAddress()
@JvmField
protected var _bits: Byte = argument.substringAfter('/').toByte()
protected var _bits: Byte = argument.substringAfterLast('/').toByte()

@JvmSynthetic
internal final override fun build(): TorSetting {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
@file:Suppress("UNUSED_PARAMETER")

package io.matthewnelson.kmp.tor.runtime.core.ctrl

import io.matthewnelson.encoding.base16.Base16
Expand All @@ -30,6 +28,7 @@ import io.matthewnelson.kmp.tor.runtime.core.ctrl.builder.BuilderScopeOnionAdd
import io.matthewnelson.kmp.tor.runtime.core.ctrl.builder.BuilderScopeOnionAdd.Companion.configure
import io.matthewnelson.kmp.tor.runtime.core.ctrl.builder.BuilderScopeClientAuthAdd
import io.matthewnelson.kmp.tor.runtime.core.config.TorConfig
import io.matthewnelson.kmp.tor.runtime.core.config.TorConfig.Companion.toConfig
import io.matthewnelson.kmp.tor.runtime.core.config.TorOption
import io.matthewnelson.kmp.tor.runtime.core.config.TorSetting
import io.matthewnelson.kmp.tor.runtime.core.key.*
Expand Down Expand Up @@ -124,10 +123,16 @@ public sealed class TorCmd<Success: Any> private constructor(
/**
* [control-spec#LOADCONF](https://spec.torproject.org/control-spec/commands.html#loadconf)
* */
public class Load(
public class Load: Privileged<Reply.Success.OK> {

@JvmField
public val configText: String,
): Privileged<Reply.Success.OK>("LOADCONF")
public val config: TorConfig

public constructor(block: ThisBlock<TorConfig.BuilderScope>): this(TorConfig.Builder(block))
public constructor(config: TorConfig): super("LOADCONF") {
this.config = config
}
}

/**
* [control-spec#RESETCONF](https://spec.torproject.org/control-spec/commands.html#resetconf)
Expand Down Expand Up @@ -165,17 +170,15 @@ public sealed class TorCmd<Success: Any> private constructor(
public class Set: Unprivileged<Reply.Success.OK> {

@JvmField
public val settings: kotlin.collections.Set<TorSetting>
public val config: TorConfig

public constructor(setting: TorSetting): this(immutableSetOf(setting), null)
public constructor(setting: TorSetting): this(setting.toConfig())
public constructor(vararg settings: TorSetting): this(ThisBlock { settings.forEach { put(it) } })
public constructor(settings: Collection<TorSetting>): this(ThisBlock { putAll(settings) })

public constructor(block: ThisBlock<TorConfig.BuilderScope>): this(TorConfig.Builder(block))
public constructor(config: TorConfig): this(config.settings, null)

private constructor(settings: kotlin.collections.Set<TorSetting>, any: Any?): super("SETCONF") {
this.settings = settings
public constructor(config: TorConfig): super("SETCONF") {
this.config = config
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ class TorCmdConfigSetUnitTest {
assertEquals(2, set.size)

val cmd = TorCmd.Config.Set(set)
assertEquals(1, cmd.settings.size)
assertEquals(1, cmd.config.settings.size)

// When all items in the set were added to TorConfig.BuilderScope, the
// final argument should have overridden the first one.
assertEquals(false.byte.toString(), cmd.settings.first().items.first().argument)
assertEquals(false.byte.toString(), cmd.config.settings.first().items.first().argument)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,27 @@ private fun TorCmd.Config.Get.encode(LOG: Debugger?): ByteArray {

@Throws(IllegalArgumentException::class)
private fun TorCmd.Config.Load.encode(LOG: Debugger?): ByteArray {
require(config.settings.isNotEmpty()) { "A minimum of 1 setting is required" }

return StringBuilder().apply {
append('+').append(keyword)

var hasLine = false
for (line in configText.lines()) {
val isCommentOrBlank = run {
val i = line.indexOfFirst { !it.isWhitespace() }
if (i == -1) true else line[i] == '#'
}
if (isCommentOrBlank) continue

if (!hasLine) {
hasLine = true
LOG.d { ">> ${toString()}" }
CRLF()
} else {
appendLine()
}
var crlf = false
for (setting in config) {
for (line in setting.items) {
if (!crlf) {
crlf = true
LOG.d { ">> ${toString()}" }
CRLF()
} else {
appendLine()
}

append(line)
LOG.d { ">> $line" }
append(line)
LOG.d { ">> $line" }
}
}

require(hasLine) { "configText must contain at least 1 setting" }

CRLF()
LOG.d { ">> ." }
append('.')
Expand Down Expand Up @@ -146,28 +142,23 @@ private fun TorCmd.Config.Save.encode(LOG: Debugger?): ByteArray {

@Throws(IllegalArgumentException::class)
private fun TorCmd.Config.Set.encode(LOG: Debugger?): ByteArray {
require(settings.isNotEmpty()) { "A minimum of 1 setting is required" }
require(config.settings.isNotEmpty()) { "A minimum of 1 setting is required" }

return StringBuilder(keyword).apply {
for (setting in settings) {
for (setting in config) {
for (line in setting.items) {
SP().append(line.option).append('=').append('"')

run {
var argument = line.argument

with(line.option.attributes) {
when {
contains(Attribute.UNIX_SOCKET) -> {
if (argument.startsWith("unix:")) {
argument = argument.replace("\"", "\\\"")
}
}
contains(Attribute.FILE) || contains(Attribute.DIRECTORY) -> {
if (SysDirSep == '\\') {
argument = argument.replace("\\", "\\\\")
}
}
// Escapes
when {
line.isUnixSocket -> {
argument = argument.replace("\"", "\\\"")
}
(line.isDirectory || line.isFile) && SysDirSep == '\\' -> {
argument = argument.replace("\\", "\\\\")
}
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,8 @@ public class TorListeners private constructor(
protected open fun onConfigChangeJob(cmd: TorCmd.Config.Set, job: EnqueuedJob) {
job.invokeOnErrorRecovery(recovery = {
val changes = run {
val eSocks = cmd.settings.filterByOption<TorOption.__SocksPort>()
val socks = cmd.settings.filterByOption<TorOption.SocksPort>()
val eSocks = cmd.config.filterByOption<TorOption.__SocksPort>()
val socks = cmd.config.filterByOption<TorOption.SocksPort>()
eSocks + socks
}.takeIf { it.isNotEmpty() }?.let { settings ->
settings.mapTo(LinkedHashSet(settings.size, 1.0F)) { setting ->
Expand Down
Loading

0 comments on commit 0b08bf8

Please sign in to comment.