Project

General

Profile

The QKD Module template

Remark: we recommend to refer to the online AIT QKD API documentation reference: https://sqt.ait.ac.at/qkd/doc for details on objects, data types, namespaces and such.

Hello World!

Creating a module is fairly simple. In fact the most simplistic QKD module is:

#include <iostream>
#include <QtCore/QCoreApplication>
#include <qkd/qkd.h>

class HelloWorld : public qkd::module::module {

public:

    HelloWorld() : qkd::module::module("hello-world", qkd::module::module_type::TYPE_OTHER) {}

private:

    bool process(qkd::key::key & key, 
                 qkd::crypto::crypto_context & ctxIn, 
                 qkd::crypto::crypto_context & ctxOut) {

        std::cout << "Hello World!" << std::endl;
        terminate();

        return true;
    }
};

int main(int argc, char ** argv) {

    QCoreApplication app(argc, argv);

    HelloWorld helloWorld;

    helloWorld.set_url_pipe_in("");
    helloWorld.start_later();

    app.connect(&helloWorld, SIGNAL(terminated()), SLOT(quit()));
    app.exec();

    helloWorld.join();

    return 0;
}

Compile and run this code with (this is for the AIT QKD R10 v9.9999.8 using Qt5, if you use versions below v9.9999.8 you have to link with QtCore of Qt4):

$ g++ -std=c++11 -fPIC -I /usr/include/x86_64-linux-gnu/qt5/ helloworld.cpp -lqkd -lQt5Core -lboost_system
$ ./a.out
Hello World!

Let's see what this QKD module does:

1. We need some includes:

#include <iostream>
#include <QtCore/QCoreApplication>
#include <qkd/qkd.h>

The iostream is pretty standard. However, the AIT QKD R10 draws a lot of functions from the Qt library. In fact, the message loop and event handling inside a QKD module is based around the Qt message loop. That's why we include the most basic Qt stuff: QCoreApplication. And finally, qkd.h itself. This later include will import all definitions we need to create any AIT QKD module.

2. Specify our QKD module:

All AIT QKD modules derive from the base QKD module class qkd::module::module. This class needs at least an id, some text to uniquely identify the module, and a module type, some hint about the purpose of the module.

In our example the module's id is "hello-world" and the module type is TYPE_OTHER.

class HelloWorld : public qkd::module::module {

public:

    HelloWorld() : qkd::module::module("hello-world", qkd::module::module_type::TYPE_OTHER) {}

};

The fundamental purpose of any QKD module is to process incoming keys and forward these once processed. Keys are delivered by the preceding module and then pushed to the next succeeding one. The AIT QKD framework takes care on how to get these keys and where to push them.

The only job remaining is: to declare what to do with a key.

The method responsible for handling keys inside the QKD module class is:

private:

    bool process(qkd::key::key & key, 
                 qkd::crypto::crypto_context & ctxIn, 
                 qkd::crypto::crypto_context & ctxOut) {

        std::cout << "Hello World!" << std::endl;
        terminate();

        return true;
    }

Examining the method signature we find that the very first argument is the key to work on. This parameter is given by reference (&) with the intention that the modifications on the key is done in place without any memory copy.

The second and third parameter are crypto_context. These are constructions which hold the current authentication crypto states of incoming and outgoing messages with respect to the key. For each message the module wants to send to its peer module the outgoing crypto context is needed (and modified), for every message the module receives from its peer in order to work on the key the incoming crypto context is needed (and modified).

If the key has been successfully worked on (i.e. for error correction: have we succeeded in correcting the key?) this method ought to return true. If we return false instead, the key is discarded, dropped and vanishes.

Our current key "processing" is to say "Hello World!" on the console. We then tell ourselves (the module) to quit by invoking terminate() and return from this function. Note: we may as well return false here, it doesn't really matter.

3. Finally let's check main():

We need to get up the Qt subsystem working. So we instantiate a QCoreApplication object and let it execute. The execute call (app.exec()) won't return until we tell the QCoreApplication object to terminate (see below). However, after this we return 0 and close the process:

int main(int argc, char ** argv) {

    QCoreApplication app(argc, argv);

    ...
    app.exec();
    ...

    return 0;
}

Just right before we start the Qt application loop (at app.exec()) we instantiate our module.

    HelloWorld helloWorld;

    helloWorld.set_url_pipe_in("");
    helloWorld.start_later();

The set_url_pipe_in("") statement tells the module, that there is no preceding module to pull the keys from. The key input URL is empty (""). If this URL is empty the AIT QKD framework will "successfully pull a key from nowhere". That said: if the URL is empty, the AIT QKD framework will create an empty key for the module to work on. The key has 0 size and default metadata associated.

If instead we specify a valid URL (e.g.: "tcp://192.168.0.1:2000") the framework will try to grab key material delivered to this address and once parsed and decoded would hand it out to the process() method of the module.

Also we tell the module to start key processing once all other startup code has run. This is achieved by the start_later() call. If we miss this, the module will remain in the READY state even if there are keys ready to be processed. We have to explicitly tell the module to run and work on the keys. On the other hand: we can anytime tell the module to pause and resume work after some time based on the very same mechanics.

Before we let loose by invoking app.exec() we still have to tell the Qt5 QCoreApplication to quit once our module terminates.

    app.connect(&helloWorld, SIGNAL(terminated()), SLOT(quit()));

When we return from app.exec() we have to clean up. As AIT QKD modules are multithreaded we have to join() all threads returning from their cleanup codes and destructors.

    helloWorld.join();

By this you should be capable already on how to write your own AIT QKD module. Refer to the online API documentation for more details https://sqt.ait.ac.at/qkd/doc ... or read on. =)

The AIT QKD R10 Template

We offer a complete elaborated template for you to start off writing your own QKD module. It is located in the project root at

qkd/examples/template
├── bin
│   ├── CMakeLists.txt
│   ├── main.cpp
│   ├── my_module.cpp
│   └── my_module.h
└── CMakeLists.txt

Copy and paste this folder somewhere on your hard drive. Then step into this folder, create a build directory, invoke cmake and make.

$ mkdir build
$ cd build/
$ cmake ..
...
$ make
[ 11%] Generating my_module.xml
[ 22%] Generating my_module.moc.cpp
[ 33%] Generating my_module_dbus.cpp, my_module_dbus.h
[ 44%] Generating my_module_dbus.moc
.../build/bin/my_module_dbus.h:0: Note: No relevant classes found. No output generated.
Scanning dependencies of target my_module_exe
[ 55%] Building CXX object bin/CMakeFiles/my_module_exe.dir/main.cpp.o
[ 66%] Building CXX object bin/CMakeFiles/my_module_exe.dir/my_module.cpp.o
[ 77%] Building CXX object bin/CMakeFiles/my_module_exe.dir/my_module.moc.cpp.o
[ 88%] Building CXX object bin/CMakeFiles/my_module_exe.dir/my_module_dbus.cpp.o
[100%] Linking CXX executable my_module_exe
[100%] Built target my_module_exe

This template comes along also with DBus support. That is: you can declare variables and methods to be called from the outside of the current module process during runtime, e.g. query the current bits per seconds, the current QBER, pause and resume the module, etc.

In the sources of this template you find the literal MY_MODULE and my_module respectively. Please substitute these literals with the names you choose for your module.

For convenience we provide the template tarball for download. Please unpack the tarball and check the included README.txt for further details.

qkd-module-template.tar.gz (4.3 KB) Oliver Maurhart, 17.08.2016 15:30