Migrated networking and fixed networking tests
This commit is contained in:
@ -78,7 +78,7 @@ class BitmessageContext(
|
||||
port: Int = 8444,
|
||||
connectionTTL: Long = 30 * MINUTE,
|
||||
connectionLimit: Int = 150,
|
||||
sendPubkeyOnIdentityCreation: Boolean,
|
||||
sendPubkeyOnIdentityCreation: Boolean = true,
|
||||
doMissingProofOfWorkDelayInSeconds: Int = 30
|
||||
) {
|
||||
|
||||
@ -333,7 +333,7 @@ class BitmessageContext(
|
||||
|
||||
fun status(): Property {
|
||||
return Property("status",
|
||||
internals.networkHandler.networkStatus,
|
||||
internals.networkHandler.getNetworkStatus(),
|
||||
Property("unacknowledged", internals.messageRepository.findMessagesToResend().size)
|
||||
)
|
||||
}
|
||||
|
@ -32,8 +32,12 @@ import java.util.*
|
||||
internal open class DefaultMessageListener(
|
||||
private val labeler: Labeler,
|
||||
private val listener: BitmessageContext.Listener
|
||||
) : NetworkHandler.MessageListener {
|
||||
private var ctx by InternalContext.lateinit
|
||||
) : NetworkHandler.MessageListener, InternalContext.ContextHolder {
|
||||
private lateinit var ctx: InternalContext
|
||||
|
||||
override fun setContext(context: InternalContext) {
|
||||
ctx = context
|
||||
}
|
||||
|
||||
override fun receive(objectMessage: ObjectMessage) {
|
||||
val payload = objectMessage.payload
|
||||
@ -43,7 +47,7 @@ internal open class DefaultMessageListener(
|
||||
receive(objectMessage, payload as GetPubkey)
|
||||
}
|
||||
ObjectType.PUBKEY -> {
|
||||
receive(objectMessage, payload as Pubkey)
|
||||
receive(payload as Pubkey)
|
||||
}
|
||||
ObjectType.MSG -> {
|
||||
receive(objectMessage, payload as Msg)
|
||||
@ -56,9 +60,6 @@ internal open class DefaultMessageListener(
|
||||
receive(payload)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw IllegalArgumentException("Unknown payload type " + payload.type!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +72,7 @@ internal open class DefaultMessageListener(
|
||||
}
|
||||
}
|
||||
|
||||
protected fun receive(objectMessage: ObjectMessage, pubkey: Pubkey) {
|
||||
protected fun receive(pubkey: Pubkey) {
|
||||
try {
|
||||
if (pubkey is V4Pubkey) {
|
||||
ctx.addressRepository.findContact(pubkey.tag)?.let {
|
||||
|
@ -28,7 +28,6 @@ import ch.dissem.bitmessage.utils.UnixTime
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* The internal context should normally only be used for port implementations. If you need it in your client
|
||||
@ -67,8 +66,6 @@ class InternalContext(
|
||||
get() = _streams.toLongArray()
|
||||
|
||||
init {
|
||||
lateinit.instance = this
|
||||
lateinit = ContextDelegate()
|
||||
Singleton.initialize(cryptography)
|
||||
|
||||
// TODO: streams of new identities and subscriptions should also be added. This works only after a restart.
|
||||
@ -218,19 +215,10 @@ class InternalContext(
|
||||
fun setContext(context: InternalContext)
|
||||
}
|
||||
|
||||
class ContextDelegate {
|
||||
internal lateinit var instance: InternalContext
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>) = instance
|
||||
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: InternalContext) {}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = LoggerFactory.getLogger(InternalContext::class.java)
|
||||
|
||||
@JvmField val NETWORK_NONCE_TRIALS_PER_BYTE: Long = 1000
|
||||
@JvmField val NETWORK_EXTRA_BYTES: Long = 1000
|
||||
|
||||
var lateinit = ContextDelegate()
|
||||
private set
|
||||
}
|
||||
}
|
||||
|
@ -22,21 +22,23 @@ import ch.dissem.bitmessage.entity.*
|
||||
import ch.dissem.bitmessage.entity.payload.Msg
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkEngine
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkRepository.Item
|
||||
import ch.dissem.bitmessage.utils.Strings
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
class ProofOfWorkService : ProofOfWorkEngine.Callback {
|
||||
class ProofOfWorkService : ProofOfWorkEngine.Callback, InternalContext.ContextHolder {
|
||||
|
||||
private val ctx by InternalContext.lateinit
|
||||
private lateinit var ctx: InternalContext
|
||||
private val cryptography by lazy { ctx.cryptography }
|
||||
private val powRepo by lazy { ctx.proofOfWorkRepository }
|
||||
private val messageRepo by lazy { ctx.messageRepository }
|
||||
|
||||
override fun setContext(context: InternalContext) {
|
||||
ctx = context
|
||||
}
|
||||
|
||||
fun doMissingProofOfWork(delayInMilliseconds: Long) {
|
||||
val items = powRepo.getItems()
|
||||
if (items.isEmpty()) return
|
||||
|
@ -23,10 +23,28 @@ import ch.dissem.bitmessage.utils.UnixTime
|
||||
import java.io.OutputStream
|
||||
import java.net.InetAddress
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Socket
|
||||
import java.net.SocketAddress
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.*
|
||||
|
||||
fun ip6(inetAddress: InetAddress): ByteArray {
|
||||
val address = inetAddress.address
|
||||
when (address.size) {
|
||||
16 -> {
|
||||
return address
|
||||
}
|
||||
4 -> {
|
||||
val ip6 = ByteArray(16)
|
||||
ip6[10] = 0xff.toByte()
|
||||
ip6[11] = 0xff.toByte()
|
||||
System.arraycopy(address, 0, ip6, 12, 4)
|
||||
return ip6
|
||||
}
|
||||
else -> throw IllegalArgumentException("Weird address " + inetAddress)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node's address. It's written in IPv6 format.
|
||||
*/
|
||||
@ -51,6 +69,9 @@ data class NetworkAddress(
|
||||
val port: Int
|
||||
) : Streamable {
|
||||
|
||||
constructor(time: Long, stream: Long, services: Long = 1, socket: Socket)
|
||||
: this(time, stream, services, ip6(socket.inetAddress), socket.port)
|
||||
|
||||
fun provides(service: Version.Service?): Boolean = service?.isEnabled(services) ?: false
|
||||
|
||||
fun toInetAddress(): InetAddress {
|
||||
@ -125,18 +146,7 @@ data class NetworkAddress(
|
||||
}
|
||||
|
||||
fun ip(inetAddress: InetAddress): Builder {
|
||||
val addr = inetAddress.address
|
||||
if (addr.size == 16) {
|
||||
this.ipv6 = addr
|
||||
} else if (addr.size == 4) {
|
||||
val ipv6 = ByteArray(16)
|
||||
ipv6[10] = 0xff.toByte()
|
||||
ipv6[11] = 0xff.toByte()
|
||||
System.arraycopy(addr, 0, ipv6, 12, 4)
|
||||
this.ipv6 = ipv6
|
||||
} else {
|
||||
throw IllegalArgumentException("Weird address " + inetAddress)
|
||||
}
|
||||
ipv6 = ip6(inetAddress)
|
||||
return this
|
||||
}
|
||||
|
||||
@ -165,9 +175,8 @@ data class NetworkAddress(
|
||||
|
||||
fun address(address: SocketAddress): Builder {
|
||||
if (address is InetSocketAddress) {
|
||||
val inetAddress = address
|
||||
ip(inetAddress.address)
|
||||
port(inetAddress.port)
|
||||
ip(address.address)
|
||||
port(address.port)
|
||||
} else {
|
||||
throw IllegalArgumentException("Unknown type of address: " + address.javaClass)
|
||||
}
|
||||
@ -180,4 +189,8 @@ data class NetworkAddress(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField val ANY = NetworkAddress(time = 0, stream = 0, services = 0, IPv6 = ByteArray(16), port = 0)
|
||||
}
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ object BufferPool {
|
||||
|
||||
@Synchronized fun allocate(capacity: Int): ByteBuffer {
|
||||
val targetSize = getTargetSize(capacity)
|
||||
val pool = pools[targetSize]
|
||||
if (pool == null || pool.isEmpty()) {
|
||||
LOG.trace("Creating new buffer of size " + targetSize!!)
|
||||
val pool = pools[targetSize] ?: throw IllegalStateException("No pool for size $targetSize available")
|
||||
if (pool.isEmpty()) {
|
||||
LOG.trace("Creating new buffer of size $targetSize")
|
||||
return ByteBuffer.allocate(targetSize)
|
||||
} else {
|
||||
return pool.pop()
|
||||
@ -64,16 +64,14 @@ object BufferPool {
|
||||
|
||||
@Synchronized fun deallocate(buffer: ByteBuffer) {
|
||||
buffer.clear()
|
||||
val pool = pools[buffer.capacity()]
|
||||
pool?.push(buffer) ?: throw IllegalArgumentException("Illegal buffer capacity " + buffer.capacity() +
|
||||
" one of " + pools.keys + " expected.")
|
||||
val pool = pools[buffer.capacity()] ?: throw IllegalArgumentException("Illegal buffer capacity ${buffer.capacity()} one of ${pools.keys} expected.")
|
||||
pool.push(buffer)
|
||||
}
|
||||
|
||||
private fun getTargetSize(capacity: Int): Int? {
|
||||
private fun getTargetSize(capacity: Int): Int {
|
||||
for (size in pools.keys) {
|
||||
if (size >= capacity) return size
|
||||
}
|
||||
throw IllegalArgumentException("Requested capacity too large: " +
|
||||
"requested=" + capacity + "; max=" + MAX_PAYLOAD_SIZE)
|
||||
throw IllegalArgumentException("Requested capacity too large: requested=$capacity; max=$MAX_PAYLOAD_SIZE")
|
||||
}
|
||||
}
|
||||
|
@ -40,23 +40,22 @@ class V3MessageReader {
|
||||
|
||||
private val messages = LinkedList<NetworkMessage>()
|
||||
|
||||
val activeBuffer: ByteBuffer
|
||||
get() {
|
||||
if (state != null && state != ReaderState.DATA) {
|
||||
if (headerBuffer == null) {
|
||||
headerBuffer = BufferPool.allocateHeaderBuffer()
|
||||
}
|
||||
fun getActiveBuffer(): ByteBuffer {
|
||||
if (state != null && state != ReaderState.DATA) {
|
||||
if (headerBuffer == null) {
|
||||
headerBuffer = BufferPool.allocateHeaderBuffer()
|
||||
}
|
||||
return if (state == ReaderState.DATA)
|
||||
dataBuffer ?: throw IllegalStateException("data buffer is null")
|
||||
else
|
||||
headerBuffer ?: throw IllegalStateException("header buffer is null")
|
||||
}
|
||||
return if (state == ReaderState.DATA)
|
||||
dataBuffer ?: throw IllegalStateException("data buffer is null")
|
||||
else
|
||||
headerBuffer ?: throw IllegalStateException("header buffer is null")
|
||||
}
|
||||
|
||||
fun update() {
|
||||
if (state != ReaderState.DATA) {
|
||||
activeBuffer
|
||||
headerBuffer!!.flip()
|
||||
getActiveBuffer() // in order to initialize
|
||||
headerBuffer?.flip() ?: throw IllegalStateException("header buffer is null")
|
||||
}
|
||||
when (state) {
|
||||
V3MessageReader.ReaderState.MAGIC -> magic(headerBuffer ?: throw IllegalStateException("header buffer is null"))
|
||||
@ -93,12 +92,12 @@ class V3MessageReader {
|
||||
BufferPool.deallocate(headerBuffer)
|
||||
val dataBuffer = BufferPool.allocate(length)
|
||||
this.dataBuffer = dataBuffer
|
||||
dataBuffer.clear()
|
||||
dataBuffer.limit(length)
|
||||
data(dataBuffer)
|
||||
}
|
||||
|
||||
private fun data(dataBuffer: ByteBuffer) {
|
||||
dataBuffer.clear()
|
||||
dataBuffer.limit(length)
|
||||
if (dataBuffer.position() < length) {
|
||||
return
|
||||
} else {
|
||||
@ -126,7 +125,7 @@ class V3MessageReader {
|
||||
}
|
||||
}
|
||||
|
||||
fun getMessages(): List<NetworkMessage> {
|
||||
fun getMessages(): MutableList<NetworkMessage> {
|
||||
return messages
|
||||
}
|
||||
|
||||
|
@ -36,13 +36,17 @@ import javax.crypto.spec.SecretKeySpec
|
||||
/**
|
||||
* Implements everything that isn't directly dependent on either Spongy- or Bouncycastle.
|
||||
*/
|
||||
abstract class AbstractCryptography protected constructor(@JvmField protected val provider: Provider) : Cryptography {
|
||||
private val context by InternalContext.lateinit
|
||||
abstract class AbstractCryptography protected constructor(@JvmField protected val provider: Provider) : Cryptography, InternalContext.ContextHolder {
|
||||
private lateinit var ctx: InternalContext
|
||||
|
||||
@JvmField protected val ALGORITHM_ECDSA = "ECDSA"
|
||||
@JvmField protected val ALGORITHM_ECDSA_SHA1 = "SHA1withECDSA"
|
||||
@JvmField protected val ALGORITHM_EVP_SHA256 = "SHA256withECDSA"
|
||||
|
||||
override fun setContext(context: InternalContext) {
|
||||
ctx = context
|
||||
}
|
||||
|
||||
override fun sha512(data: ByteArray, offset: Int, length: Int): ByteArray {
|
||||
val mda = md("SHA-512")
|
||||
mda.update(data, offset, length)
|
||||
@ -95,7 +99,7 @@ abstract class AbstractCryptography protected constructor(@JvmField protected va
|
||||
val target = getProofOfWorkTarget(objectMessage,
|
||||
max(nonceTrialsPerByte, NETWORK_NONCE_TRIALS_PER_BYTE), max(extraBytes, NETWORK_EXTRA_BYTES))
|
||||
|
||||
context.proofOfWorkEngine.calculateNonce(initialHash, target, callback)
|
||||
ctx.proofOfWorkEngine.calculateNonce(initialHash, target, callback)
|
||||
}
|
||||
|
||||
@Throws(InsufficientProofOfWorkException::class)
|
||||
|
@ -27,8 +27,12 @@ import ch.dissem.bitmessage.utils.Strings
|
||||
import ch.dissem.bitmessage.utils.UnixTime
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractMessageRepository : MessageRepository {
|
||||
protected var ctx by InternalContext.lateinit
|
||||
abstract class AbstractMessageRepository : MessageRepository, InternalContext.ContextHolder {
|
||||
protected lateinit var ctx: InternalContext
|
||||
|
||||
override fun setContext(context: InternalContext) {
|
||||
ctx = context
|
||||
}
|
||||
|
||||
protected fun saveContactIfNecessary(contact: BitmessageAddress?) {
|
||||
contact?.let {
|
||||
|
@ -22,8 +22,12 @@ import ch.dissem.bitmessage.entity.Plaintext.Status.*
|
||||
import ch.dissem.bitmessage.entity.Plaintext.Type.BROADCAST
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
|
||||
open class DefaultLabeler : Labeler {
|
||||
private var ctx by InternalContext.lateinit
|
||||
open class DefaultLabeler : Labeler, InternalContext.ContextHolder {
|
||||
private lateinit var ctx: InternalContext
|
||||
|
||||
override fun setContext(context: InternalContext) {
|
||||
ctx = context
|
||||
}
|
||||
|
||||
override fun setLabels(msg: Plaintext) {
|
||||
msg.status = RECEIVED
|
||||
|
@ -73,9 +73,9 @@ interface NetworkHandler {
|
||||
|
||||
* @param inventoryVectors of the objects to be requested
|
||||
*/
|
||||
fun request(inventoryVectors: Collection<InventoryVector>)
|
||||
fun request(inventoryVectors: MutableCollection<InventoryVector>)
|
||||
|
||||
val networkStatus: Property
|
||||
fun getNetworkStatus(): Property
|
||||
|
||||
val isRunning: Boolean
|
||||
|
||||
|
@ -30,5 +30,5 @@ interface NodeRegistry {
|
||||
|
||||
fun getKnownAddresses(limit: Int, vararg streams: Long): List<NetworkAddress>
|
||||
|
||||
fun offerAddresses(addresses: List<NetworkAddress>)
|
||||
fun offerAddresses(nodes: List<NetworkAddress>)
|
||||
}
|
||||
|
Reference in New Issue
Block a user