diff --git a/modules/csharp/pages/p2psync-websocket-using-passive.adoc b/modules/csharp/pages/p2psync-websocket-using-passive.adoc index 88e09ac0b..64987bdcf 100644 --- a/modules/csharp/pages/p2psync-websocket-using-passive.adoc +++ b/modules/csharp/pages/p2psync-websocket-using-passive.adoc @@ -1,11 +1,790 @@ = Passive Peer :page-aliases: advance/csharp-p2psync-websocket-using-passive.adoc -ifdef::show_edition[:page-edition: {release}] {enterprise} ifdef::prerelease[:page-status: {prerelease}] :page-role: :description: Couchbase Lite's Peer-to-Peer Synchronization enables edge devices to synchronize securely without consuming centralized cloud-server resources -include::partial$_set_page_context_for_csharp.adoc[] -include::{root-commons}p2psync-websocket-using-passive.adoc[subs="macros,attributes"] +[abstract] +-- +Description -- _{description}_ + +_Abstract -- How to set up a Listener to accept a Replicator connection and sync using peer-to-peer_ + +Related Content -- https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net[API Reference] | xref:csharp:p2psync-websocket-using-passive.adoc[Passive Peer] | xref:csharp:p2psync-websocket-using-active.adoc[Active Peer] +-- + + + +.Code Snippets +[NOTE] +All code examples are indicative only. +They demonstrate the basic concepts and approaches to using a feature. +Use them as inspiration and adapt these examples to best practice when developing applications for your platform. + + +[discrete#csharp:p2psync-websocket-using-passive:::introduction] +== Introduction +This content provides code and configuration examples covering the implementation of xref:refer-glossary.adoc#peer-to-peer-sync[Peer-to-Peer Sync] over WebSockets. +Specifically, it covers the implementation of a xref:refer-glossary.adoc#passive-peer[Passive Peer]. + +Couchbase's Passive Peer (also referred to as the server, or Listener) will accept a connection from an xref:refer-glossary.adoc#active-peer[Active Peer] (also referred to as the client or replicator) and replicate database changes to synchronize both databases. + +Subsequent sections provide additional details and examples for the main configuration options. + +.Secure Storage +[NOTE] +The use of TLS, its associated keys and certificates requires using secure storage to minimize the chances of a security breach. +The implementation of this storage differs from platform to platform -- see xref:csharp:p2psync-websocket.adoc#using-secure-storage[Using secure storage]. + + + +[discrete#csharp:p2psync-websocket-using-passive:::configuration-summary] +== Configuration Summary + +You should configure and initialize a Listener for each Couchbase Lite database instance you want to sync. +There is no limit on the number of Listeners you may configure -- <> shows a simple initialization and configuration process. + + + + +// Example 1 +.Listener configuration and initialization +[#simple-listener-initialization] + +[#csharp:p2psync-websocket-using-passive:::simple-listener-initialization] +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-initialize", indent=0] +[source, C#] +---- + // Initialize the listener config + var endpointConfig = new URLEndpointListenerConfiguration(new[] { collection }); // <.> + + endpointConfig.Port = 55990; //<.> + + endpointConfig.NetworkInterface = "10.1.1.10"; // <.> + + endpointConfig.EnableDeltaSync = true; // <.> + + endpointConfig.DisableTLS = false; // <.> + + // Use an Anonymous Self-Signed Cert + endpointConfig.TlsIdentity = null; // <.> + + // Configure the client authenticator + // Here we are using Basic Authentication) <.> + SecureString validPassword = new SecureString(); /* example only */ + // Get SecureString input for validPassword + var validUser = "valid.username"; + endpointConfig.Authenticator = new ListenerPasswordAuthenticator( + (sender, username, password) => + { + // Implement your own ValidatePassword function + return username == validUser && ValidatePassword(password); + } + ); + + // Initialize the listener + var listener = new URLEndpointListener(endpointConfig); // <.> + + // Start the listener + listener.Start(); // <.> +---- + + + +==== + +<.> Identify the local database to be used -- see: <> + +<.> Optionally, choose a port to use. +By default the system will automatically assign a port -- to over-ride this, see: <> + +<.> Optionally, choose a network interface to use. +By default the system will listen on all network interfaces -- to over-ride this see: <> + +<.> Optionally, choose to sync only changes. +The default is not to enable delta-sync -- see: <>. + +<.> Set server security. +TLS is always enabled instantly, so you can usually omit this line. +But you _can_, optionally, disable TLS (*not* advisable in production) -- see: <> + +<.> Set the credentials this server will present to the client for authentication. +Here we show the default TLS authentication, which is an anonymous self-signed certificate. +The server must always authenticate itself to the client. + +<.> Set client security -- define the credentials the server expects the client to present for authentication. +Here we show how basic authentication is configured to authenticate the client-supplied credentials from the http authentication header against valid credentials -- see <> for more options. + +Note that client authentication is optional. + +<.> Initialize the listener using the configuration settings. + +<.> <> + + + +[discrete#csharp:p2psync-websocket-using-passive:::api-references] +== API References +You can find https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net[C#.Net API References] here. + +[discrete#csharp:p2psync-websocket-using-passive:::device-discovery] +== Device Discovery +*This phase is optional:* If the Listener is initialized on a well-known URL endpoint (for example, a static IP Address or well-known DNS address) then you can configure Active Peers to connect to those. + +Before initiating the Listener, you may execute a peer discovery phase. +For the Passive Peer, this involves advertising the service using, for example, + and waiting for an invite from the Active Peer. +The connection is established once the Passive Peer has authenticated and accepted an Active Peer's invitation. + + +[discrete#csharp:p2psync-websocket-using-passive:::initialize-the-listener-configuration] +== Initialize the Listener Configuration +Initialize the Listener configuration with the local database -- see <> +All other configuration values take their default setting. + +Each Listener instance serves one Couchbase Lite database. +Couchbase sets no hard limit on the number of Listeners you can initialize. + +// Example 2 +.Specify Local Database +[#ex-locdb] + +[#csharp:p2psync-websocket-using-passive:::ex-locdb] +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-db", indent=0] +[source, C#] +---- +// Initialize the listener config +var endpointConfig = new URLEndpointListenerConfiguration(new[] { collection }); // <.> +---- + + +==== + +<.> Set the local database using the https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html[URLEndpointListenerConfiguration]'s constructor https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration__ctor_Couchbase_Lite_Database_[(Database database)]. + +The database must be opened before the Listener is started. + +`thisDB` has previously been declared as an object of type `Database`. + +[discrete#csharp:p2psync-websocket-using-passive:::lbl-set-network-and-port] +== Set Port and Network Interface + + +[discrete#csharp:p2psync-websocket-using-passive:::port-number] +=== Port number +The Listener will automatically select an available port if you do not specify one -- see <> for how to specify a port. + +// Example 3 +.Specify a port +[#ex-port] + +[#csharp:p2psync-websocket-using-passive:::ex-port] +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-port", indent=0] +[source, C#] +---- +endpointConfig.Port = 55990; //<.> +---- + + + +==== + +<.> To use a canonical port -- one known to other applications -- specify it explicitly using the https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration_Port[Port] method shown here. + +Ensure that firewall rules do not block any port you do specify. + + + +[discrete#csharp:p2psync-websocket-using-passive:::network-interface] +=== Network Interface +The Listener will listen on all network interfaces by default. + +// Example 4 + +[#specify-a-network-interface-to-use] +.Specify a Network Interface to Use + +[#csharp:p2psync-websocket-using-passive:::specify-a-network-interface-to-use] +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-netw-iface", indent=0] +[source, C#] +---- +endpointConfig.NetworkInterface = "10.1.1.10"; // <.> +---- + + +==== + +<.> To specify an interface -- one known to other applications -- identify it explicitly, using the https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration_NetworkInterface[NetworkInterface] method shown here. +This must be either an IP Address or network interface name such as `en0`. + + +TIP: Where necessary, you can identify the available interfaces at runtime, using appropriate platform tools -- see <>. + +[#get-network-interfaces] +.Identify available network interfaces + +[#csharp:p2psync-websocket-using-passive:::get-network-interfaces] +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-get-network-interfaces", indent=0] +[source, C#] +---- +foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { + if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || + ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet) { + // do something with the interface(s) + } +} +---- + + + +==== + + +[discrete#csharp:p2psync-websocket-using-passive:::delta-sync] +== Delta Sync + +Delta Sync allows clients to sync only those parts of a document that have changed. +This can result in significant bandwidth consumption savings and throughput improvements. +Both are valuable benefits, especially when network bandwidth is constrained. + +// Example 5 +.Enable delta sync + +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-delta-sync", indent=0] +[source, C#] +---- +endpointConfig.EnableDeltaSync = true; // <.> +---- + + +==== + +<.> Delta sync replication is not enabled by default. +Use https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html[URLEndpointListenerConfiguration]'s https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration_EnableDeltaSync[EnableDeltaSync] method to activate or deactivate it. + +[discrete#csharp:p2psync-websocket-using-passive:::lbl-tls-security] +== TLS Security + + +[discrete#csharp:p2psync-websocket-using-passive:::enable-or-disable-tls] +=== Enable or Disable TLS + +Define whether the connection is to use TLS or clear text. + +TLS-based encryption is enabled by default, and this setting ought to be used in any production environment. +However, it _can_ be disabled. For example, for development or test environments. + +When TLS is enabled, Couchbase Lite provides several options on how the Listener may be configured with an appropriate TLS Identity -- see <>. + + +You can use https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html[URLEndpointListenerConfiguration]'s https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration_DisableTLS[DisableTLS] method to disable TLS communication if necessary + +The `disableTLS` setting must be 'false' when _Client Cert Authentication_ is required. + +Basic Authentication can be used with, or without, TLS. + +https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration_DisableTLS[DisableTLS] works in conjunction with `TLSIdentity`, to enable developers to define the key and certificate to be used. + +* If `disableTLS` is true -- TLS communication is disabled and TLS identity is ignored. +Active peers will use the `ws://` URL scheme used to connect to the listener. +* If `disableTLS` is false or not specified -- TLS communication is enabled. ++ +Active peers will use the `wss://` URL scheme to connect to the listener. + + + +[discrete#csharp:p2psync-websocket-using-passive:::configure-tls-identity-for-listener] +=== Configure TLS Identity for Listener + +Define the credentials the server will present to the client for authentication. +Note that the server must always authenticate itself with the client -- see: xref:csharp:p2psync-websocket-using-active.adoc#authenticate-listener[Authenticate Listener on Active Peer] for how the client deals with this. + +Use https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html[URLEndpointListenerConfiguration]'s +https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration_TlsIdentity[TlsIdentity] method to configure the TLS Identity used in TLS communication. + +If `TLSIdentity` is not set, then the listener uses an auto-generated anonymous self-signed identity (unless `disableTLS = true`). +Whilst the client cannot use this to authenticate the server, it will use it to encrypt communication, giving a more secure option than non-TLS communication. + +The auto-generated anonymous self-signed identity is saved in secure storage for future use to obviate the need to re-generate it. + + +NOTE: Typically, you will configure the Listener's TLS Identity once during the initial launch and re-use it (from secure storage on any subsequent starts. + +Here are some example code snippets showing: + +* Importing a TLS identity -- see: <> +* Setting TLS identity to expect self-signed certificate -- -- see: <> +* Setting TLS identity to expect anonymous certificate -- see: <> + +.Import Listener's TLS identity +[#ex-import-tls-id] + +[#csharp:p2psync-websocket-using-passive:::ex-import-tls-id] +==== + +Import an identity from a secure key and certificate data source. + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-tls-enable;listener-config-tls-id-full;!listener-config-tls-id-SelfSigned;!listener-config-tls-id-anon", indent=0] +[source, C#] +---- + endpointConfig.DisableTLS = false; // <.> + // Use CA Cert + // Create a TLSIdentity from an imported key-pair + // . . . previously declared variables include ... + X509Store store = + new X509Store(StoreName.My); // create and label x509 store + + // Get keys and certificates from PKCS12 data + byte[] certData = + File.ReadAllBytes("c:client.p12"); // <.> + // . . . other user code . . . + + TLSIdentity identity = TLSIdentity.ImportIdentity( + store, + certData, // <.> + "123", // Password to access certificate data + "couchbase-demo-cert", + null); // Label to get cert in certificate map + // NOTE: If a null label is supplied then the same + // default directory for a Couchbase Lite database + // is used for map. + + // Set the TLS Identity + endpointConfig.TlsIdentity = identity; // <.> +---- + + +==== + +<.> Ensure TLS is used +<.> Get key and certificate data +<.> Use the retrieved data to create and store the TLS identity +<.> Set this identity as the one presented in response to the client's prompt + +.Create Self-Signed Cert +[#ex-create-tls-id] +The system generates a self-signed certificate.] + +[#csharp:p2psync-websocket-using-passive:::ex-create-tls-id] +==== + +pass:q,a[Create a TLSIdentity for the server using convenience API. + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-tls-enable;listener-config-tls-id-full;!listener-config-tls-id-caCert;!listener-config-tls-id-anon", indent=0] +[source, C#] +---- +endpointConfig.DisableTLS = false; // <.> + +// Set the TLS Identity +endpointConfig.TlsIdentity = identity; // <.> +---- + + +==== + + +<.> Ensure TLS is used. +<.> Map the required certificate attributes, in this case the common name. +<.> Create the required TLS identity using the attributes. +Add to secure storage as 'couchbase-docs-cert'. +<.> Configure the server to present the defined identity credentials when prompted. + + +.Use Anonymous Self-Signed Certificate +[#ex-anon-tls-id] +Generated certificates are held in secure storage.] + +[#csharp:p2psync-websocket-using-passive:::ex-anon-tls-id] +==== + +This example uses an _anonymous_ self signed certificate. + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-tls-enable;listener-config-tls-id-anon", indent=0] +[source, C#] +---- +endpointConfig.DisableTLS = false; // <.> + +// Use an Anonymous Self-Signed Cert +endpointConfig.TlsIdentity = null; // <.> + +// Use an Anonymous Self-Signed Cert +endpointConfig.TlsIdentity = null; // <.> +---- + + + +==== + +<.> Ensure TLS is used. + +This is the default setting. +<.> Authenticate using an anonymous self-signed certificate. + +This is the default setting. + +// Are we missing a section that shows how to use TLSIdentity.getIdentity. It would be used to create an identity with a certificate signed by a Root CA, in important case. It could also be used to get an existing self-signed cert (perhaps one created by CreateIdentity above) + +// [#authenticating-the-client] +[discrete#csharp:p2psync-websocket-using-passive:::lbl-authenticating-the-client] +== Authenticating the Client +In this section: <> | <> | <> | <> + +Define how the server (Listener) will authenticate the client as one it is prepared to interact with. + +Whilst client authentication is optional, Couchbase lite provides the necessary tools to implement it. +Use the +https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html[URLEndpointListenerConfiguration] class's https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListenerConfiguration.html#Couchbase_Lite_P2P_URLEndpointListenerConfiguration_Authenticator[Authenticator] method to specify how the client-supplied credentials are to be authenticated. + +Valid options are: + +* No authentication -- If you do not define an Authenticator then all clients are accepted. +* Basic Authentication -- uses the https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.ListenerPasswordAuthenticator.html[ListenerPasswordAuthenticator] to authenticate the client using the client-supplied username and password (from the http authentication header). +* https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.ListenerCertificateAuthenticator.html[ListenerCertificateAuthenticator] -- which authenticates the client using a client supplied chain of one or more certificates. +You should initialize the authenticator using one of the following constructors: +** A list of one or more root certificates -- the client supplied certificate must end at a certificate in this list if it is to be authenticated +** A block of code that assumes total responsibility for authentication -- it must return a boolean response (true for an authenticated client, or false for a failed authentication). + +[discrete#csharp:p2psync-websocket-using-passive:::use-basic-authentication] +=== Use Basic Authentication +// === Authenticate Using the Client Username and Password + +Define how to authenticate client-supplied username and password credentials. +To use client-supplied certificates instead -- see: <> + + + +// Example 7 +.Password authentication + +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-client-auth-pwd", indent=0] +[source, C#] +---- +// Configure the client authenticator +// Here we are using Basic Authentication) <.> +SecureString validPassword = new SecureString(); /* example only */ + +// Get SecureString input for validPassword +var validUser = "valid.username"; +endpointConfig.Authenticator = new ListenerPasswordAuthenticator( + (sender, username, password) => + { + // Implement your own ValidatePassword function + return username == validUser && ValidatePassword(password); + } +); +---- + + +==== + +<.> Where 'username'/'password' are the client-supplied values (from the http-authentication header) and `validUser`/`validPassword` are the values acceptable to the server. + + +[discrete#csharp:p2psync-websocket-using-passive:::using-client-certificate-authentication] +=== Using Client Certificate Authentication +Define how the server will authenticate client-supplied certificates. + +There are two ways to authenticate a client: + +* A chain of one or more certificates that ends at a certificate in the list of certificates supplied to the constructor for https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.ListenerCertificateAuthenticator.html[ListenerCertificateAuthenticator] -- see: <> + +* Application logic: This method assumes complete responsibility for verifying and authenticating the client -- see: <> ++ +If the parameter supplied to the constructor for `ListenerCertificateAuthenticator` is of type `ListenerCertificateAuthenticatorDelegate`, all other forms of authentication are bypassed. ++ +The client response to the certificate request is passed to the method supplied as the constructor parameter. +The logic should take the form of function or block (such as, a closure expression) where the platform allows. + +// Example 8 +.Set Certificate Authorization +[#ex-set-cert-auth] + +[#csharp:p2psync-websocket-using-passive:::ex-set-cert-auth] +==== + +Configure the server (listener) to authenticate the client against a list of one or more certificates provided by the server to the the https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.ListenerCertificateAuthenticator.html[ListenerCertificateAuthenticator]. + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-client-auth-root, indent=0]", indent=0] +[source, C#] +---- +// Configure the client authenticator +// to validate using ROOT CA + +// Get the valid cert chain, in this instance from +// PKCS12 data containing private key, public key +// and certificates <.> +var clientData = File.ReadAllBytes("c:client.p12"); +var ourCaData = File.ReadAllBytes("c:client-ca.der"); + +// Get the root certs from the data +var rootCert = new X509Certificate2(ourCaData); // <.> + +// Configure the authenticator to use the root certs +var certAuth = new ListenerCertificateAuthenticator(new X509Certificate2Collection(rootCert)); + +endpointConfig.Authenticator = certAuth; // <.> + +// Initialize the listener using the config +var listener = new URLEndpointListener(endpointConfig); +---- + + +==== + +<.> Get the identity data to authenticate against. +This can be, for example, from a resource file provided with the app, or an identity previously saved in secure storage. +<.> Configure the authenticator to authenticate the client supplied certificate(s) using these root certs. +A valid client will provide one or more certificates that match a certificate in this list. +<.> Add the authenticator to the Listener configuration. + + +.Application Logic +[#ex-use-app-logic] + +[#csharp:p2psync-websocket-using-passive:::ex-use-app-logic] +==== + +Configure the server (listener) to authenticate the client using user-supplied logic. + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-config-client-auth-lambda", indent=0] +[source, C#] +---- +// Configure the client authenticator +// to validate using application logic + +// Get the valid cert chain, in this instance from +// PKCS12 data containing private key, public key +// and certificates <.> +clientData = File.ReadAllBytes("c:client.p12"); +ourCaData = File.ReadAllBytes("c:client-ca.der"); + +// Configure the authenticator to pass the root certs +// To a user supplied code block for authentication +var callbackAuth = + new ListenerCertificateAuthenticator( + (object sender, X509Certificate2Collection chain) => + { + // . . . user supplied code block + // . . . returns boolean value (true=authenticated) + return true; + }); // <.> + +endpointConfig.Authenticator = callbackAuth; // <.> +---- + +==== + +<.> Get the identity data to authenticate against. +This can be, for example, from a resource file provided with the app, or an identity previously saved in secure storage. +<.> Configure the Authenticator to pass the root certificates to a user supplied code block. +This code assumes complete responsibility for authenticating the client supplied certificate(s). +It must return a boolean value; with `true` denoting the client supplied certificate authentic. +<.> Add the authenticator to the Listener configuration. + + +[discrete#csharp:p2psync-websocket-using-passive:::delete-tls-identity] +=== Delete Entry + +You can remove unwanted TLS identities from secure storage using the convenience API. + +// Example 9 +.Deleting TLS Identities + +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="p2p-tlsid-delete-id-from-keychain", indent=0] +[source, C#] +---- +TLSIdentity.DeleteIdentity(_store, "alias-to-delete", null); +---- + + +==== + + +[discrete#csharp:p2psync-websocket-using-passive:::the-impact-of-tls-settings] +=== The Impact of TLS Settings + +The table in this section shows the expected system behavior (in regards to security) depending on the TLS configuration settings deployed. + + + +.Expected system behavior +[cols="12,44,44"] +|=== +|disableTLS |tlsIdentity (corresponding to server) |Expected system behavior + +|true +|Ignored +a|TLS is disabled; all communication is plain text. + +|false +a| set to null +a|* The system will auto generate an _anonymous_ self signed cert. +* Active Peers (clients) should be configured to accept self-signed certificates. +* Communication is encrypted + +|false +a|Set to server identity generated from a self- or CA-signed certificate + +// On first use:: +* On first use -- Bring your own certificate and private key; for example, using the https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.TLSIdentity.html[TLSIdentity] class's https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.TLSIdentity.html#Couchbase_Lite_P2P_TLSIdentity_CreateIdentity_System_Boolean_System_Collections_Generic_Dictionary_System_String_System_String__System_Nullable_System_DateTimeOffset__System_Security_Cryptography_X509Certificates_X509Store_System_String_System_String_[CreateIdentity()] method to add it to the secure storage. +* Each time -- Use the server identity from the certificate stored in the secure storage; for example, using the https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.TLSIdentity.html[TLSIdentity] class's https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.TLSIdentity.html#Couchbase_Lite_P2P_TLSIdentity_GetIdentity_System_Security_Cryptography_X509Certificates_X509Store_System_String_System_String_[GetIdentity(X509Store, String, String)] method with the alias you want to retrieve.. + +// See: {xref-cbl-pg-p2p-manage-tls-id} for more on how to store and use identities. + +a|* System will use the configured identity. +* Active Peers will validate the server certificate corresponding to the TLSIdentity (as long as they are configured to not skip validation -- see <>). + +// |false +// a| +// // Use the convenience `createIdentity` API to generate the certificate and identity +// * On first use -- Bring your own CA certificate and private key (use `importIdentity`). +// * Each time -- Use the server identity from the CA certificate stored in the keychain; for example, use `TSLIdentity.identity(withIdentity:)`. + +// See: {xref-cbl-pg-p2p-manage-tls-id} for more on how to store and use identities. +// a|. The system will use the provided CA cert. +// . Active peers will validate the CA cert. +// . Communication is encrypted. + +|=== + + +[discrete#csharp:p2psync-websocket-using-passive:::lbl-start-listener] +== Start Listener + +Once you have completed the Listener's configuration settings you can initialize the Listener instance and start it running -- see: <> + +// Example 10 +[#initialize-and-start-listener] +.Initialize and start listener + +[#csharp:p2psync-websocket-using-passive:::initialize-and-start-listener] +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-start", indent=0] +[source, C#] +---- +// Initialize the listener +var listener = new URLEndpointListener(endpointConfig); // <.> + +// Start the listener +listener.Start(); // <.> +---- + +==== + + +[discrete#csharp:p2psync-websocket-using-passive:::monitor-listener] +== Monitor Listener + +Use the Listener's `https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.URLEndpointListener.html#Couchbase_Lite_P2P_URLEndpointListener_Status[Status]` property/method to get counts of total and active connections -- see: <>. + +You should note that these counts can be extremely volatile. So, the actual number of active connections may have changed, by the time the `https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net/api/Couchbase.Lite.P2P.ConnectionStatus.html[ConnectionStatus]` class returns a result. + +// Example 11 +.Get connection counts +[#get-connection-counts] + +[#csharp:p2psync-websocket-using-passive:::get-connection-counts] +==== + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-status-check", indent=0] +[source, C#] +---- +ulong connectionCount = listener.Status.ConnectionCount; // <.> +ulong activeConnectionCount = listener.Status.ActiveConnectionCount; // <.> +---- + + +==== + +[discrete#csharp:p2psync-websocket-using-passive:::stop-listener] +== Stop Listener + +It is best practice to check the status of the Listener's connections and stop only when you have confirmed that there are no active connections -- see <>. + +// Example 12 +.Stop listener using `stop` method + +==== + + +// Show Main Snippet +// include ::csharp:example$code_snippets/Program.cs[tags="listener-stop", indent=0] +[source, C#] +---- +listener.Stop(); +---- + + +==== + + +NOTE: Closing the database will also close the Listener. + + +[discrete#csharp:p2psync-websocket-using-passive:::related-content] +== Related Content +++++ +
+++++ + +[.column] +=== {empty} +.How to +* xref:csharp:p2psync-websocket-using-passive.adoc[Passive Peer] +* xref:csharp:p2psync-websocket-using-active.adoc[Active Peer] + + +[column] +=== {empty} +.Concepts +* xref:csharp:landing-p2psync.adoc[Peer-to-Peer Sync] +* https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-net}{empty}/couchbase-lite-net[API References] + + +[.column] +=== {empty} +.Community Resources +https://forums.couchbase.com/c/mobile/14[Mobile Forum] | +https://blog.couchbase.com/[Blog] | +https://docs.couchbase.com/tutorials/[Tutorials] + +xref:tutorials:cbl-p2p-sync-websockets:swift/cbl-p2p-sync-websockets.adoc[Getting Started with Peer-to-Peer Synchronization] + + +++++ +
+++++