Migrated networking and fixed networking tests

This commit is contained in:
2017-06-25 20:06:17 +02:00
parent 894e0ff724
commit 322bddcc4f
49 changed files with 2081 additions and 2936 deletions

View File

@ -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)
)
}

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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

View File

@ -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)
}
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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>)
}