Code examples

The following section will describe the basic usage of License-manager from C++ code snippets. CrossControl also provides a larger Qt application with a full implementation using a larger set of the funtionality.

Acquire license

To read if the system contains a valid license for the software, the method acquire_license is used. Basic usage is to call the method without parameters to check the default feature.

#include <iostream>
#include <unordered_map>
#include <licensecc/licensecc.h>

using namespace std;

LicenseInfo licenseInfo;

LCC_EVENT_TYPE result = acquire_license(nullptr, nullptr, &licenseInfo);

if (result == LICENSE_OK) {
	cout << "license for main software OK" << endl;
}

In case of failure to acquire a valid license, the following set of possible return values are mapped as:

unordered_map<LCC_EVENT_TYPE, string> stringByEventType = {
	{LICENSE_OK, "OK "},
	{LICENSE_FILE_NOT_FOUND, "license file not found "},
	{LICENSE_SERVER_NOT_FOUND, "license server can't be contacted "},
	{ENVIRONMENT_VARIABLE_NOT_DEFINED, "environment variable not defined "},
	{FILE_FORMAT_NOT_RECOGNIZED, "license file has invalid format (not .ini file) "},
	{LICENSE_MALFORMED, "some mandatory field are missing, or data can't be fully read. "},
	{PRODUCT_NOT_LICENSED, "this product was not licensed "},
	{PRODUCT_EXPIRED, "license expired "},
	{LICENSE_CORRUPTED, "license signature didn't match with current license "},
	{IDENTIFIERS_MISMATCH, "Calculated identifier and the one provided in license didn't match"}
};

The acquire_license method call can be used to query specific parts of the license by adding CallerInformation to the call.

CallerInformations callerInfo = {"\0", "FULL_SELF_DRIVING_SUPPORT", 0};
result = acquire_license(&callerInfo, nullptr, &licenseInfo);

if (result == LICENSE_OK) {
	cout << "FULL_SELF_DRIVING_SUPPORT is licensed" << endl;
} else {
	cout << "FULL_SELF_DRIVING_SUPPORT is NOT licensed" << endl;
}

Read hardware identifier

To read the unique hardware ID of a CCpilot device, the license manager call identify_pc is used. See Public API for additional information. The C++ code for this will look like:

size_t hw_id_sz = LCC_API_PC_IDENTIFIER_SIZE + 1;
char hw_identifier[LCC_API_PC_IDENTIFIER_SIZE + 1];

if (identify_pc(STRATEGY_DEFAULT, hw_identifier, &hw_id_sz,   nullptr)) {
    cout << "hardware identifier is :" << hw_identifier << endl;
}

Using a Demo license

If the issued license file does not have a hardware signature, it can be used as a “demo license” for the application that can work on any device with limited functionality. Example usage:

LicenseInfo licenseInfo;
size_t pc_id_sz = LCC_API_PC_IDENTIFIER_SIZE + 1;
char pc_identifier[LCC_API_PC_IDENTIFIER_SIZE + 1];

LCC_EVENT_TYPE result = acquire_license(nullptr, nullptr, &licenseInfo);

if (result == LICENSE_OK) {
	cout << "license OK" << endl;
	if (!licenseInfo.linked_to_pc) {
		cout << "No hardware signature in license file. This is a 'demo' license that works on every device." << endl;
	}
}

Display date limited license

If license already has expired you will get the PRODUCT_EXPIRED as a result instead of LICENSE_OK. If license has not expired you can check for the has_expiry field and look at the days_left and expiry_date fields of LicenseInfo. See example below.

LicenseInfo licenseInfo;
size_t pc_id_sz = LCC_API_PC_IDENTIFIER_SIZE + 1;
char pc_identifier[LCC_API_PC_IDENTIFIER_SIZE + 1];

LCC_EVENT_TYPE result = acquire_license(nullptr, nullptr, &licenseInfo);

if (result == LICENSE_OK) {
    cout << "license OK" << endl;

    if (licenseInfo.has_expiry)
    {
        cout << "Days left " << licenseInfo.days_left << endl;
        cout << "Expired date " << licenseInfo.expiry_date << endl;
    }
}

Display hardware ID using a QrCode

If a feature in your sofware is unlicenced it can be nice to show the Hardware ID as a QrCode in your UI, enabling scanning it via a mobile phone and send the ID to the license issuer.

Using the public api you can retrieve the hardware ID which would look something like this AAAC-QtjM-1R8=

Below an idea of what the UI can look like

Qr Example

Convert HW ID to Qr and display it

Using this qr-code-generator-library Link you can use the code-snippet to create SVG including the hardware ID.

Displaying it via Qt is pretty straight forward. Using Qt’s SVG

void QrHelper::createQrCode(QString input) {
    // Hardware ID does not change during program run, so it is only necessary to generate the code once
    if (_qrImage.isNull()) {
        const QrCode::Ecc errCorLvl = QrCode::Ecc::LOW; // Error correction level

        std::string s      = input.toStdString();
        const char *qrData = s.data();

        const QrCode qr = QrCode::encodeText(qrData, errCorLvl);

        std::string svgStr = toSvgString(qr, 4);
        QXmlStreamReader reader(svgStr.c_str());

        QSvgRenderer renderer(&reader);
        qDebug() << "QrCode ready to be rendered " << renderer.isValid();

        _qrImage = QImage(200, 200, QImage::Format_ARGB32_Premultiplied);
        QPainter imagePainter(&_qrImage);
        imagePainter.setRenderHint(QPainter::Antialiasing, false);
        renderer.render(&imagePainter);
        imagePainter.end();

        // Rough transparency conversion of the white background
        for (int i = 0; i < _qrImage.width(); i++) {
            for (int j = 0; j < _qrImage.height(); j++) {
                QColor c = _qrImage.pixelColor(i, j);
                if (c == Qt::white) {
                    _qrImage.setPixelColor(i, j, Qt::transparent);
                }
            }
        }
    }    
    emit qrImageChanged(&_qrImage);
}

Load license at specific location

By providing the struct LicenseLocation when you acquire a license you can name the license anything (instead of the default same name as your binary)

// Result after acuire_license stored in licenseInfo
LicenseInfo licenseInfo;
// Path to license file
LicenseLocation loc {LICENSE_PATH, "/opt/cclicenses/onelicense.lic"};
// What feature should we check
CallerInformations ci = {"\0", "SOME_FEATURE", 0};

LCC_EVENT_TYPE result = acquire_license(&ci, &loc, &licenseInfo);
if (result == LICENSE_OK) {
    cout << "license OK" << endl;
}

Using multiple license files

An idea for using more than one license file. If your software has X features, you could try loading all license files found in a specific folder and keep track of the most benificial one per feature you have. Doing this it will be easy to drop in new license files and when you restart the software it will correctly choose the best license. In our Qt demo example we use this approach (can be requested). Workflow