diff --git a/build.gradle b/build.gradle index 4e228e0..2169e2f 100644 --- a/build.gradle +++ b/build.gradle @@ -54,6 +54,14 @@ subprojects { archives javadocJar, sourcesJar } + jar { + manifest { + attributes 'Implementation-Title': "Jabit ${project.name.capitalize()}", + 'Implementation-Version': version + } + baseName "jabit-${project.name}" + } + signing { required { isRelease && project.getProperties().get("signing.keyId")?.length() > 0 } sign configurations.archives diff --git a/core/build.gradle b/core/build.gradle index eb8118c..6af7a84 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -25,9 +25,27 @@ artifacts { dependencies { compile 'org.slf4j:slf4j-api' - compile 'ch.dissem.msgpack:msgpack' - testCompile 'junit:junit' - testCompile 'org.hamcrest:hamcrest-library' - testCompile 'com.nhaarman:mockito-kotlin' + compile 'ch.dissem.msgpack:msgpack:1.0.0' + testCompile 'junit:junit:4.12' + testCompile 'org.hamcrest:hamcrest-library:1.3' + testCompile 'com.nhaarman:mockito-kotlin:1.5.0' testCompile project(':cryptography-bc') } + +def generatedResources = "${project.buildDir}/generated-resources/main" + +sourceSets { + main { + output.dir(generatedResources, builtBy: 'generateVersionInfo') + } +} +task('generateVersionInfo') { + doLast { + def dir = new File(generatedResources) + if (!dir.exists()) { + dir.mkdirs() + } + def file = new File(generatedResources, "version") + file.write(project.version.toString()) + } +} diff --git a/core/src/main/kotlin/ch/dissem/bitmessage/BitmessageContext.kt b/core/src/main/kotlin/ch/dissem/bitmessage/BitmessageContext.kt index ff3a58d..2f09636 100644 --- a/core/src/main/kotlin/ch/dissem/bitmessage/BitmessageContext.kt +++ b/core/src/main/kotlin/ch/dissem/bitmessage/BitmessageContext.kt @@ -75,6 +75,7 @@ class BitmessageContext( }, listener: Listener, labeler: Labeler = DefaultLabeler(), + userAgent: String? = null, port: Int = 8444, connectionTTL: Long = 30 * MINUTE, connectionLimit: Int = 150, @@ -99,6 +100,7 @@ class BitmessageContext( }, builder.listener, builder.labeler ?: DefaultLabeler(), + builder.userAgent, builder.port, builder.connectionTTL, builder.connectionLimit, @@ -333,6 +335,7 @@ class BitmessageContext( fun status(): Property { return Property("status", + Property("user agent", internals.userAgent), internals.networkHandler.getNetworkStatus(), Property("unacknowledged", internals.messageRepository.findMessagesToResend().size) ) @@ -361,6 +364,7 @@ class BitmessageContext( internal var cryptography by Delegates.notNull() internal var customCommandHandler: CustomCommandHandler? = null internal var labeler: Labeler? = null + internal var userAgent: String? = null internal var listener by Delegates.notNull() internal var connectionLimit = 150 internal var connectionTTL = 30 * MINUTE @@ -480,6 +484,7 @@ class BitmessageContext( customCommandHandler, listener, labeler, + userAgent?.let { "/$it/Jabit:$version/" } ?: "/Jabit:$version/", port, connectionTTL, connectionLimit @@ -494,5 +499,11 @@ class BitmessageContext( companion object { @JvmField val CURRENT_VERSION = 3 private val LOG = LoggerFactory.getLogger(BitmessageContext::class.java) + + val version: String by lazy { + BitmessageContext::class.java.getResource("/version")?.readText() ?: "local build" + } + @JvmStatic get + } } diff --git a/core/src/main/kotlin/ch/dissem/bitmessage/DefaultMessageListener.kt b/core/src/main/kotlin/ch/dissem/bitmessage/DefaultMessageListener.kt index 826c9cd..ac30587 100644 --- a/core/src/main/kotlin/ch/dissem/bitmessage/DefaultMessageListener.kt +++ b/core/src/main/kotlin/ch/dissem/bitmessage/DefaultMessageListener.kt @@ -29,7 +29,7 @@ import ch.dissem.bitmessage.utils.Strings.hex import org.slf4j.LoggerFactory import java.util.* -internal open class DefaultMessageListener( +open class DefaultMessageListener( private val labeler: Labeler, private val listener: BitmessageContext.Listener ) : NetworkHandler.MessageListener, InternalContext.ContextHolder { diff --git a/core/src/main/kotlin/ch/dissem/bitmessage/InternalContext.kt b/core/src/main/kotlin/ch/dissem/bitmessage/InternalContext.kt index a1c7f16..42ed782 100644 --- a/core/src/main/kotlin/ch/dissem/bitmessage/InternalContext.kt +++ b/core/src/main/kotlin/ch/dissem/bitmessage/InternalContext.kt @@ -51,6 +51,8 @@ class InternalContext( listener: BitmessageContext.Listener, val labeler: Labeler, + val userAgent: String, + val port: Int, val connectionTTL: Long, val connectionLimit: Int diff --git a/core/src/main/kotlin/ch/dissem/bitmessage/entity/Version.kt b/core/src/main/kotlin/ch/dissem/bitmessage/entity/Version.kt index 07d6d47..5f65bcc 100644 --- a/core/src/main/kotlin/ch/dissem/bitmessage/entity/Version.kt +++ b/core/src/main/kotlin/ch/dissem/bitmessage/entity/Version.kt @@ -62,7 +62,7 @@ class Version constructor( /** * User Agent (0x00 if string is 0 bytes long). Sending nodes must not include a user_agent longer than 5000 bytes. */ - val userAgent: String = "/Jabit:0.0.1/", + val userAgent: String, /** * The stream numbers that the emitting node is interested in. Sending nodes must not include more than 160000 diff --git a/core/src/main/kotlin/ch/dissem/bitmessage/utils/Property.kt b/core/src/main/kotlin/ch/dissem/bitmessage/utils/Property.kt index 323c5cb..91fbb24 100644 --- a/core/src/main/kotlin/ch/dissem/bitmessage/utils/Property.kt +++ b/core/src/main/kotlin/ch/dissem/bitmessage/utils/Property.kt @@ -25,7 +25,11 @@ package ch.dissem.bitmessage.utils * If you need a real JSON representation, please add a method `toJson()`. * */ -class Property private constructor(val name: String, val value: Any? = null, val properties: Array = emptyArray()) { +class Property private constructor( + val name: String, + val value: Any? = null, + val properties: Array +) { constructor(name: String, value: Any) : this(name = name, value = value, properties = emptyArray()) constructor(name: String, vararg properties: Property) : this(name, null, arrayOf(*properties)) diff --git a/core/src/test/kotlin/ch/dissem/bitmessage/BitmessageContextTest.kt b/core/src/test/kotlin/ch/dissem/bitmessage/BitmessageContextTest.kt index 4814ac7..24e8ae3 100644 --- a/core/src/test/kotlin/ch/dissem/bitmessage/BitmessageContextTest.kt +++ b/core/src/test/kotlin/ch/dissem/bitmessage/BitmessageContextTest.kt @@ -28,6 +28,7 @@ import ch.dissem.bitmessage.ports.DefaultLabeler import ch.dissem.bitmessage.ports.ProofOfWorkEngine import ch.dissem.bitmessage.ports.ProofOfWorkRepository import ch.dissem.bitmessage.testutils.TestInventory +import ch.dissem.bitmessage.utils.Property import ch.dissem.bitmessage.utils.Singleton.cryptography import ch.dissem.bitmessage.utils.Strings.hex import ch.dissem.bitmessage.utils.TTL @@ -98,7 +99,9 @@ class BitmessageContextTest { .inventory(inventory) .listener(listener) .messageRepo(mock()) - .networkHandler(mock()) + .networkHandler(mock { + on { getNetworkStatus() } doReturn Property("test", "mocked") + }) .nodeRegistry(mock()) .labeler(spy(DefaultLabeler())) .powRepo(testPowRepo) @@ -318,4 +321,10 @@ class BitmessageContextTest { ctx.resendUnacknowledgedMessages() verify(ctx.labeler, timeout(1000).times(1)).markAsSent(eq(plaintext)) } + + @Test + fun `ensure status contains user agent`() { + val userAgent = ctx.status().getProperty("user agent")?.value.toString() + assertThat(userAgent, `is`("/Jabit:${BitmessageContext.version}/")) + } } diff --git a/core/src/test/kotlin/ch/dissem/bitmessage/utils/TestUtils.kt b/core/src/test/kotlin/ch/dissem/bitmessage/utils/TestUtils.kt index 6f72ba3..0d92726 100644 --- a/core/src/test/kotlin/ch/dissem/bitmessage/utils/TestUtils.kt +++ b/core/src/test/kotlin/ch/dissem/bitmessage/utils/TestUtils.kt @@ -125,6 +125,7 @@ object TestUtils { customCommandHandler, listener, labeler, + "/Jabit:TEST/", port, connectionTTL, connectionLimit diff --git a/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java b/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java index 059af66..40ee063 100644 --- a/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java +++ b/demo/src/main/java/ch/dissem/bitmessage/demo/Main.java @@ -46,6 +46,8 @@ public class Main { if (System.getProperty("org.slf4j.simpleLogger.logFile") == null) System.setProperty("org.slf4j.simpleLogger.logFile", "./jabit.log"); + System.out.println("Version: " + BitmessageContext.getVersion()); + CmdLineOptions options = new CmdLineOptions(); CmdLineParser parser = new CmdLineParser(options); try { diff --git a/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NetworkConnectionInitializer.kt b/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NetworkConnectionInitializer.kt index 4fd6d7c..df915cd 100644 --- a/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NetworkConnectionInitializer.kt +++ b/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NetworkConnectionInitializer.kt @@ -41,7 +41,7 @@ class NetworkConnectionInitializer( fun start() { if (mode == Connection.Mode.CLIENT || mode == Connection.Mode.SYNC) { - send(Version(nonce = ctx.clientNonce, addrFrom = NetworkAddress.ANY, addrRecv = node)) + send(Version(nonce = ctx.clientNonce, addrFrom = NetworkAddress.ANY, addrRecv = node, userAgent = ctx.userAgent)) } } diff --git a/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NioNetworkHandler.kt b/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NioNetworkHandler.kt index 171b4bb..3a0464a 100644 --- a/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NioNetworkHandler.kt +++ b/networking/src/main/kotlin/ch/dissem/bitmessage/networking/nio/NioNetworkHandler.kt @@ -408,18 +408,18 @@ class NioNetworkHandler : NetworkHandler, InternalContext.ContextHolder { val incomingConnections = TreeMap() val outgoingConnections = TreeMap() - for (connection in connections.keys) { - if (connection.state == Connection.State.ACTIVE) { - for (stream in connection.streams) { + connections.keys + .filter { it.state == Connection.State.ACTIVE } + .forEach { + for (stream in it.streams) { streams.add(stream) - if (connection.mode == SERVER) { + if (it.mode == SERVER) { DebugUtils.inc(incomingConnections, stream) } else { DebugUtils.inc(outgoingConnections, stream) } } } - } val streamProperties = mutableListOf() for (stream in streams) { val incoming = incomingConnections[stream] ?: 0