diff --git a/docs/source/hello-world-state.rst b/docs/source/hello-world-state.rst index fb078f0780..e4b3e5f488 100644 --- a/docs/source/hello-world-state.rst +++ b/docs/source/hello-world-state.rst @@ -24,17 +24,6 @@ interface is defined as follows: val participants: List } -The first thing you'll probably notice about this interface declaration is that its not written in Java or another -common language. The core Corda platform, including the interface declaration above, is entirely written in Kotlin. - -Learning some Kotlin will be very useful for understanding how Corda works internally, and usually only takes an -experienced Java developer a day or so to pick up. However, learning Kotlin isn't essential. Because Kotlin code -compiles down to JVM bytecode, CorDapps written in other JVM languages can interoperate with Corda. - -If you do want to dive into Kotlin, there's an official -`getting started guide `_, and a series of -`Kotlin Koans `_. - We can see that the ``ContractState`` interface has a single field, ``participants``. ``participants`` is a list of the entities for which this state is relevant. diff --git a/node/src/integration-test/kotlin/net/corda/node/amqp/AMQPBridgeTest.kt b/node/src/integration-test/kotlin/net/corda/node/amqp/AMQPBridgeTest.kt index 074429b628..ed490f5323 100644 --- a/node/src/integration-test/kotlin/net/corda/node/amqp/AMQPBridgeTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/amqp/AMQPBridgeTest.kt @@ -258,7 +258,7 @@ class AMQPBridgeTest { doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration } artemisConfig.configureWithDevSSLCertificate() - val artemisServer = ArtemisMessagingServer(artemisConfig, artemisPort, MAX_MESSAGE_SIZE) + val artemisServer = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", artemisPort), MAX_MESSAGE_SIZE) val artemisClient = ArtemisMessagingClient(artemisConfig, artemisAddress, MAX_MESSAGE_SIZE, confirmationWindowSize = 10 * 1024) artemisServer.start() artemisClient.start() diff --git a/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt b/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt index f16fe5180e..ca9fb3daa6 100644 --- a/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt @@ -236,7 +236,7 @@ class ProtonWrapperTests { } artemisConfig.configureWithDevSSLCertificate() - val server = ArtemisMessagingServer(artemisConfig, artemisPort, MAX_MESSAGE_SIZE) + val server = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", artemisPort), MAX_MESSAGE_SIZE) val client = ArtemisMessagingClient(artemisConfig, NetworkHostAndPort("localhost", artemisPort), MAX_MESSAGE_SIZE) server.start() client.start() diff --git a/node/src/main/kotlin/net/corda/node/internal/Node.kt b/node/src/main/kotlin/net/corda/node/internal/Node.kt index 50d2b1db77..fe6da562d7 100644 --- a/node/src/main/kotlin/net/corda/node/internal/Node.kt +++ b/node/src/main/kotlin/net/corda/node/internal/Node.kt @@ -33,8 +33,8 @@ import net.corda.node.VersionInfo import net.corda.node.internal.artemis.ArtemisBroker import net.corda.node.internal.artemis.BrokerAddresses import net.corda.node.internal.cordapp.CordappLoader -import net.corda.node.internal.security.RPCSecurityManagerWithAdditionalUser import net.corda.node.internal.security.RPCSecurityManagerImpl +import net.corda.node.internal.security.RPCSecurityManagerWithAdditionalUser import net.corda.node.serialization.KryoServerSerializationScheme import net.corda.node.services.api.NodePropertiesStore import net.corda.node.services.api.SchemaService @@ -171,14 +171,18 @@ open class Node(configuration: NodeConfiguration, networkParameters: NetworkParameters): MessagingService { // Construct security manager reading users data either from the 'security' config section // if present or from rpcUsers list if the former is missing from config. - val securityManagerConfig = configuration.security?.authService ?: - SecurityConfiguration.AuthService.fromUsers(configuration.rpcUsers) + val securityManagerConfig = configuration.security?.authService ?: SecurityConfiguration.AuthService.fromUsers(configuration.rpcUsers) securityManager = with(RPCSecurityManagerImpl(securityManagerConfig)) { if (configuration.shouldInitCrashShell()) RPCSecurityManagerWithAdditionalUser(this, localShellUser()) else this } - val serverAddress = configuration.messagingServerAddress ?: makeLocalMessageBroker(networkParameters) + if (!configuration.messagingServerExternal) { + val brokerBindAddress = configuration.messagingServerAddress ?: NetworkHostAndPort("0.0.0.0", configuration.p2pAddress.port) + messageBroker = ArtemisMessagingServer(configuration, brokerBindAddress, MAX_FILE_SIZE) + } + + val serverAddress = configuration.messagingServerAddress ?: NetworkHostAndPort("localhost", configuration.p2pAddress.port) val rpcServerAddresses = if (configuration.rpcOptions.standAloneBroker) { BrokerAddresses(configuration.rpcOptions.address!!, configuration.rpcOptions.adminAddress) } else { @@ -200,7 +204,7 @@ open class Node(configuration: NodeConfiguration, printBasicNodeInfo("RPC admin connection address", it.admin.toString()) } verifierMessagingClient = when (configuration.verifierType) { - VerifierType.OutOfProcess -> throw IllegalArgumentException("OutOfProcess verifier not supported") //VerifierMessagingClient(configuration, serverAddress, services.monitoringService.metrics, /*networkParameters.maxMessageSize*/MAX_FILE_SIZE) + VerifierType.OutOfProcess -> throw IllegalArgumentException("OutOfProcess verifier not supported") //VerifierMessagingClient(configuration, serverAddress, services.monitoringService.metrics, /*networkParameters.maxMessageSize*/MAX_FILE_SIZE) VerifierType.InMemory -> null } require(info.legalIdentities.size in 1..2) { "Currently nodes must have a primary address and optionally one serviced address" } @@ -239,13 +243,6 @@ open class Node(configuration: NodeConfiguration, } } - private fun makeLocalMessageBroker(networkParameters: NetworkParameters): NetworkHostAndPort { - with(configuration) { - messageBroker = ArtemisMessagingServer(this, p2pAddress.port, /*networkParameters.maxMessageSize*/MAX_FILE_SIZE) - return NetworkHostAndPort("localhost", p2pAddress.port) - } - } - override fun myAddresses(): List = listOf(getAdvertisedAddress()) private fun getAdvertisedAddress(): NetworkHostAndPort { diff --git a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt index 7f03c31d4c..fe1ab5947c 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt @@ -52,6 +52,7 @@ interface NodeConfiguration : NodeSSLConfiguration { val p2pAddress: NetworkHostAndPort val rpcOptions: NodeRpcOptions val messagingServerAddress: NetworkHostAndPort? + val messagingServerExternal: Boolean val enterpriseConfiguration: EnterpriseConfiguration // TODO Move into DevModeOptions val useTestClock: Boolean get() = false @@ -163,6 +164,7 @@ data class NodeConfigurationImpl( // TODO This field is slightly redundant as p2pAddress is sufficient to hold the address of the node's MQ broker. // Instead this should be a Boolean indicating whether that broker is an internal one started by the node or an external one override val messagingServerAddress: NetworkHostAndPort?, + override val messagingServerExternal: Boolean = (messagingServerAddress != null), override val enterpriseConfiguration: EnterpriseConfiguration, override val notary: NotaryConfig?, override val certificateChainCheckPolicies: List, diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt index e21e16092c..f26fa64557 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt @@ -18,7 +18,6 @@ import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.contextLogger import net.corda.core.utilities.debug -import net.corda.node.internal.Node import net.corda.node.internal.artemis.ArtemisBroker import net.corda.node.internal.artemis.BrokerAddresses import net.corda.node.internal.artemis.CertificateChainCheckPolicy @@ -79,11 +78,12 @@ import javax.security.auth.spi.LoginModule */ @ThreadSafe class ArtemisMessagingServer(private val config: NodeConfiguration, - private val p2pPort: Int, + private val messagingServerAddress: NetworkHostAndPort, val maxMessageSize: Int) : ArtemisBroker, SingletonSerializeAsToken() { companion object { private val log = contextLogger() } + private class InnerState { var running = false } @@ -129,7 +129,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, } // Config driven switch between legacy CORE bridges and the newer AMQP protocol bridges. activeMQServer.start() - log.info("P2P messaging server listening on port $p2pPort") + log.info("P2P messaging server listening on $messagingServerAddress") } private fun createArtemisConfig() = SecureArtemisConfiguration().apply { @@ -140,7 +140,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, val connectionDirection = ConnectionDirection.Inbound( acceptorFactoryClassName = NettyAcceptorFactory::class.java.name ) - val acceptors = mutableSetOf(createTcpTransport(connectionDirection, "0.0.0.0", p2pPort)) + val acceptors = mutableSetOf(createTcpTransport(connectionDirection, messagingServerAddress.host, messagingServerAddress.port)) acceptorConfigurations = acceptors // Enable built in message deduplication. Note we still have to do our own as the delayed commits // and our own definition of commit mean that the built in deduplication cannot remove all duplicates. diff --git a/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt b/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt index 1255d15b47..ba1052c63f 100644 --- a/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt @@ -17,6 +17,7 @@ import net.corda.tools.shell.SSHDConfiguration import net.corda.nodeapi.internal.persistence.CordaPersistence.DataSourceConfigTag import net.corda.testing.core.ALICE_NAME import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties +import net.corda.tools.shell.SSHDConfiguration import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.Test import java.nio.file.Paths diff --git a/node/src/test/kotlin/net/corda/node/services/messaging/ArtemisMessagingTest.kt b/node/src/test/kotlin/net/corda/node/services/messaging/ArtemisMessagingTest.kt index b78f6a603c..8b2a56dc5e 100644 --- a/node/src/test/kotlin/net/corda/node/services/messaging/ArtemisMessagingTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/messaging/ArtemisMessagingTest.kt @@ -363,7 +363,7 @@ class ArtemisMessagingTest { } private fun createMessagingServer(local: Int = serverPort, maxMessageSize: Int = MAX_MESSAGE_SIZE): ArtemisMessagingServer { - return ArtemisMessagingServer(config, local, maxMessageSize).apply { + return ArtemisMessagingServer(config, NetworkHostAndPort("0.0.0.0", local), maxMessageSize).apply { config.configureWithDevSSLCertificate() messagingServer = this }