Merge branch 'master' into os-merge-244167d

This commit is contained in:
Shams Asari 2018-07-05 15:47:09 +01:00
commit c4d0a62ceb
16 changed files with 227 additions and 67 deletions

View File

@ -76,7 +76,7 @@ buildscript {
ext.selenium_version = '3.8.1'
ext.ghostdriver_version = '2.1.0'
ext.eaagentloader_version = '1.0.3'
ext.curator_version = '4.0.0'
ext.curator_version = '4.0.1'
ext.proguard_version = constants.getProperty('proguardVersion')
ext.jsch_version = '0.1.54'
ext.protonj_version = '0.27.1'

View File

@ -210,3 +210,7 @@ a:visited {
border-radius: 4px;
border-color: #263673;
}
.grey {
color: #808080;
}

View File

@ -36,7 +36,7 @@ your own ``bridge.conf`` file will use these defaults:
.. literalinclude:: ../../bridge/src/main/resources/bridgedefault.conf
:language: javascript
Bridge Operating Modes
Bridge operating modes
----------------------
.. note:: By default, the Corda node assumes that it will carry out the peer-to-peer functions of the bridge internally!
Before running a dedicated bridge process, it is essential to turn off the dev mode component by setting the
@ -212,8 +212,8 @@ absolute path to the bridge's base directory.
:enableAMQPPacketTrace: Set this developer flag to true if very detailed logs are required for connectivity debugging. Note that the logging volume is substantial, so do not enable in production systems.
Fully Worked Example
-------
Complete example
----------------
As an example to show all features the following is a walk through of the configuration for a pair of HA hot-cold Nodes,
connected to by a HA hot-warm set of ``BridgeInner`` and ``FloatOuter`` that use some simple certificates to secure the
control tunnel and a SOCKS5 proxy for outgoing connectivity (see diagram).

View File

@ -1,4 +1,4 @@
Certificate Revocation List
Certificate revocation list
===========================
The certificate revocation list consists of certificate serial numbers of issued certificates that are no longer valid.
@ -56,8 +56,8 @@ Submission of the certificate revocation requests expects the following fields t
:reporter: Issuer of this certificate revocation request.
Note: At least one of the three: certificateSerialNumber, csrRequestId or legalName needs to be specified.
Also, Corda AMQP serialization framework is used as the serialization framework.
.. note:: At least one of the three: certificateSerialNumber, csrRequestId or legalName needs to be specified.
Also, Corda AMQP serialization framework is used as the serialization framework.
Because of the proprietary serialization mechanism, it is assumed that those endpoints are used by dedicated tools that support this kind of data encoding.

View File

@ -1,5 +1,5 @@
Corda Bridge Component Overview
===============================
Bridge component overview
=========================
.. contents::
@ -35,7 +35,7 @@ protocol will continue to be AMQP 1.0 over TLS.
.. Note:: All deployment modes of the bridge, float, or all-in-one node are transparently interoperable, if correctly configured.
Message Path Between Peer Nodes
Message path between peer nodes
-------------------------------
When a flow within a node needs to send a message to a peer there is a carefully orchestrated sequence of steps to ensure
correct secure routing based upon the network map information and to ensure safe, restartable delivery to the remote flow.

View File

@ -5,7 +5,7 @@
<script type="text/javascript" src="_static/codesets.js"></script>
Database Management
Database management
===================
Corda - the platform, and the installed third-party CorDapps store their data in a relational database (see

View File

@ -4,8 +4,8 @@
.. role:: red
Deterministic Corda Modules
===========================
Deterministic modules
=====================
A Corda contract's verify function should always produce the same results for the same input data. To that end,
Corda provides the following modules:
@ -21,7 +21,7 @@ contract verification should be compiled against these modules to prevent them c
.. note:: These modules are only a development aid. They cannot guarantee determinism without also including
deterministic versions of all their dependent libraries, e.g. ``kotlin-stdlib``.
Generating the Deterministic Modules
Generating the deterministic modules
------------------------------------
JDK 8
@ -92,7 +92,7 @@ The build generates each of Corda's deterministic JARs in six steps:
This step will fail if ProGuard spots any Java API references that still cannot be satisfied by the deterministic
``rt.jar``, and hence it will break the build.
Configuring IntelliJ with a Deterministic SDK
Configuring IntelliJ with a deterministic SDK
---------------------------------------------
We would like to configure IntelliJ so that it will highlight uses of non-deterministic Java APIs as :red:`not found`.
@ -195,7 +195,7 @@ These steps will enable IntelliJ's presentation compiler to use the deterministi
but still build everything using Gradle with the full JDK.
Testing the Deterministic Modules
Testing the deterministic modules
---------------------------------
The ``core-deterministic:testing`` module executes some basic JUnit tests for the ``core-deterministic`` and

View File

@ -15,7 +15,7 @@ will download the correct version of Kotlin.
Please note:
* Corda runs in a JVM. JVM implementations other than Oracle JDK 8 are not actively supported. However, if you do
choose to use OpenJDK, you will also need to install OpenJFX
choose to use OpenJDK, you will also need to `install OpenJFX <http://openjdk.java.net/install/>`_.
* Applications on Corda (CorDapps) can be written in any language targeting the JVM. However, Corda itself and most of
the samples are written in Kotlin. Kotlin is an
@ -79,14 +79,21 @@ IntelliJ
Download a sample project
^^^^^^^^^^^^^^^^^^^^^^^^^
1. Open a command prompt
2. Clone the ``cordapp-example`` repo by running ``git clone https://github.com/corda/cordapp-example``
2. Clone the CorDapp example repo by running ``git clone https://github.com/corda/cordapp-example``
3. Move into the ``cordapp-example`` folder by running ``cd cordapp-example``
4. Checkout the branch for Corda Enterprise 3.0.0 by running ``git checkout release-enterprise-V3``
4. Checkout the branch for Corda Enterprise 3.0 by running ``git checkout release-enterprise-V3``
Resolve Corda Enterprise binaries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Corda Enterprise binaries are not available in a publicly accessible Maven repository.
The ``build.gradle`` file on ``release-enterprise-V3`` branch includes instructions on how to allow Gradle to resolve these dependencies.
The Corda Enterprise binaries are not available in a publicly accessible Maven repository. Instead, the Corda Enterprise
binaries will be made available to your organisation as a tarball (``r3-corda-enterprise-3.0-developer-pack.tar``).
This tarball contains all of the Corda dependencies as they would appear in your local Maven repository located at
``C:\Documents and Settings\{your-username}\.m2``.
To build CorDapps on development machines the Corda Enterprise binaries will need to be discoverable by Gradle. The
`<build.gradle https://github.com/corda/cordapp-example/blob/release-enterprise-V3/build.gradle>`_ file on the
``cordapp-example`` ``release-enterprise-V3`` branch includes instructions on how to allow Gradle to discover
dependencies.
1. Open ``cordapp-example\build.gradle``
2. Do any of the following to allow Gradle to resolve Corda Enterprise binaries, for more information read the commented code in ``build.gradle``:
@ -95,10 +102,14 @@ The ``build.gradle`` file on ``release-enterprise-V3`` branch includes instructi
b. Upload Corda Enterprise binaries and dependencies to your company's private Maven repository and register the repository with Gradle.
c. Add Corda Enterprise binaries to a local directory and register a local Maven repository pointing to this directory with Gradle.
.. note:: Upon receiving the binaries, the quickest way to get started developing your CorDapps is **option a**. This can
be done by firstly unpacking the ``r3-corda-enterprise-3.0-developer-pack.tar`` tarball. Then, copy the unpacked
``respository`` folder to your local Maven repository located at ``C:\Documents and Settings\{your-username}\.m2``.
Run from the command prompt
^^^^^^^^^^^^^^^^^^^^^^^^^^^
1. From the ``cordapp-example`` folder, deploy the nodes by running ``gradlew deployNodes``
2. Move into the ``cordapp-example`` folder by running ``cd cordapp-example``
1. Move into the ``cordapp-example`` folder by running ``cd cordapp-example``
2. From the ``cordapp-example`` folder, deploy the nodes by running ``gradlew deployNodes``
3. Start the nodes by running ``call kotlin-source/build/nodes/runnodes.bat``
4. Wait until all the terminal windows display either ``Webserver started up in XX.X sec`` or ``Node for "NodeC" started up and registered in XX.XX sec``
5. Confirm that the CorDapp is running correctly by visiting the front end at http://localhost:10009/web/example/
@ -137,7 +148,8 @@ Java
3. Toggle "Accept License Agreement"
4. Click the download link for jdk-8uXXX-macosx-x64.dmg (where "XXX" is the latest minor version number)
5. Download and run the executable to install Java (use the default settings)
6. Open a new terminal window and run ``java -version`` to test that Java is installed correctly
6. Open a new terminal window and run ``java -version`` to test that Java is installed correctly. The version should be
"8u171" or higher.
IntelliJ
^^^^^^^^
@ -147,16 +159,23 @@ IntelliJ
Download a sample project
^^^^^^^^^^^^^^^^^^^^^^^^^
1. Open a terminal
2. Clone the ``cordapp-example`` repo by running ``git clone https://github.com/corda/cordapp-example``
2. Clone the CorDapp example repo by running ``git clone https://github.com/corda/cordapp-example``
3. Move into the ``cordapp-example`` folder by running ``cd cordapp-example``
4. Checkout the branch for Corda Enterprise 3.0.0 by running ``git checkout release-enterprise-V3``
4. Checkout the branch for Corda Enterprise 3.0 by running ``git checkout release-enterprise-V3``
.. _resolve-corda-enterprise-binaries:
Resolve Corda Enterprise binaries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Corda Enterprise binaries are not available in a publicly accessible Maven repository.
The ``build.gradle`` file on ``release-enterprise-V3`` branch includes instructions on how to allow Gradle to resolve these dependencies.
The Corda Enterprise binaries are not available in a publicly accessible Maven repository. Instead, the Corda Enterprise
binaries will be made available to your organisation as a tarball (``r3-corda-enterprise-3.0-developer-pack.tar``).
This tarball contains all of the Corda dependencies as they would appear in your local Maven repository located at
``~/.m2/repository``.
To build CorDapps on development machines the Corda Enterprise binaries will need to be discoverable by Gradle. The
`<build.gradle https://github.com/corda/cordapp-example/blob/release-enterprise-V3/build.gradle>`_ file on the
``cordapp-example`` ``release-enterprise-V3`` branch includes instructions on how to allow Gradle to discover
dependencies.
1. Open ``cordapp-example/build.gradle``
2. Do any of the following to allow Gradle to resolve Corda Enterprise binaries, for more information read the commented code in ``build.gradle``:
@ -165,10 +184,23 @@ The ``build.gradle`` file on ``release-enterprise-V3`` branch includes instructi
b. Upload Corda Enterprise binaries and dependencies to your company's private Maven repository and register the repository with Gradle.
c. Add Corda Enterprise binaries to a local directory and register a local Maven repository pointing to this directory with Gradle.
.. note:: Upon receiving the binaries, the quickest way to get started developing your CorDapps is **option a**. This can
be done by firstly unpacking the ``r3-corda-enterprise-3.0-developer-pack.tar`` tarball:
``tar -xvf r3-corda-enterprise-3.0-developer-pack.tar``
Then, copy the unpacked ``respository`` folder to your local Maven repository:
``rsync -av repository ~/.m2/repository``
The extracted folder can now be deleted:
``rm -rf repository``
Run from the terminal
^^^^^^^^^^^^^^^^^^^^^
1. From the ``cordapp-example`` folder, deploy the nodes by running ``./gradlew deployNodes``
2. Move into the ``cordapp-example`` folder by running ``cd cordapp-example``
1. Move into the ``cordapp-example`` folder by running ``cd cordapp-example``
2. From the ``cordapp-example`` folder, deploy the nodes by running ``./gradlew deployNodes``
3. Start the nodes by running ``kotlin-source/build/nodes/runnodes``. Do not click while 7 additional terminal windows start up.
4. Wait until all the terminal windows display either ``Webserver started up in XX.X sec`` or ``Node for "NodeC" started up and registered in XX.XX sec``
5. Confirm that the CorDapp is running correctly by visiting the front end at http://localhost:10009/web/example/
@ -193,11 +225,27 @@ Run from IntelliJ
7. Wait until the run windows displays the message ``Webserver started up in XX.X sec``
8. Confirm that the CorDapp is running correctly by visiting the front end at http://localhost:10009/web/example/
CorDapp Templates and samples
-----------------------------
A CorDapp template that you can use as the basis for your own CorDapps is available in both Java and Kotlin versions:
https://github.com/corda/cordapp-template-java.git
https://github.com/corda/cordapp-template-kotlin.git
And a list of simple sample CorDapps for you to explore basic concepts is available here:
https://www.corda.net/samples/
You can clone these repos to your local machine by running the command ``git clone [repo URL]``.
Next steps
----------
First, explore the example CorDapp you just ran :doc:`here <tutorial-cordapp>`.
The best way to check that everything is working fine is by taking a deeper look at the
:doc:`example CorDapp <tutorial-cordapp>`.
Next, read through :doc:`Corda Key Concepts <key-concepts>` to understand how Corda works.
Next, you should read through :doc:`Corda Key Concepts <key-concepts>` to understand how Corda works.
By then, you'll be ready to start writing your own CorDapps. Learn how to do this in the
:doc:`Hello, World tutorial <hello-world-introduction>`. You may want to refer to the API documentation, the

View File

@ -1,8 +1,8 @@
.. highlight:: kotlin
.. raw:: html
Hot-cold deployment
===================
Hot-cold high availability deployment
=====================================
Overview
--------

View File

@ -28,6 +28,9 @@ application development please continue to refer to `the main project documentat
:caption: Corda Enterprise
:maxdepth: 1
release-notes.rst
version-compatibility.rst
platform-support-matrix.rst
hot-cold-deployment
database-management
corda-firewall
@ -65,21 +68,4 @@ application development please continue to refer to `the main project documentat
:caption: Other documentation
deterministic-modules.rst
release-notes.rst
changelog.rst
.. only:: htmlmode
.. toctree::
:caption: Design docs
:maxdepth: 2
design/design-review-process.md
design/certificate-hierarchies/design.md
design/failure-detection-master-election/design.md
design/float/design.md
design/hadr/design.md
design/kafka-notary/design.md
design/monitoring-management/design.md
design/sgx-integration/design.md

View File

@ -0,0 +1,57 @@
Platform support matrix
=======================
Our supported Operating System platforms are a subset of those supported by Java `8u172 <http://www.oracle.com/technetwork/java/javase/certconfig-2095354.html>`_. Production use of Corda Enterprise 3.0 is only supported on Linux OS, see details below.
Operating systems supported in production
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------+------------------+-----------+
| Platform | CPU Architecture | Versions |
+===============================+==================+===========+
| Red Hat Enterprise Linux | x86-64 | 7.x, |
| | | 6.x |
+-------------------------------+------------------+-----------+
| Suse Linux Enterprise Server | x86-64 | 12.x, |
| | | 11.x |
+-------------------------------+------------------+-----------+
| Ubuntu Linux | x86-64 | 16.10, |
| | | 16.04 |
+-------------------------------+------------------+-----------+
| Oracle Linux | x86-64 | 7.x, |
| | | 6.x |
+-------------------------------+------------------+-----------+
Operating systems supported in development
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------+------------------+-----------+
| Platform | CPU Architecture | Versions |
+===============================+==================+===========+
| Microsoft Windows | x86-64 | 10, |
| | | 8.x |
+-------------------------------+------------------+-----------+
| Microsoft Windows Server | x86-64 | 2016, |
| | | 2012 R2, |
| | | 2012 |
+-------------------------------+------------------+-----------+
| Apple macOS | x86-64 | 10.9 and |
| | | above |
+-------------------------------+------------------+-----------+
Databases
~~~~~~~~~
+-------------------------------+------------------+------------------+--------------------+
| Vendor | CPU Architecture | Versions | JDBC Driver |
+===============================+==================+==================+====================+
| Microsoft | x86-64 | Azure SQL, | Microsoft JDBC |
| | | SQL Server 2017 | Driver 6.2 |
+-------------------------------+------------------+------------------+--------------------+
| Oracle | x86-64 | 11gR2 | Oracle JDBC 6 |
+-------------------------------+------------------+------------------+--------------------+
| Oracle | x86-64 | 12cR2 | Oracle JDBC 8 |
+-------------------------------+------------------+------------------+--------------------+
| PostgreSQL | x86-64 | 9.6 | PostgreSQL JDBC |
| | | | Driver 42.1.4 |
+-------------------------------+------------------+------------------+--------------------+

View File

@ -148,9 +148,9 @@ From a build perspective, switching CorDapps built using Corda 3.x to |release|
and simply requires making the Corda Enterprise binaries available to Gradle, and changing two variables in the build file:
.. parsed-literal:: shell
.. sourcecode:: shell
ext.corda_release_version = '|version|'
ext.corda_release_version = '3.0'
ext.corda_release_distribution = 'com.r3.corda'
..

View File

@ -1,4 +1,4 @@
Sizing and Performance
Sizing and performance
======================
Overview

View File

@ -0,0 +1,60 @@
Corda and Corda Enterprise compatibility
========================================
Corda Enterprise 3.0 provides a baseline for wire stability and compatibility with future versions of Corda Enterprise, and open-source releases of Corda starting from version 3.0.
Future versions of Corda Enterprise will be backward compatible with Corda Enterprise 3.0:
* Corda Enterprise 3.0 nodes can be upgraded to future version of Corda Enterprise. The upgrade will preserve transaction, configuration and other data.
* Corda Enterprise 3.0 nodes will be able to transact with nodes running future versions of Corda Enterprise, providing the CorDapp is compatible with and between platform versions.
* Future versions of Corda Enterprise will be able to run CorDapps developed for, and packaged on Corda Enterprise 3.0.
Corda Enterprise 3.0 can be used in mixed-version/mixed-distribution networks seamlessly transacting with nodes running Corda 3.x and future versions.
* Corda Enterprise 3.0 nodes can transact with nodes running Corda 3.0 and future versions, providing the CorDapp is compatible with and between platform versions and distributions.
* CorDapps originally written for Corda 3.x are API compatible with Corda Enterprise 3.0 and future versions, developers can switch their IDE to Corda Enterprise 3.0 without any code changes in their CorDapp.
* Corda Enterprise 3.0 nodes can run, without recompilation, CorDapps developed on and packaged for Corda 3.x.
.. note:: These compatibility commitments are subject to the standard Corda Enterprise software support policy.
.. role:: grey
+------------------------------------------------+-------------+---------------+---------------+------------------+-----------------+-----------------+---------------------+
| Compatibility with Corda Enterprise 3.0 | :grey:`DP3` | :grey:`DP2` | :grey:`DP1` | Corda 3.x | :grey:`Corda 2` | :grey:`Corda 1` | :grey:`Corda pre 1` |
+================================================+=============+===============+===============+==================+=================+=================+=====================+
| **API compatibility**, i.e. CorDapps developed | :grey:`Yes` | :grey:`Yes` | :grey:`Yes` | Yes | :grey:`Yes` | :grey:`Yes` | :grey:`No` |
| for this Corda version can be compiled and run | | | | | | | |
| on Corda Enterprise 3.0 nodes | | | | | | | |
+------------------------------------------------+-------------+---------------+---------------+------------------+-----------------+-----------------+---------------------+
| **Binary compatibility**, i.e. CorDapps | :grey:`Yes` | :grey:`Yes` | :grey:`Yes` | Yes | :grey:`Yes` | :grey:`Yes` | :grey:`No` |
| compiled on this Corda version can be run on | | | | | | | |
| Corda Enterprise 3.0 nodes | | | | | | | |
+------------------------------------------------+-------------+---------------+---------------+------------------+-----------------+-----------------+---------------------+
| **Network compatibility**, i.e., nodes running | :grey:`No*` | :grey:`Yes` | :grey:`Yes` | Yes | :grey:`No` | :grey:`No` | :grey:`No` |
| this Corda version can transact with Corda | | | | | | | |
| Enterprise 3.0 nodes | | | | | | | |
+------------------------------------------------+-------------+---------------+---------------+------------------+-----------------+-----------------+---------------------+
| **RPC compatibility**, i.e, a client | :grey:`Yes` | :grey:`Yes` | :grey:`Yes` | No | :grey:`No` | :grey:`No` | :grey:`No` |
| application developed for this Corda version | | | | | | | |
| can interact via RPC with a CorDapp running on | | | | | | | |
| the Corda Enterprise 3.0 node | | | | | | | |
+------------------------------------------------+-------------+---------------+---------------+------------------+-----------------+-----------------+---------------------+
| Samples and community apps from | :grey:`Yes` | :grey:`Yes` | :grey:`Yes` | Yes | :grey:`Yes` | :grey:`Yes` | :grey:`No` |
| https://www.corda.net/samples/ for this Corda | | | | | | | |
| version can be compiled and run on Corda | | | | | | | |
| Enterprise 3.0 nodes | | | | | | | |
+------------------------------------------------+-------------+---------------+---------------+------------------+-----------------+-----------------+---------------------+
| Bootstrapper tool from this Corda version can | :grey:`No*` | :grey:`Yes` | :grey:`Yes` | No | :grey:`No` | :grey:`No` | :grey:`No` |
| be used to build Corda Enterprise 3.0 test | | | | | | | |
| networks | | | | | | | |
+------------------------------------------------+-------------+---------------+---------------+------------------+-----------------+-----------------+---------------------+
.. note:: Greyed out releases are out of support.
Cells denoted with asterisk (*) refer to development-mode only. The incompatibility is caused by a change to the truststore for development-mode certificates between
Developer Preview 3 (DP3) and Corda Enterprise 3.0. In other words, DP3 is network compatible with Corda Enterprise 3.0 provided that development-mode is disabled.

View File

@ -83,13 +83,13 @@ internal class PrioritizedLeaderLatch(client: CuratorFramework,
fun start() {
Preconditions.checkState(state.compareAndSet(State.CLOSED, State.STARTED),
"Cannot be started more than once.")
startTask.set(AfterConnectionEstablished.execute(watchedClient, {
startTask.set(AfterConnectionEstablished.execute(watchedClient) {
try {
internalStart()
} finally {
startTask.set(null)
}
}))
})
}
/**

View File

@ -278,20 +278,25 @@ class ZkClientTests {
@Test
fun `clients randomly do things`() {
val alice = ZkClient(zkServer.connectString, ZKPaths.makePath(ELECTION_PATH, "test9"), "ALICE", 0)
val bob = ZkClient(zkServer.connectString, ZKPaths.makePath(ELECTION_PATH, "test9"), "BOB", 1)
val chip = ZkClient(zkServer.connectString, ZKPaths.makePath(ELECTION_PATH, "test9"), "CHIP", 2)
val dave = ZkClient(zkServer.connectString, ZKPaths.makePath(ELECTION_PATH, "test9"), "DAVE", 3)
val countDownLatch = CountDownLatch(3)
val CLIENTS_NUMBER = 4
val ACTIONS_NUMBER = 100
val CLIENT_TIMEOUT = 60L
val clientList = mutableListOf<ZkClient>()
(1..CLIENTS_NUMBER).forEach {
clientList.add(ZkClient(zkServer.connectString, ZKPaths.makePath(ELECTION_PATH, "test9"), "CLI_${it}", it))
}
val countDownLatch = CountDownLatch(clientList.size)
val leaderBuffer = mutableListOf<String>()
listOf(alice, bob, chip, dave).forEach { client ->
clientList.forEach { client ->
thread{
client.addLeadershipListener(HelperListener(client.nodeId, leaderBuffer))
client.start()
val randomizer = Random()
val actions = listOf(Action.RELINQUISH, Action.REQUEST)
for (i in 1..100) {
for (i in 1..ACTIONS_NUMBER) {
val action = actions[randomizer.nextInt(actions.size)]
when(action) {
Action.REQUEST -> client.requestLeadership()
@ -301,17 +306,16 @@ class ZkClientTests {
Thread.sleep(100)
}
countDownLatch.countDown()
}
}
countDownLatch.await(120, TimeUnit.SECONDS)
countDownLatch.await(CLIENT_TIMEOUT, TimeUnit.SECONDS)
//only one leader should exist
var leaderCount = 0
var leaderId = ""
listOf(alice, bob, chip, dave).forEach { client ->
clientList.forEach { client ->
if (client.isLeader()) {
leaderCount++
leaderId = client.nodeId
@ -324,7 +328,8 @@ class ZkClientTests {
println(leaderBuffer)
assertEquals(leaderBuffer.first(), leaderId)
}
listOf(alice, bob, chip, dave).forEach { client -> client.close() }
clientList.forEach { client -> client.close() }
}
private enum class Action {