Retire HostAndPort (#962)

* Don't attempt to parse a resolved InetSocketAddress toString
* A mock node isn't reachable via an address
This commit is contained in:
Andrzej Cichocki
2017-07-07 15:11:07 +01:00
committed by GitHub
parent 7822118835
commit cefa14507a
61 changed files with 290 additions and 266 deletions

View File

@ -1,11 +1,11 @@
package net.corda.core.node
import com.google.common.net.HostAndPort
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.NetworkHostAndPort
/**
* Information for an advertised service including the service specific identity information.
@ -19,7 +19,7 @@ data class ServiceEntry(val info: ServiceInfo, val identity: PartyAndCertificate
*/
// TODO We currently don't support multi-IP/multi-identity nodes, we only left slots in the data structures.
@CordaSerializable
data class NodeInfo(val addresses: List<HostAndPort>,
data class NodeInfo(val addresses: List<NetworkHostAndPort>,
val legalIdentityAndCert: PartyAndCertificate, //TODO This field will be removed in future PR which gets rid of services.
val legalIdentitiesAndCerts: Set<PartyAndCertificate>,
val platformVersion: Int,

View File

@ -0,0 +1,37 @@
package net.corda.core.utilities
import java.net.URI
/**
* Tuple of host and port. Use [parseNetworkHostAndPort] on untrusted data.
* @param host a hostname or IP address. IPv6 addresses must not be enclosed in square brackets.
* @param port a valid port number.
*/
data class NetworkHostAndPort(val host: String, val port: Int) {
companion object {
internal val invalidPortFormat = "Invalid port: %s"
internal val unparseableAddressFormat = "Unparseable address: %s"
internal val missingPortFormat = "Missing port: %s"
}
init {
require(port in (0..0xffff)) { invalidPortFormat.format(port) }
}
override fun toString() = if (':' in host) "[$host]:$port" else "$host:$port"
}
/**
* Parses a string of the form host:port into a [NetworkHostAndPort].
* The host part may be a hostname or IP address. If it's an IPv6 address, it must be enclosed in square brackets.
* Note this does not parse the toString of a resolved [java.net.InetSocketAddress], which is of a host/IP:port form.
* @throws IllegalArgumentException if the port is missing, the string is garbage, or the NetworkHostAndPort constructor rejected the parsed parts.
*/
fun String.parseNetworkHostAndPort() = run {
val uri = URI(null, this, null, null, null)
require(uri.host != null) { NetworkHostAndPort.unparseableAddressFormat.format(this) }
require(uri.port != -1) { NetworkHostAndPort.missingPortFormat.format(this) }
NetworkHostAndPort(bracketedHost.matchEntire(uri.host)?.groupValues?.get(1) ?: uri.host, uri.port)
}
private val bracketedHost = "\\[(.*)]".toRegex()

View File

@ -1,7 +1,5 @@
package net.corda.core.utilities
package net.corda.core
import net.corda.core.indexOfOrThrow
import net.corda.core.noneOrSingle
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

View File

@ -0,0 +1,60 @@
package net.corda.core.utilities
import org.junit.Test
import kotlin.test.assertEquals
import org.assertj.core.api.Assertions.assertThatThrownBy
class NetworkHostAndPortTest {
/**
* If a host isn't known-good it should go via the parser, which does some validation.
*/
@Test
fun `constructor is not fussy about host`() {
assertEquals("", NetworkHostAndPort("", 1234).host)
assertEquals("x", NetworkHostAndPort("x", 1234).host)
assertEquals("500", NetworkHostAndPort("500", 1234).host)
assertEquals(" yo yo\t", NetworkHostAndPort(" yo yo\t", 1234).host)
assertEquals("[::1]", NetworkHostAndPort("[::1]", 1234).host) // Don't do this.
}
@Test
fun `constructor requires a valid port`() {
assertEquals(0, NetworkHostAndPort("example.com", 0).port)
assertEquals(65535, NetworkHostAndPort("example.com", 65535).port)
listOf(65536, -1).forEach {
assertThatThrownBy {
NetworkHostAndPort("example.com", it)
}.isInstanceOf(IllegalArgumentException::class.java).hasMessage(NetworkHostAndPort.invalidPortFormat.format(it))
}
}
@Test
fun `toString works`() {
assertEquals("example.com:1234", NetworkHostAndPort("example.com", 1234).toString())
assertEquals("example.com:65535", NetworkHostAndPort("example.com", 65535).toString())
assertEquals("1.2.3.4:1234", NetworkHostAndPort("1.2.3.4", 1234).toString())
assertEquals("[::1]:1234", NetworkHostAndPort("::1", 1234).toString())
// Brackets perhaps not necessary in unabbreviated case, but URI seems to need them for parsing:
assertEquals("[0:0:0:0:0:0:0:1]:1234", NetworkHostAndPort("0:0:0:0:0:0:0:1", 1234).toString())
assertEquals(":1234", NetworkHostAndPort("", 1234).toString()) // URI won't parse this.
}
@Test
fun `parseNetworkHostAndPort works`() {
assertEquals(NetworkHostAndPort("example.com", 1234), "example.com:1234".parseNetworkHostAndPort())
assertEquals(NetworkHostAndPort("example.com", 65535), "example.com:65535".parseNetworkHostAndPort())
assertEquals(NetworkHostAndPort("1.2.3.4", 1234), "1.2.3.4:1234".parseNetworkHostAndPort())
assertEquals(NetworkHostAndPort("::1", 1234), "[::1]:1234".parseNetworkHostAndPort())
assertEquals(NetworkHostAndPort("0:0:0:0:0:0:0:1", 1234), "[0:0:0:0:0:0:0:1]:1234".parseNetworkHostAndPort())
listOf("0:0:0:0:0:0:0:1:1234", ":1234", "example.com:-1").forEach {
assertThatThrownBy {
it.parseNetworkHostAndPort()
}.isInstanceOf(IllegalArgumentException::class.java).hasMessage(NetworkHostAndPort.unparseableAddressFormat.format(it))
}
listOf("example.com:", "example.com").forEach {
assertThatThrownBy {
it.parseNetworkHostAndPort()
}.isInstanceOf(IllegalArgumentException::class.java).hasMessage(NetworkHostAndPort.missingPortFormat.format(it))
}
}
}