# Floating Server V2

LicenseSpring SDKs support both Floating Server v1 and v2. Here we demonstrate how to retrieve and register licenses on Floating Server v2.

In some SDKs you can reuse the same interface for handling licenses on Floating Server v1, with an additional function used for fetching all floating licenses tied to a single product. Each license has its own 64-bit integer `license_id`, called the server-side license ID in LicenseSpring SDKs.

## Certificate and signature verification

Each Floating Server instance has its own private key used for signing response payloads, and you should have received a certificate chain tied to your instance.

To verify the certificate and to verify signatures returned by the Floating Server, you must enter the whole certificate chain into the SDK. You can do it by specifying an absolute or relative path to the chain PEM file, or input the whole chain as a string constant:

{% tabs %}
{% tab title="C++" %}

<pre class="language-cpp"><code class="lang-cpp">#include &#x3C;LicenseSpring/ExtendedOptions.h>

<strong>options.setCertificateChainFromFile("chain.pem");
</strong>// or
options.setCertificateChain(R"(...cert...)");
</code></pre>

{% endtab %}

{% tab title="C#" %}

```csharp
options.setCertificateChainFromFile("chain.pem");
// or
options.CertificateChain = "(...cert...)";
```

{% endtab %}

{% tab title="Python" %}

```python
# API client configuration
from licensespring.floating_server import FloatingAPIClient

api_client = FloatingAPIClient(api_protocol="http",api_domail="localhost:8080",certificate_chain_path="path_to_pem_file/chain.pem")

# Floating Manager configuration
from licensespring.licensefile.config import Configuration
from licensespring.licensefile.floating_manager import FloatingManager

conf = Configuration(product="your_product_key",api_key="your_api_key",
                   shared_key="your_shared_key",file_key=key,file_iv=iv,
                   is_guard_file_enabled=True,certificate_chain_path="path_to_pem_file/chain.pem")

fs_manager = FloatingManager(conf=conf)
```

{% endtab %}

{% tab title="Swift" %}

```
let fs2Options = ExtendedOptions()
let path: String
fs2Options.setCertificateChain(from: path)
// or
let url: String
fs2Options.setCertificateChain(from: url)

let configuration = Configuration( 
                                apiKey: "apiKey",
                                sharedKey: "SharedKey",
                                productCode: "", 
                                publicKey: publicKey,
                                extendedOptions: fs2Options
)
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
If you're getting a `License signature is not valid` error or a similar verification error, you're missing the Floating Server certificate chain, or set the wrong one.
{% endhint %}

## Authentication and license registration

Registering and using a license requires users to be logged in to an account created on the Floating Server. The SDK manages token lifetime automatically.

{% tabs %}
{% tab title="C++" %}

```cpp
#include <LicenseSpring/FloatingClient.h>
#include <LicenseSpring/ExtendedOptions.h>

// ...

LicenseSpring::ExtendedOptions options;
options.setCertificateChainFromFile("chain.pem");
// or
options.setCertificateChain(R"(...cert...)");
// and other options ...

auto config = LicenseSpring::Configuration::Create(/*...*/);
auto fc = LicenseSpring::FloatingClient::create(config);

// Authenticate the user if it is required
// You should first create the user on the Floating server itself
fc->authenticateUser("user", "pass");

// FloatingClient::getAllLicenses returns one LicenseID for each license tied to the configured product code
std::vector<LicenseSpring::LicenseID> licenseIds = fc->getAllLicenses();

// check if at least one license exists
if (licenseIds.empty())
    return 1;
    
for (const auto &licenseId : licenseIds)
{
    std::cout << "Server-side license ID: " << licenseId.serverId();
    // licenseId.key() will return the license key of the license
}
    
// register the first license, same as on Floating Server v1
auto licenseId = licenseId.front();
std::string username = "John";
auto license = fc->registerLicense(username, licenseId); 
```

{% endtab %}

{% tab title="C#" %}

```csharp
ExtendedOptions options = new LicenseSpring.ExtendedOptions();
options.SetCertificateChainFromFile(@"path/to/certificate.pem", true);
//or
options.CertificateChain = ""; // certificate goes here
Configuration config = new Configuration(/*...*/);
config.ExtendedOptions = options;
FloatingClient floatingClient = new FloatingClient();
floatingClient.Initialize( config );

// Authenticate the user if it is required
// You should first create the user on the Floating server itself
_floatingClient.AuthenticateUser("user", "pass");

bool onLine = floatingClient.IsOnline();
List<LicenseID> licenseIds = floatingClient.GetAllLicenses();
// check if at least one license exists
if (!licenseIds.Any())
{
    return;
}

foreach (LicenseID licenseId in licenseIds)
{
    Console.WriteLine("Server-side license ID: " + licenseId.ServerId);
}

// register the first license, same as on Floating Server v1
string username = "John"; 
LicenseID licenseId = licenseIds[0];
ILicense license = floatingClient.Register(username, licenseId);
```

{% endtab %}

{% tab title="SWIFT" %}

```
let fs2Options = ExtendedOptions()
let path: String
fs2Options.setCertificateChain(from: path)
let configuration = Configuration( 
                                apiKey: "apiKey",
                                sharedKey: "SharedKey",
                                productCode: "", 
                                publicKey: publicKey,
                                extendedOptions: fs2Options
)
let floatingClient = FloatingClient(configuration: configuration)

// Authenticate the user if it is required
// You should first create the user on the Floating server itself
try floatingClient.authenticateUser(user: fs2Username, password: fs2Password)

let onLine = floatingClient.checkConnection();
let licenses = floatingClient.getAllLicenses();
// check if at least one license exists
guard !licenses.isEmpty else { return }

for license in licenses {
     print("Server-side license ID: \(String(describing: license.serverId)) ")
}

// register the first license, same as on Floating Server v1
let username = "John"
guard let firstLicense = licenses.first else { return }
let license = floatingClient.register(userID: username, licenseId: firstLicense)
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Manually setting up a license ID with the license key, or a username and password combination does not work in Floating Server V2.
{% endhint %}

### Load balancing

When using a high-availability deployment of the Floating Server, the C++ SDK provides built-in round-robin load balancing with automated failover.&#x20;

The SDK logs if a node becomes blacklisted, and such nodes are temporarily removed from round-robin rotation. The SDK throws an exception only when all nodes are blacklisted.

<pre class="language-cpp" data-line-numbers><code class="lang-cpp">#include &#x3C;LicenseSpring/LicenseSpring.h>
<strong>
</strong>
LicenseSpring::ExtendedOptions options;
std::vector&#x3C;std::string> floatingServerURLs {
    "https://primary-fs.yourdomain.com",
    "https://backup-fs.yourdomain.com"
};

options.setAlternateServiceURLs(floatingServerURLs);
// disable a failing node for 30 seconds before retrying
options.setBlacklistPeriod(30);

// pass options to LicenseSpring::Configuration::create
</code></pre>
