Refactored BitmessageContext creation
This commit is contained in:
parent
a5c78fd8cf
commit
ddb2073c2f
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.1.60'
|
ext.kotlin_version = '1.1.61'
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package ch.dissem.bitmessage
|
package ch.dissem.bitmessage
|
||||||
|
|
||||||
|
import ch.dissem.bitmessage.BitmessageContext.Companion.version
|
||||||
import ch.dissem.bitmessage.InternalContext.Companion.NETWORK_EXTRA_BYTES
|
import ch.dissem.bitmessage.InternalContext.Companion.NETWORK_EXTRA_BYTES
|
||||||
import ch.dissem.bitmessage.InternalContext.Companion.NETWORK_NONCE_TRIALS_PER_BYTE
|
import ch.dissem.bitmessage.InternalContext.Companion.NETWORK_NONCE_TRIALS_PER_BYTE
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||||
@ -33,7 +34,6 @@ import ch.dissem.bitmessage.exception.DecryptionFailedException
|
|||||||
import ch.dissem.bitmessage.factory.Factory
|
import ch.dissem.bitmessage.factory.Factory
|
||||||
import ch.dissem.bitmessage.ports.*
|
import ch.dissem.bitmessage.ports.*
|
||||||
import ch.dissem.bitmessage.utils.Property
|
import ch.dissem.bitmessage.utils.Property
|
||||||
import ch.dissem.bitmessage.utils.UnixTime.HOUR
|
|
||||||
import ch.dissem.bitmessage.utils.UnixTime.MINUTE
|
import ch.dissem.bitmessage.utils.UnixTime.MINUTE
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
@ -58,57 +58,7 @@ import kotlin.properties.Delegates
|
|||||||
*
|
*
|
||||||
* The port defaults to 8444 (the default Bitmessage port)
|
* The port defaults to 8444 (the default Bitmessage port)
|
||||||
*/
|
*/
|
||||||
class BitmessageContext(
|
class BitmessageContext private constructor(builder: BitmessageContext.Builder) {
|
||||||
cryptography: Cryptography,
|
|
||||||
inventory: Inventory,
|
|
||||||
nodeRegistry: NodeRegistry,
|
|
||||||
networkHandler: NetworkHandler,
|
|
||||||
addressRepository: AddressRepository,
|
|
||||||
messageRepository: MessageRepository,
|
|
||||||
proofOfWorkRepository: ProofOfWorkRepository,
|
|
||||||
proofOfWorkEngine: ProofOfWorkEngine = MultiThreadedPOWEngine(),
|
|
||||||
customCommandHandler: CustomCommandHandler = object : CustomCommandHandler {
|
|
||||||
override fun handle(request: CustomMessage): MessagePayload? {
|
|
||||||
BitmessageContext.LOG.debug("Received custom request, but no custom command handler configured.")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
listener: Listener,
|
|
||||||
labeler: Labeler = DefaultLabeler(),
|
|
||||||
userAgent: String? = null,
|
|
||||||
port: Int = 8444,
|
|
||||||
connectionTTL: Long = 30 * MINUTE,
|
|
||||||
connectionLimit: Int = 150,
|
|
||||||
sendPubkeyOnIdentityCreation: Boolean = true,
|
|
||||||
doMissingProofOfWorkDelayInSeconds: Int = 30
|
|
||||||
) {
|
|
||||||
|
|
||||||
private constructor(builder: BitmessageContext.Builder) : this(
|
|
||||||
builder.cryptography,
|
|
||||||
builder.inventory,
|
|
||||||
builder.nodeRegistry,
|
|
||||||
builder.networkHandler,
|
|
||||||
builder.addressRepo,
|
|
||||||
builder.messageRepo,
|
|
||||||
builder.proofOfWorkRepository,
|
|
||||||
builder.proofOfWorkEngine ?: MultiThreadedPOWEngine(),
|
|
||||||
builder.customCommandHandler ?: object : CustomCommandHandler {
|
|
||||||
override fun handle(request: CustomMessage): MessagePayload? {
|
|
||||||
BitmessageContext.LOG.debug("Received custom request, but no custom command handler configured.")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
builder.listener,
|
|
||||||
builder.labeler ?: DefaultLabeler(),
|
|
||||||
builder.userAgent,
|
|
||||||
builder.port,
|
|
||||||
builder.connectionTTL,
|
|
||||||
builder.connectionLimit,
|
|
||||||
builder.sendPubkeyOnIdentityCreation,
|
|
||||||
builder.doMissingProofOfWorkDelay
|
|
||||||
)
|
|
||||||
|
|
||||||
private val sendPubkeyOnIdentityCreation: Boolean
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [InternalContext] - normally you wouldn't need it,
|
* The [InternalContext] - normally you wouldn't need it,
|
||||||
@ -135,7 +85,7 @@ class BitmessageContext(
|
|||||||
*features
|
*features
|
||||||
))
|
))
|
||||||
internals.addressRepository.save(identity)
|
internals.addressRepository.save(identity)
|
||||||
if (sendPubkeyOnIdentityCreation) {
|
if (internals.preferences.sendPubkeyOnIdentityCreation) {
|
||||||
internals.sendPubkey(identity, identity.stream)
|
internals.sendPubkey(identity, identity.stream)
|
||||||
}
|
}
|
||||||
return identity
|
return identity
|
||||||
@ -262,9 +212,8 @@ class BitmessageContext(
|
|||||||
* @param request the request
|
* @param request the request
|
||||||
* @return the response
|
* @return the response
|
||||||
*/
|
*/
|
||||||
fun send(server: InetAddress, port: Int, request: CustomMessage): CustomMessage {
|
fun send(server: InetAddress, port: Int, request: CustomMessage): CustomMessage =
|
||||||
return internals.networkHandler.send(server, port, request)
|
internals.networkHandler.send(server, port, request)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes expired objects from the inventory. You should call this method regularly,
|
* Removes expired objects from the inventory. You should call this method regularly,
|
||||||
@ -327,7 +276,7 @@ class BitmessageContext(
|
|||||||
|
|
||||||
fun status(): Property {
|
fun status(): Property {
|
||||||
return Property("status",
|
return Property("status",
|
||||||
Property("user agent", internals.userAgent),
|
Property("user agent", internals.preferences.userAgent),
|
||||||
internals.networkHandler.getNetworkStatus(),
|
internals.networkHandler.getNetworkStatus(),
|
||||||
Property("unacknowledged", internals.messageRepository.findMessagesToResend().size)
|
Property("unacknowledged", internals.messageRepository.findMessagesToResend().size)
|
||||||
)
|
)
|
||||||
@ -344,29 +293,22 @@ class BitmessageContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin users: you might want to use [BitmessageContext.build] instead.
|
||||||
|
*/
|
||||||
class Builder {
|
class Builder {
|
||||||
internal var port = 8444
|
var inventory by Delegates.notNull<Inventory>()
|
||||||
internal var inventory by Delegates.notNull<Inventory>()
|
var nodeRegistry by Delegates.notNull<NodeRegistry>()
|
||||||
internal var nodeRegistry by Delegates.notNull<NodeRegistry>()
|
var networkHandler by Delegates.notNull<NetworkHandler>()
|
||||||
internal var networkHandler by Delegates.notNull<NetworkHandler>()
|
var addressRepo by Delegates.notNull<AddressRepository>()
|
||||||
internal var addressRepo by Delegates.notNull<AddressRepository>()
|
var messageRepo by Delegates.notNull<MessageRepository>()
|
||||||
internal var messageRepo by Delegates.notNull<MessageRepository>()
|
var proofOfWorkRepo by Delegates.notNull<ProofOfWorkRepository>()
|
||||||
internal var proofOfWorkRepository by Delegates.notNull<ProofOfWorkRepository>()
|
var proofOfWorkEngine: ProofOfWorkEngine? = null
|
||||||
internal var proofOfWorkEngine: ProofOfWorkEngine? = null
|
var cryptography by Delegates.notNull<Cryptography>()
|
||||||
internal var cryptography by Delegates.notNull<Cryptography>()
|
var customCommandHandler: CustomCommandHandler? = null
|
||||||
internal var customCommandHandler: CustomCommandHandler? = null
|
var labeler: Labeler? = null
|
||||||
internal var labeler: Labeler? = null
|
var listener by Delegates.notNull<Listener>()
|
||||||
internal var userAgent: String? = null
|
val preferences = Preferences()
|
||||||
internal var listener by Delegates.notNull<Listener>()
|
|
||||||
internal var connectionLimit = 150
|
|
||||||
internal var connectionTTL = 30 * MINUTE
|
|
||||||
internal var sendPubkeyOnIdentityCreation = true
|
|
||||||
internal var doMissingProofOfWorkDelay = 30
|
|
||||||
|
|
||||||
fun port(port: Int): Builder {
|
|
||||||
this.port = port
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun inventory(inventory: Inventory): Builder {
|
fun inventory(inventory: Inventory): Builder {
|
||||||
this.inventory = inventory
|
this.inventory = inventory
|
||||||
@ -394,7 +336,7 @@ class BitmessageContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun powRepo(proofOfWorkRepository: ProofOfWorkRepository): Builder {
|
fun powRepo(proofOfWorkRepository: ProofOfWorkRepository): Builder {
|
||||||
this.proofOfWorkRepository = proofOfWorkRepository
|
this.proofOfWorkRepo = proofOfWorkRepository
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +365,7 @@ class BitmessageContext(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("kotlinListener")
|
@JvmSynthetic
|
||||||
fun listener(listener: (Plaintext) -> Unit): Builder {
|
fun listener(listener: (Plaintext) -> Unit): Builder {
|
||||||
this.listener = object : Listener {
|
this.listener = object : Listener {
|
||||||
override fun receive(plaintext: Plaintext) {
|
override fun receive(plaintext: Plaintext) {
|
||||||
@ -433,63 +375,39 @@ class BitmessageContext(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun connectionLimit(connectionLimit: Int): Builder {
|
fun build() = BitmessageContext(this)
|
||||||
this.connectionLimit = connectionLimit
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun connectionTTL(hours: Int): Builder {
|
|
||||||
this.connectionTTL = hours * HOUR
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doMissingProofOfWorkDelay(seconds: Int) {
|
|
||||||
this.doMissingProofOfWorkDelay = seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* By default a client will send the public key when an identity is being created. On weaker devices
|
|
||||||
* this behaviour might not be desirable.
|
|
||||||
*/
|
|
||||||
fun doNotSendPubkeyOnIdentityCreation(): Builder {
|
|
||||||
this.sendPubkeyOnIdentityCreation = false
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun build(): BitmessageContext {
|
|
||||||
return BitmessageContext(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.labeler = labeler
|
this.labeler = builder.labeler ?: DefaultLabeler()
|
||||||
this.internals = InternalContext(
|
this.internals = InternalContext(
|
||||||
cryptography,
|
builder.cryptography,
|
||||||
inventory,
|
builder.inventory,
|
||||||
nodeRegistry,
|
builder.nodeRegistry,
|
||||||
networkHandler,
|
builder.networkHandler,
|
||||||
addressRepository,
|
builder.addressRepo,
|
||||||
messageRepository,
|
builder.messageRepo,
|
||||||
proofOfWorkRepository,
|
builder.proofOfWorkRepo,
|
||||||
proofOfWorkEngine,
|
builder.proofOfWorkEngine ?: MultiThreadedPOWEngine(),
|
||||||
customCommandHandler,
|
builder.customCommandHandler ?: object : CustomCommandHandler {
|
||||||
listener,
|
override fun handle(request: CustomMessage): MessagePayload? {
|
||||||
|
BitmessageContext.LOG.debug("Received custom request, but no custom command handler configured.")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
builder.listener,
|
||||||
labeler,
|
labeler,
|
||||||
userAgent?.let { "/$it/Jabit:$version/" } ?: "/Jabit:$version/",
|
builder.preferences
|
||||||
port,
|
|
||||||
connectionTTL,
|
|
||||||
connectionLimit
|
|
||||||
)
|
)
|
||||||
this.addresses = addressRepository
|
this.addresses = builder.addressRepo
|
||||||
this.messages = messageRepository
|
this.messages = builder.messageRepo
|
||||||
this.sendPubkeyOnIdentityCreation = sendPubkeyOnIdentityCreation
|
(builder.listener as? Listener.WithContext)?.setContext(this)
|
||||||
(listener as? Listener.WithContext)?.setContext(this)
|
internals.proofOfWorkService.doMissingProofOfWork(builder.preferences.doMissingProofOfWorkDelayInSeconds * 1000L)
|
||||||
internals.proofOfWorkService.doMissingProofOfWork(doMissingProofOfWorkDelayInSeconds * 1000L)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField val CURRENT_VERSION = 3
|
@JvmField
|
||||||
|
val CURRENT_VERSION = 3
|
||||||
private val LOG = LoggerFactory.getLogger(BitmessageContext::class.java)
|
private val LOG = LoggerFactory.getLogger(BitmessageContext::class.java)
|
||||||
|
|
||||||
val version: String by lazy {
|
val version: String by lazy {
|
||||||
@ -497,5 +415,40 @@ class BitmessageContext(
|
|||||||
}
|
}
|
||||||
@JvmStatic get
|
@JvmStatic get
|
||||||
|
|
||||||
|
@JvmSynthetic
|
||||||
|
inline fun build(block: Builder.() -> Unit): BitmessageContext {
|
||||||
|
val builder = Builder()
|
||||||
|
block(builder)
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Preferences {
|
||||||
|
var port = 8444
|
||||||
|
/**
|
||||||
|
* Defaults to "/Jabit:<version>/", and whatever you set will be inserted into "/<your user agent>/Jabit:<version>/"
|
||||||
|
*/
|
||||||
|
var userAgent = "/Jabit:$version/"
|
||||||
|
set(value) {
|
||||||
|
field = "/$value/Jabit:$version/"
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Time to live for any connection
|
||||||
|
*/
|
||||||
|
var connectionTTL = 30 * MINUTE
|
||||||
|
/**
|
||||||
|
* Maximum number of connections. Values below 8 would probably result in erratic behaviour, so you shouldn't do that.
|
||||||
|
*/
|
||||||
|
var connectionLimit = 150
|
||||||
|
/**
|
||||||
|
* By default a client will send the public key when an identity is being created. On weaker devices
|
||||||
|
* this behaviour might not be desirable.
|
||||||
|
*/
|
||||||
|
var sendPubkeyOnIdentityCreation = true
|
||||||
|
/**
|
||||||
|
* Delay in seconds before outstandinng proof of work is calculated.
|
||||||
|
*/
|
||||||
|
var doMissingProofOfWorkDelayInSeconds = 30
|
||||||
|
}
|
||||||
|
@ -51,11 +51,7 @@ class InternalContext(
|
|||||||
listener: BitmessageContext.Listener,
|
listener: BitmessageContext.Listener,
|
||||||
val labeler: Labeler,
|
val labeler: Labeler,
|
||||||
|
|
||||||
val userAgent: String,
|
val preferences: Preferences
|
||||||
|
|
||||||
val port: Int,
|
|
||||||
val connectionTTL: Long,
|
|
||||||
val connectionLimit: Int
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val threadPool = Executors.newCachedThreadPool()
|
private val threadPool = Executors.newCachedThreadPool()
|
||||||
|
@ -47,8 +47,8 @@ import kotlin.concurrent.thread
|
|||||||
* @author Christian Basler
|
* @author Christian Basler
|
||||||
*/
|
*/
|
||||||
class BitmessageContextTest {
|
class BitmessageContextTest {
|
||||||
private var listener: BitmessageContext.Listener = mock()
|
private var testListener: BitmessageContext.Listener = mock()
|
||||||
private val inventory = spy(TestInventory())
|
private val testInventory = spy(TestInventory())
|
||||||
private val testPowRepo = spy(object : ProofOfWorkRepository {
|
private val testPowRepo = spy(object : ProofOfWorkRepository {
|
||||||
internal var items: MutableMap<InventoryVector, ProofOfWorkRepository.Item> = HashMap()
|
internal var items: MutableMap<InventoryVector, ProofOfWorkRepository.Item> = HashMap()
|
||||||
internal var added = 0
|
internal var added = 0
|
||||||
@ -93,20 +93,20 @@ class BitmessageContextTest {
|
|||||||
thread { callback.onNonceCalculated(initialHash, ByteArray(8)) }
|
thread { callback.onNonceCalculated(initialHash, ByteArray(8)) }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
private var ctx = BitmessageContext.Builder()
|
private var ctx = BitmessageContext.build {
|
||||||
.addressRepo(mock())
|
addressRepo = mock()
|
||||||
.cryptography(BouncyCryptography())
|
cryptography = BouncyCryptography()
|
||||||
.inventory(inventory)
|
inventory = testInventory
|
||||||
.listener(listener)
|
listener = testListener
|
||||||
.messageRepo(mock())
|
messageRepo = mock()
|
||||||
.networkHandler(mock {
|
networkHandler = mock {
|
||||||
on { getNetworkStatus() } doReturn Property("test", "mocked")
|
on { getNetworkStatus() } doReturn Property("test", "mocked")
|
||||||
})
|
}
|
||||||
.nodeRegistry(mock())
|
nodeRegistry = mock()
|
||||||
.labeler(spy(DefaultLabeler()))
|
labeler = spy(DefaultLabeler())
|
||||||
.powRepo(testPowRepo)
|
proofOfWorkRepo = testPowRepo
|
||||||
.proofOfWorkEngine(testPowEngine)
|
proofOfWorkEngine = testPowEngine
|
||||||
.build()
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
TTL.msg = 2 * MINUTE
|
TTL.msg = 2 * MINUTE
|
||||||
@ -143,7 +143,7 @@ class BitmessageContextTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `ensure V2Pubkey is not requested if it exists in inventory`() {
|
fun `ensure V2Pubkey is not requested if it exists in inventory`() {
|
||||||
inventory.init(
|
testInventory.init(
|
||||||
"V1Msg.payload",
|
"V1Msg.payload",
|
||||||
"V2GetPubkey.payload",
|
"V2GetPubkey.payload",
|
||||||
"V2Pubkey.payload",
|
"V2Pubkey.payload",
|
||||||
@ -166,7 +166,7 @@ class BitmessageContextTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `ensure V4Pubkey is not requested if it exists in inventory`() {
|
fun `ensure V4Pubkey is not requested if it exists in inventory`() {
|
||||||
inventory.init(
|
testInventory.init(
|
||||||
"V1Msg.payload",
|
"V1Msg.payload",
|
||||||
"V2GetPubkey.payload",
|
"V2GetPubkey.payload",
|
||||||
"V2Pubkey.payload",
|
"V2Pubkey.payload",
|
||||||
@ -192,7 +192,7 @@ class BitmessageContextTest {
|
|||||||
fun `ensure subscription is added and existing broadcasts retrieved`() {
|
fun `ensure subscription is added and existing broadcasts retrieved`() {
|
||||||
val address = BitmessageAddress("BM-2D9Vc5rFxxR5vTi53T9gkLfemViHRMVLQZ")
|
val address = BitmessageAddress("BM-2D9Vc5rFxxR5vTi53T9gkLfemViHRMVLQZ")
|
||||||
|
|
||||||
inventory.init(
|
testInventory.init(
|
||||||
"V4Broadcast.payload",
|
"V4Broadcast.payload",
|
||||||
"V5Broadcast.payload"
|
"V5Broadcast.payload"
|
||||||
)
|
)
|
||||||
@ -203,7 +203,7 @@ class BitmessageContextTest {
|
|||||||
verify(ctx.addresses, atLeastOnce()).save(address)
|
verify(ctx.addresses, atLeastOnce()).save(address)
|
||||||
assertThat(address.isSubscribed, `is`(true))
|
assertThat(address.isSubscribed, `is`(true))
|
||||||
verify(ctx.internals.inventory).getObjects(eq(address.stream), any(), any())
|
verify(ctx.internals.inventory).getObjects(eq(address.stream), any(), any())
|
||||||
verify(listener).receive(any())
|
verify(testListener).receive(any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -18,6 +18,7 @@ package ch.dissem.bitmessage.utils
|
|||||||
|
|
||||||
import ch.dissem.bitmessage.BitmessageContext
|
import ch.dissem.bitmessage.BitmessageContext
|
||||||
import ch.dissem.bitmessage.InternalContext
|
import ch.dissem.bitmessage.InternalContext
|
||||||
|
import ch.dissem.bitmessage.Preferences
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||||
import ch.dissem.bitmessage.entity.ObjectMessage
|
import ch.dissem.bitmessage.entity.ObjectMessage
|
||||||
import ch.dissem.bitmessage.entity.payload.V4Pubkey
|
import ch.dissem.bitmessage.entity.payload.V4Pubkey
|
||||||
@ -39,21 +40,25 @@ import kotlin.NoSuchElementException
|
|||||||
* If there's ever a need for this in production code, it should be rewritten to be more efficient.
|
* If there's ever a need for this in production code, it should be rewritten to be more efficient.
|
||||||
*/
|
*/
|
||||||
object TestUtils {
|
object TestUtils {
|
||||||
@JvmField val RANDOM = Random()
|
@JvmField
|
||||||
|
val RANDOM = Random()
|
||||||
|
|
||||||
@JvmStatic fun int16(number: Int): ByteArray {
|
@JvmStatic
|
||||||
|
fun int16(number: Int): ByteArray {
|
||||||
val out = ByteArrayOutputStream()
|
val out = ByteArrayOutputStream()
|
||||||
Encode.int16(number, out)
|
Encode.int16(number, out)
|
||||||
return out.toByteArray()
|
return out.toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun loadObjectMessage(version: Int, resourceName: String): ObjectMessage {
|
@JvmStatic
|
||||||
|
fun loadObjectMessage(version: Int, resourceName: String): ObjectMessage {
|
||||||
val data = getBytes(resourceName)
|
val data = getBytes(resourceName)
|
||||||
val input = ByteArrayInputStream(data)
|
val input = ByteArrayInputStream(data)
|
||||||
return Factory.getObjectMessage(version, input, data.size) ?: throw NoSuchElementException("error loading object message")
|
return Factory.getObjectMessage(version, input, data.size) ?: throw NoSuchElementException("error loading object message")
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun getBytes(resourceName: String): ByteArray {
|
@JvmStatic
|
||||||
|
fun getBytes(resourceName: String): ByteArray {
|
||||||
val input = javaClass.classLoader.getResourceAsStream(resourceName)
|
val input = javaClass.classLoader.getResourceAsStream(resourceName)
|
||||||
val out = ByteArrayOutputStream()
|
val out = ByteArrayOutputStream()
|
||||||
val buffer = ByteArray(1024)
|
val buffer = ByteArray(1024)
|
||||||
@ -65,16 +70,19 @@ object TestUtils {
|
|||||||
return out.toByteArray()
|
return out.toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun randomInventoryVector(): InventoryVector {
|
@JvmStatic
|
||||||
|
fun randomInventoryVector(): InventoryVector {
|
||||||
val bytes = ByteArray(32)
|
val bytes = ByteArray(32)
|
||||||
RANDOM.nextBytes(bytes)
|
RANDOM.nextBytes(bytes)
|
||||||
return InventoryVector(bytes)
|
return InventoryVector(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun getResource(resourceName: String): InputStream =
|
@JvmStatic
|
||||||
|
fun getResource(resourceName: String): InputStream =
|
||||||
javaClass.classLoader.getResourceAsStream(resourceName)
|
javaClass.classLoader.getResourceAsStream(resourceName)
|
||||||
|
|
||||||
@JvmStatic fun loadIdentity(address: String): BitmessageAddress {
|
@JvmStatic
|
||||||
|
fun loadIdentity(address: String): BitmessageAddress {
|
||||||
val privateKey = PrivateKey.read(TestUtils.getResource(address + ".privkey"))
|
val privateKey = PrivateKey.read(TestUtils.getResource(address + ".privkey"))
|
||||||
val identity = BitmessageAddress(privateKey)
|
val identity = BitmessageAddress(privateKey)
|
||||||
assertEquals(address, identity.address)
|
assertEquals(address, identity.address)
|
||||||
@ -82,7 +90,8 @@ object TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(DecryptionFailedException::class)
|
@Throws(DecryptionFailedException::class)
|
||||||
@JvmStatic fun loadContact(): BitmessageAddress {
|
@JvmStatic
|
||||||
|
fun loadContact(): BitmessageAddress {
|
||||||
val address = BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h")
|
val address = BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h")
|
||||||
val objectMessage = TestUtils.loadObjectMessage(3, "V4Pubkey.payload")
|
val objectMessage = TestUtils.loadObjectMessage(3, "V4Pubkey.payload")
|
||||||
objectMessage.decrypt(address.publicDecryptionKey)
|
objectMessage.decrypt(address.publicDecryptionKey)
|
||||||
@ -90,13 +99,15 @@ object TestUtils {
|
|||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun loadPubkey(address: BitmessageAddress) {
|
@JvmStatic
|
||||||
|
fun loadPubkey(address: BitmessageAddress) {
|
||||||
val bytes = getBytes(address.address + ".pubkey")
|
val bytes = getBytes(address.address + ".pubkey")
|
||||||
val pubkey = Factory.readPubkey(address.version, address.stream, ByteArrayInputStream(bytes), bytes.size, false)
|
val pubkey = Factory.readPubkey(address.version, address.stream, ByteArrayInputStream(bytes), bytes.size, false)
|
||||||
address.pubkey = pubkey
|
address.pubkey = pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun mockedInternalContext(
|
@JvmStatic
|
||||||
|
fun mockedInternalContext(
|
||||||
cryptography: Cryptography = mock {},
|
cryptography: Cryptography = mock {},
|
||||||
inventory: Inventory = mock {},
|
inventory: Inventory = mock {},
|
||||||
nodeRegistry: NodeRegistry = mock {},
|
nodeRegistry: NodeRegistry = mock {},
|
||||||
@ -124,10 +135,12 @@ object TestUtils {
|
|||||||
customCommandHandler,
|
customCommandHandler,
|
||||||
listener,
|
listener,
|
||||||
labeler,
|
labeler,
|
||||||
"/Jabit:TEST/",
|
Preferences().apply {
|
||||||
port,
|
this.userAgent = "/Jabit:TEST/"
|
||||||
connectionTTL,
|
this.port = port
|
||||||
connectionLimit
|
this.connectionTTL = connectionTTL
|
||||||
|
this.connectionLimit = connectionLimit
|
||||||
|
}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,8 @@ public class Main {
|
|||||||
.messageRepo(new JdbcMessageRepository(jdbcConfig))
|
.messageRepo(new JdbcMessageRepository(jdbcConfig))
|
||||||
.powRepo(new JdbcProofOfWorkRepository(jdbcConfig))
|
.powRepo(new JdbcProofOfWorkRepository(jdbcConfig))
|
||||||
.networkHandler(new NioNetworkHandler())
|
.networkHandler(new NioNetworkHandler())
|
||||||
.cryptography(new BouncyCryptography())
|
.cryptography(new BouncyCryptography());
|
||||||
.port(48444);
|
ctxBuilder.getPreferences().setPort(48444);
|
||||||
if (options.localPort != null) {
|
if (options.localPort != null) {
|
||||||
ctxBuilder.nodeRegistry(new NodeRegistry() {
|
ctxBuilder.nodeRegistry(new NodeRegistry() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,13 +73,13 @@ public class SystemTest {
|
|||||||
.inventory(new JdbcInventory(aliceDB))
|
.inventory(new JdbcInventory(aliceDB))
|
||||||
.messageRepo(new JdbcMessageRepository(aliceDB))
|
.messageRepo(new JdbcMessageRepository(aliceDB))
|
||||||
.powRepo(new JdbcProofOfWorkRepository(aliceDB))
|
.powRepo(new JdbcProofOfWorkRepository(aliceDB))
|
||||||
.port(alicePort)
|
|
||||||
.nodeRegistry(new TestNodeRegistry(bobPort))
|
.nodeRegistry(new TestNodeRegistry(bobPort))
|
||||||
.networkHandler(new NioNetworkHandler())
|
.networkHandler(new NioNetworkHandler())
|
||||||
.cryptography(new BouncyCryptography())
|
.cryptography(new BouncyCryptography())
|
||||||
.listener(aliceListener)
|
.listener(aliceListener)
|
||||||
.labeler(aliceLabeler)
|
.labeler(aliceLabeler)
|
||||||
.build();
|
.build();
|
||||||
|
alice.internals().getPreferences().setPort(alicePort);
|
||||||
alice.startup();
|
alice.startup();
|
||||||
aliceIdentity = alice.createIdentity(false, DOES_ACK);
|
aliceIdentity = alice.createIdentity(false, DOES_ACK);
|
||||||
}
|
}
|
||||||
@ -91,13 +91,13 @@ public class SystemTest {
|
|||||||
.inventory(new JdbcInventory(bobDB))
|
.inventory(new JdbcInventory(bobDB))
|
||||||
.messageRepo(new JdbcMessageRepository(bobDB))
|
.messageRepo(new JdbcMessageRepository(bobDB))
|
||||||
.powRepo(new JdbcProofOfWorkRepository(bobDB))
|
.powRepo(new JdbcProofOfWorkRepository(bobDB))
|
||||||
.port(bobPort)
|
|
||||||
.nodeRegistry(new TestNodeRegistry(alicePort))
|
.nodeRegistry(new TestNodeRegistry(alicePort))
|
||||||
.networkHandler(new NioNetworkHandler())
|
.networkHandler(new NioNetworkHandler())
|
||||||
.cryptography(new BouncyCryptography())
|
.cryptography(new BouncyCryptography())
|
||||||
.listener(bobListener)
|
.listener(bobListener)
|
||||||
.labeler(new DebugLabeler("Bob"))
|
.labeler(new DebugLabeler("Bob"))
|
||||||
.build();
|
.build();
|
||||||
|
bob.internals().getPreferences().setPort(bobPort);
|
||||||
bob.startup();
|
bob.startup();
|
||||||
bobIdentity = bob.createIdentity(false, DOES_ACK);
|
bobIdentity = bob.createIdentity(false, DOES_ACK);
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ class NetworkConnectionInitializer(
|
|||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
if (mode == Connection.Mode.CLIENT || mode == Connection.Mode.SYNC) {
|
if (mode == Connection.Mode.CLIENT || mode == Connection.Mode.SYNC) {
|
||||||
send(Version(nonce = ctx.clientNonce, addrFrom = NetworkAddress.ANY, addrRecv = node, userAgent = ctx.userAgent))
|
send(Version(nonce = ctx.clientNonce, addrFrom = NetworkAddress.ANY, addrRecv = node, userAgent = ctx.preferences.userAgent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ class NioNetworkHandler : NetworkHandler, InternalContext.ContextHolder {
|
|||||||
val serverChannel = ServerSocketChannel.open()
|
val serverChannel = ServerSocketChannel.open()
|
||||||
this.serverChannel = serverChannel
|
this.serverChannel = serverChannel
|
||||||
serverChannel.configureBlocking(false)
|
serverChannel.configureBlocking(false)
|
||||||
serverChannel.socket().bind(InetSocketAddress(ctx.port))
|
serverChannel.socket().bind(InetSocketAddress(ctx.preferences.port))
|
||||||
serverChannel.register(selector, OP_ACCEPT, null)
|
serverChannel.register(selector, OP_ACCEPT, null)
|
||||||
|
|
||||||
while (selector.isOpen) {
|
while (selector.isOpen) {
|
||||||
|
@ -23,7 +23,8 @@ import ch.dissem.bitmessage.entity.MessagePayload
|
|||||||
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress
|
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress
|
||||||
import ch.dissem.bitmessage.exception.NodeException
|
import ch.dissem.bitmessage.exception.NodeException
|
||||||
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
|
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
|
||||||
import ch.dissem.bitmessage.ports.*
|
import ch.dissem.bitmessage.ports.CustomCommandHandler
|
||||||
|
import ch.dissem.bitmessage.ports.NetworkHandler
|
||||||
import ch.dissem.bitmessage.testutils.TestInventory
|
import ch.dissem.bitmessage.testutils.TestInventory
|
||||||
import ch.dissem.bitmessage.utils.Property
|
import ch.dissem.bitmessage.utils.Property
|
||||||
import ch.dissem.bitmessage.utils.Singleton.cryptography
|
import ch.dissem.bitmessage.utils.Singleton.cryptography
|
||||||
@ -31,7 +32,8 @@ import com.nhaarman.mockito_kotlin.mock
|
|||||||
import org.hamcrest.Matchers.`is`
|
import org.hamcrest.Matchers.`is`
|
||||||
import org.hamcrest.Matchers.notNullValue
|
import org.hamcrest.Matchers.notNullValue
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -56,20 +58,22 @@ class NetworkHandlerTest {
|
|||||||
private lateinit var peerNetworkHandler: NetworkHandler
|
private lateinit var peerNetworkHandler: NetworkHandler
|
||||||
private lateinit var nodeNetworkHandler: NetworkHandler
|
private lateinit var nodeNetworkHandler: NetworkHandler
|
||||||
|
|
||||||
@JvmField @Rule val timeout: TestRule = DisableOnDebug(Timeout.seconds(60))
|
@JvmField
|
||||||
|
@Rule
|
||||||
|
val timeout: TestRule = DisableOnDebug(Timeout.seconds(60))
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
peerInventory = TestInventory()
|
peerInventory = TestInventory()
|
||||||
peerNetworkHandler = NioNetworkHandler()
|
peerNetworkHandler = NioNetworkHandler()
|
||||||
peer = BitmessageContext(
|
peer = BitmessageContext.build {
|
||||||
cryptography = BouncyCryptography(),
|
cryptography = BouncyCryptography()
|
||||||
inventory = peerInventory,
|
inventory = peerInventory
|
||||||
nodeRegistry = TestNodeRegistry(),
|
nodeRegistry = TestNodeRegistry()
|
||||||
networkHandler = peerNetworkHandler,
|
networkHandler = peerNetworkHandler
|
||||||
addressRepository = mock<AddressRepository>(),
|
addressRepo = mock()
|
||||||
messageRepository = mock<MessageRepository>(),
|
messageRepo = mock()
|
||||||
proofOfWorkRepository = mock<ProofOfWorkRepository>(),
|
proofOfWorkRepo = mock()
|
||||||
customCommandHandler = object : CustomCommandHandler {
|
customCommandHandler = object : CustomCommandHandler {
|
||||||
override fun handle(request: CustomMessage): MessagePayload? {
|
override fun handle(request: CustomMessage): MessagePayload? {
|
||||||
val data = request.getData()
|
val data = request.getData()
|
||||||
@ -83,23 +87,23 @@ class NetworkHandlerTest {
|
|||||||
}
|
}
|
||||||
return CustomMessage("test response", request.getData())
|
return CustomMessage("test response", request.getData())
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
listener = mock<BitmessageContext.Listener>(),
|
listener = mock()
|
||||||
port = peerAddress.port
|
preferences.port = peerAddress.port
|
||||||
)
|
}
|
||||||
peer.startup()
|
peer.startup()
|
||||||
Thread.sleep(100)
|
Thread.sleep(100)
|
||||||
|
|
||||||
nodeInventory = TestInventory()
|
nodeInventory = TestInventory()
|
||||||
nodeNetworkHandler = NioNetworkHandler()
|
nodeNetworkHandler = NioNetworkHandler()
|
||||||
node = BitmessageContext(
|
node = BitmessageContext.build {
|
||||||
cryptography = BouncyCryptography(),
|
cryptography = BouncyCryptography()
|
||||||
inventory = nodeInventory,
|
inventory = nodeInventory
|
||||||
nodeRegistry = TestNodeRegistry(peerAddress),
|
nodeRegistry = TestNodeRegistry(peerAddress)
|
||||||
networkHandler = nodeNetworkHandler,
|
networkHandler = nodeNetworkHandler
|
||||||
addressRepository = mock<AddressRepository>(),
|
addressRepo = mock()
|
||||||
messageRepository = mock<MessageRepository>(),
|
messageRepo = mock()
|
||||||
proofOfWorkRepository = mock<ProofOfWorkRepository>(),
|
proofOfWorkRepo = mock()
|
||||||
customCommandHandler = object : CustomCommandHandler {
|
customCommandHandler = object : CustomCommandHandler {
|
||||||
override fun handle(request: CustomMessage): MessagePayload? {
|
override fun handle(request: CustomMessage): MessagePayload? {
|
||||||
val data = request.getData()
|
val data = request.getData()
|
||||||
@ -113,10 +117,10 @@ class NetworkHandlerTest {
|
|||||||
}
|
}
|
||||||
return CustomMessage("test response", request.getData())
|
return CustomMessage("test response", request.getData())
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
listener = mock<BitmessageContext.Listener>(),
|
listener = mock()
|
||||||
port = 6002
|
preferences.port = 6002
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -49,16 +49,16 @@ class WifExporterTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
ctx = BitmessageContext.Builder()
|
ctx = BitmessageContext.build {
|
||||||
.cryptography(BouncyCryptography())
|
cryptography = BouncyCryptography()
|
||||||
.networkHandler(mock())
|
networkHandler = mock()
|
||||||
.inventory(mock())
|
inventory = mock()
|
||||||
.messageRepo(mock())
|
messageRepo = mock()
|
||||||
.powRepo(mock())
|
proofOfWorkRepo = mock()
|
||||||
.nodeRegistry(mock())
|
nodeRegistry = mock()
|
||||||
.addressRepo(repo)
|
addressRepo = repo
|
||||||
.listener { }
|
listener {}
|
||||||
.build()
|
}
|
||||||
importer = WifImporter(ctx, javaClass.classLoader.getResourceAsStream("nuked.dat"))
|
importer = WifImporter(ctx, javaClass.classLoader.getResourceAsStream("nuked.dat"))
|
||||||
assertEquals(81, importer.getIdentities().size)
|
assertEquals(81, importer.getIdentities().size)
|
||||||
exporter = WifExporter(ctx)
|
exporter = WifExporter(ctx)
|
||||||
|
@ -50,16 +50,16 @@ class WifImporterTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
ctx = BitmessageContext.Builder()
|
ctx = BitmessageContext.build {
|
||||||
.cryptography(BouncyCryptography())
|
cryptography = BouncyCryptography()
|
||||||
.networkHandler(mock())
|
networkHandler = mock()
|
||||||
.inventory(mock())
|
inventory = mock()
|
||||||
.messageRepo(mock())
|
messageRepo = mock()
|
||||||
.powRepo(mock())
|
proofOfWorkRepo = mock()
|
||||||
.nodeRegistry(mock())
|
nodeRegistry = mock()
|
||||||
.addressRepo(repo)
|
addressRepo = repo
|
||||||
.listener { }
|
listener { }
|
||||||
.build()
|
}
|
||||||
importer = WifImporter(ctx, javaClass.classLoader.getResourceAsStream("nuked.dat"))
|
importer = WifImporter(ctx, javaClass.classLoader.getResourceAsStream("nuked.dat"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user