The ecosystem of Ada development centered around alire has vastly expanded the free resources available for learning or for practical use in our own applications. Some of the crates like https://alire.ada.dev/crates/gsl provide a conduit to full featured, open source libraries like https://www.gnu.org/software/gsl/ that are not in ada by building bindings. While it is definitely feasible to build such a library entirely from scratch in Ada, the bindings provide continued access to the brilliant minds that contribute to such libraries.
The subject of this projeclet is https://mosquitto.org; in particular applications utilizing the MQTT protocol. Starting from a thin binding to the mosquitto library which is automatically generated, a layer of Ada like interfaces (or packages) are developed. A simple application is developed to illustrate the features.
16.1 Learning Objectives
Steps involved in building bindings
Thin vs Thick or Thickish bindings
Communication patterns beyond client/server
Leveraging testing resources
16.2 Numerical Expression Captcha
The goal of this projectlet is to support https://en.wikipedia.org/wiki/CAPTCHA except the challenge will be numerical expressions expecting the responder to compute the answer prove that they are not an automaton. Since the numerical expressions are dynamically and randomly generated the answers are not static and thus provides a reasonable challenge.
16.2.1 High Level design
The support is separated into a quizzer which is responsible for challenging the user and providing the necessary permissions. The quizzer however does not generate the numerical expression - relying on a poser of quizzes to provide a problem as well as the solution. Such a communication utilizes the MQTT protocol, in particular the mosquitto library opening up many possibilities.
In this projectlet, the communication patterns utilized is very simple - periodic broadcast. Every minute or so the poser broadcasts an automatically generated puzzle and its solution. The quizzer listens for such a broadcast for challenging the user till a successful solution is provided by the user.
16.2.2 Binding generation
The first step in this effort is to generate a thin binding to the library - which translates the basic definitions from presumably the native C specifications to Ada.
pragma Ada_2012;
pragma Style_Checks (Off);
pragma Warnings (Off, "-gnatwu");
with Interfaces.C; use Interfaces.C;
with Interfaces.C.Strings;
with System;
with Interfaces.C.Extensions;
with stddef_h;
with utypes_uuint8_t_h;
with utypes_uuint16_t_h;
with utypes_uuint32_t_h;
package mosquitto_h is
LIBMOSQUITTO_MAJOR : constant := 2; -- /opt/homebrew/include/mosquitto.h:67
LIBMOSQUITTO_MINOR : constant := 0; -- /opt/homebrew/include/mosquitto.h:68
LIBMOSQUITTO_REVISION : constant := 20; -- /opt/homebrew/include/mosquitto.h:69
-- unsupported macro: LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION)
MOSQ_LOG_NONE : constant := 0; -- /opt/homebrew/include/mosquitto.h:74
MOSQ_LOG_INFO : constant := (2**0); -- /opt/homebrew/include/mosquitto.h:75
MOSQ_LOG_NOTICE : constant := (2**1); -- /opt/homebrew/include/mosquitto.h:76
MOSQ_LOG_WARNING : constant := (2**2); -- /opt/homebrew/include/mosquitto.h:77
16.2.3 Prettier Package
Beginning with renaming the package from mosquitto_h to mosquitto, some simple heuristics provide a prettier interface that renders the users more readable:
Though the above package is functional and could support most applications, it is not Ada friendly. For example all strings are expected to be null terminated as is the norm in the C world. We help ourselves by building a family of packages which provide a lot more Adaish interfaces.
The burden of handling strings is eliminated with this layer. Similarly status codes are converted into Exceptions.
Further, the interfaces required for a producer being distinct from those of the consumer of the information, individual packages provide a friendlier interface: