Introduction

In Chapter 10 of my book (pg. 388-393), Exploring BeagleBone, I describe how you can build web-based CGI applications that can interface with electronics hardware that is attached to the BeagleBone using Bash scripts that call C/C++ programs. The solution works well for very straightforward applications, but this discussion investigates more advanced solutions for applications where there are more complex interactions — for example, the use of web forms to pass data between your web browser and the application that is executing on the BeagleBone. In this discussion I begin by explaining how you can use a C/C++ program, rather than a CGI script, to display a web page. I then investigate the use of the GNU Cgicc library for more structured and complex interactions.

The approach describe here will work on any Linux machine, including other embedded platforms such as the Raspberry PI; however, the steps are structured for the BeagleBone platform and the examples that interact with the hardware are specific to the BeagleBone platform — they can however be easily modified. In this example, the Apache server is used to serve the CGI applications, so having Apache installed is the only prerequisite software required. Apache runs on port 8080 of the BeagleBone by default when using the recommended Debian images — you can test that by opening a web browser and entering the IP address of your Beaglebone in the address bar using the following format: http://192.168.7.2:8080/ (replace the IP address with your BeagleBone’s IP address — the one listed is the default IP address for Internet-over-USB).

It could be argued that this is a “dated approach” to solving the problem of having an embedded system web server interact with a web browser client — it has been around since the 1990’s. To some extent that is true. There are powerful alternatives available such as Java servlets, node.js, Dart, PHP etc. However, this approach:

  • has a low overhead on the BeagleBone, as the code is compiled rather than interpreted,
  • permits access to system calls,
  • can interface readily with hardware using the code libraries that I provide in the book.

The downside is that it is not really suitable for novice programmers, the output format syntax can be verbose and session management is complex. Even with that, it is worth pointing out that some large-scale web applications, including those by Google and Amazon, do use C++ on their servers for performance-critical systems. The BeagleBone is not a high-end server, so any performance optimizations are always welcome, perhaps even at the cost of complexity.

Get Source Code

Source Code for this Discussion

Get Source Code

All of the code for this discussion is available in the GitHub repository for the book Exploring BeagleBone. The code can be viewed publicly at: the ExploringBB GitHub Chapter 10 directory, and/or you can clone the repository on your BeagleBone (or other Linux device) by typing:

A Simple C++ Dynamic Web Page

The first step is to write a simple C or C++ program that is capable of displaying a dynamically generated web page. This task is performed by a bash script in the book chapter, which is perfectly suitable but limiting, both in capability and performance.

Common Gateway Interface (CGI) is a straightforward approach for building dynamic web applications — effectively it allows a web server to share more than just HTML files and/or static images. It does this by allowing executable scripts/programs in a certain file system locations (e.g., /usr/lib/cgi-bin/) to be executed by the web server, and for the output from the scripts/programs to be passed, via the web server, to the web browser of the user that made the request. CGI allows the user’s web browser to pass information (environment and application information) to the script/program using HTTP POST or GET requests. Almost all programming languages can be used to build CGI applications, as their only role in the transaction is to parse the input that is sent to them by the server, and to construct a suitable HTML output response.

On the BeagleBone, the cgi-bin directory requires root access permissions. There are a number of different ways of solving this problem and that is for another discussion. Since the BeagleBone is not typically a multi-user server, I am going to be liberal in my approach to security so that we do not get bogged down in detail. If you are planning to make your BeagleBone publicly visible on the Internet, and place it in control of your home automation system, then you must investigate the topic of server security.

Hello World (with uptime!)

To create a simple C++ CGI application the application can be deployed to the /usr/lib/cgi-bin/ directory on the BeagleBone by default. This directory requires superuser permissions in order to add a script/program — that issue is dealt with shortly.

You can use the nano editor to create the C++ program. Remember that the command “nano -c” displays row/column numbering at the bottoms of the editor display — this is always useful for locating compilation errors.  The following code example in Listing 1 can then be entered — it is also available in the exploringBB GitHub repository in the directory /chp10/cgicc/ with the file name hello.cpp:

Listing 1: The Hello.cpp code that results in the hello.cgi CGI application

This example uses the sysinfo structure to obtain the system uptime and available memory for the BeagleBone single-board computer. It also uses the environment variables to determine the IP address of the client browser that made the request to execute the CGI program. The following environment variables are available (sourced from CgiEnvironment.cpp):

CGI Environment Variables
variable variable variable variable
SERVER_SOFTWARE SERVER_NAME GATEWAY_INTERFACE SERVER_PROTOCOL
SERVER_PORT REQUEST_METHOD PATH_INFO PATH_TRANSLATED
SCRIPT_NAME QUERY_STRING REMOTE_HOST REMOTE_ADDR
AUTH_TYPE REMOTE_USER REMOTE_IDENT CONTENT_TYPE
CONTENT_LENGTH HTTP_ACCEPT HTTP_USER_AGENT REDIRECT_REQUEST
REDIRECT_URL REDIRECT_STATUS HTTP_REFERER HTTP_COOKIE
You can compile the code using the following steps: 

molloyd@beaglebone:~/exploringBB/chp10/cgicc$ ./build
Building the hello.cgi C++ CGI Program

molloyd@beaglebone:~/exploringBB/chp10/cgicc$ ls -al
total 24
drwxr-xr-x 2 molloyd molloyd 4096 Mar 25 00:00 .
drwxr-xr-x 15 molloyd molloyd 4096 Mar 24 23:44 ..
-rwxr-xr-x 1 molloyd molloyd 85 Mar 24 23:46 build
-rwxr-xr-x 1 molloyd molloyd 7204 Mar 25 00:00 hello.cgi
-rw-r--r-- 1 molloyd molloyd 1193 Mar 25 00:00 hello.cpp
molloyd@beaglebone:~/exploringBB/chp10/cgicc$ sudo cp hello.cgi /usr/lib/cgi-bin/

The build script executes the command “g++ hello.cpp -o hello.cgi“.  Please note that the copy command is executed with superuser permissions. This is required as otherwise it would not have the access level required to create the binary executable (hello.cgi) in the /usr/lib/cgi-bin/ directory.

This CGI program can then be called remotely from the web browser on the desktop computer, using the URL http://192.168.7.2:8080/cgi-bin/hello.cgi, as illustrated in Figure 1 below.

Figure 1: A simple C++ CGI application display

The .cgi extension is not a requirement for the executable CGI program, but it is useful here for clarity. For example, the executable could have been named /usr/lib/cgi-bin/hello and the address that is used in the web browser client would be: http://192.168.7.2:8080/cgi-bin/hello

GNU Cgicc (CGI for C++)

Unfortunately, the approach that is described above is only really suitable for programs that make information available to the Internet. By default, C/C++ do not have the built-in libraries required to easily and effectively build interactive CGI applications — for this we need the Cgicc C++ class library.

The GNU Cgicc is a C++ library for building CGI applications. It is powerful and it greatly simplifies the process of building common gateway interface (CGI) applications — those applications that allow you to interact with the BeagleBone over the Internet using a simplified interface within a web browser. As stated, there are other, more recent, approaches to building web applications, but GNU Cgicc offers an efficient high-performance solution.

Installing GNU Cgicc

To avoid complexity, this discussion assumes that you are building the C++ CGI program directly on the BeagleBone itself. Therefore, the first task is to download, compile and install the GNU Cgicc library on the BeagleBone:

Step 1: Download the Ggicc library

The first step is to download the source code for the Cgicc library. You can find the latest version at: ftp://ftp.gnu.org/gnu/cgicc/. At the time that this discussion was written the most recent version is 3.2.16. It is advisable to choose the most recent version and download it to a user account on the BeagleBone, as follows (performing these steps as root is fine too):

molloyd@beaglebone:~$ mkdir cgicc
molloyd@beaglebone:~$ cd cgicc
molloyd@beaglebone:~/cgicc$ wget ftp://ftp.gnu.org/gnu/cgicc/cgicc-3.2.16.tar.gz

2015-03-24 00:53:55 (509 KB/s) - 'cgicc-3.2.16.tar.gz' saved [1409037]
molloyd@beaglebone:~/cgicc$ tar xvf cgicc-3.2.16.tar.gz

cgicc-3.2.16/doc/lib-overview.tmpl
cgicc-3.2.16/doc/COPYING.LIB
cgicc-3.2.16/doc/COPYING
cgicc-3.2.16/doc/Makefile.am

Step 2. Configure the source code makefiles

The final installation directory (for make install) should be configured to be /usr. This will ensure that the compiled library is made available to all users.

molloyd@beaglebone:~/cgicc$ cd cgicc-3.2.16
molloyd@beaglebone:~/cgicc/cgicc-3.2.16$ ./configure --prefix=/usr

config.status: creating doc/Makefile
config.status: creating doc/Doxyfile
config.status: creating cgicc.pc
config.status: creating cgicc/config.h
config.status: executing depfiles commands
config.status: executing libtool commands

Step 3. Make the project

This step takes approximately five minutes in order to build the library on the BeagleBone. It is initiated by typing make in the download directory:

molloyd@beaglebone:~/cgicc/cgicc-3.2.16$ make
Making all in cgicc
make[1]: Entering directory '/home/molloyd/cgicc/cgicc-3.2.16/cgicc'
make all-am
make[2]: Entering directory '/home/molloyd/cgicc/cgicc-3.2.16/cgicc'
/bin/bash ../libtool --tag=CXX --mode=compile g++ -DHAVE_CONFIG_H -I. -x c++ -Wall -W -pedantic -g -O2 -MT
libcgicc_la-CgiEnvironment.lo -MD -MP -MF .deps/libcgicc_la-CgiEnvironment.Tpo -c -o
libcgicc_la-CgiEnvironment.lo 'test -f 'CgiEnvironment.cpp' || echo './''CgiEnvironment.cpp

make[1]: Leaving directory '/home/molloyd/cgicc/cgicc-3.2.16/contrib'
make[1]: Entering directory '/home/molloyd/cgicc/cgicc-3.2.16'
make[1]: Nothing to be done for 'all-am'.
make[1]: Leaving directory '/home/molloyd/cgicc/cgicc-3.2.16'

Step 4. Install the library on the BeagleBone

The final step is to install the compiled library for all users on the BeagleBone. Ensure that you execute make install with superuser permissions, otherwise it will fail to place the library files correctly.

molloyd@beaglebone:~/cgicc/cgicc-3.2.16$ sudo make install
[sudo] password for molloyd:
Making install in cgicc

Libraries have been installed in: /usr/lib

molloyd@beaglebone:~/cgicc/cgicc-3.2.16$cd /usr/lib
molloyd@beaglebone:/usr/lib$ ls libcgi*
libcgicc.a libcgicc.so libcgicc.so.3.2.10 libcgicc.so.5.0.2
libcgicc.la libcgicc.so.3 libcgicc.so.5

C++ Cgicc HTTP GET

The first example that uses the Cgicc library is a simple HTTP GET request-response example. A GET is used to request data from the server resource, whereas a POST is used to submit data to be processed by the server resource. The general structure of a GET request is to use name/value pairs to identify the functionality that you would like to action. For example, a generalized GET request could be described as:

     http://my.beaglebone.com/cgi-bin/mygetapp?name1=value1&name2=value2

This would invoke the application “mygetapp” on the BeagleBone and pass the two variables, name1 and name2, that have the values value1 and value2 respectively. This is approach is quite straightforward and it is easy to construct request strings to be actioned from scripts or other applications. However, this approach should never be used to send sensitive information (e.g., passwords), as the URLs will be visible in server logs, browser histories etc.

The HTTP GET LED Controller

The test application is an LED controller that is very similar to the one that is described in Chapter 5 of the book. The on-board system LEDs can be controlled using the C++ LED class that is available to support that chapter.

Figure 2 illustrates the application that results from the code in Listing 2. You can see in the address bar that the URL has the form “…/getLED.cgi?command=on” — the request URL consists of one namecommand” that has the valueon“. By changing this value we can control the behaviour of the USR3 LED that is on the top left-hand corner of the BeagleBone PCB. After this request is sent, the USR3 LED lights constantly.

Figure 2: A C++ CGI GET application (on command)

The code for this example is presented in Listing 2 below. The code example uses the LED.h code that is used in Chapter 5. For convenience it is replicated in this project directory.

Listing 2: The Cgicc HTTP GET LED example code

The code has some interesting features, The form_iterator it is used to determine the value associated with the command name of the name/value pair. A check is performed to test that the element is not missing or null. If it is then a usage message is presented to the user. Otherwise, a string object cmd is created in place of **it in order to tidy up the syntax — this is not strictly necessary but it makes the code more legible. The cmd is then compared to the four possible options and the correct LED state is triggered. The program can be compiled using the call: 

g++ getLED.cpp LED.cpp -o getLED.cgi -lcgicc

where the getLED.cpp and LED.cpp files are passed to the compiler, along with the -l flag to link with the cgicc library. To deploy the resulting binary (getLED.cgi) the deploy script uses the following calls:

sudo cp getLED.cgi /usr/lib/cgi-bin/
sudo chmod +s /usr/lib/cgi-bin/getLED.cgi

The chmod +s call sets the setuid bit — effectively the getLED.cgi binary is now executed with root permissions by Apache. If you perform a “ls -l” in the /usr/lib/cgi-bin directory you will see the “s” bit set on the binary to indicate that the setuid mode is enable.

molloyd@beaglebone:/usr/lib/cgi-bin$ ls -l
total 64
-rwsr-sr-x 1 root root 19924 Mar 26 2015 getLED.cgi

This is necessary because the LED code requires root access in order to modify the state of the on-board LEDs. Importantly, if this were a CGI script, I would be quite concerned at this point about script code injection. However, this is a CGI program that does not parse input fields. That said, it is not ideal and udev rules (see page 247 in the book) are a better solution for non-root resource access.

The code in Listing 2 does not take full advantage of the Cgicc library — for example, it still manually generates the header output. That will be further improved in the next example — so please keep reading, even if you only require HTTP GET functionality.

Figures 3 below illustrates the other functionality that is available in this application. You can trigger the LED to flash at a fixed frequency, or you can request information from the application about the current status of the LED that is made available via sysfs. All of these changes have an immediate effect on the USR3 LED and it behaves as you would expect.

Figure 3: A C++ CGI GET application (animation of all commands)

C++ Cgicc POST LED Example

The second example that uses the Cgicc library is a HTTP POST example. The POST example allows you to interact with a form that contains checkboxes, radio components, buttons, text fields etc. For example you could use the HTML code in Listing 3 to display a form that passes data to the Cgicc C++ application. That is not required in this example, as the postLED.cgi application generates this code dynamically and adapts the rest of the page to represent the current state of the LED. The operation of this example is best understood by watching the animation in Figure 4.

Listing 3: Example HTML code (this code is not used, rather it is generated dynamically by the CGI C++ application)

 Figure 4: A C++ CGI POST application (animation of all functionality)

You can see that this application changes its output to display the state of the LED, and therefore it appears to be stateful. That is only possible in this example because the HTML form “stores” the “application” state — on each occasion you click the Execute Command button the postLED.cgi application executes afresh and runs to completion, thus losing its state. The expected state is only retained by the HTML form.   The full source code for the Cgicc HTTP POST example is presented in Listing 4 below. It is important to note that this is the only source code required! The application generates the HTML form, which calls itself, over and over again. Just like the getLED.cgi application, the LED3 output changes instantly and appears as you would expect.

Listing 4: The Cgicc HTTP POST example code

This program has some interesting features. In particular, it uses functions such as HTTPHTMLHeader(), html(), body() etc. to generate the HTML content for the output. This is much less verbose that in Listings 1 and 2 and is less prone to error. There are many more such functions that can be used to further clean up the code. The code example also demonstrates how to interact with radio buttons (command), checkboxes (status), and text inputs (period) within HTML forms.

It is important that the form data is parsed at the top of the program. This is because the form data that was previously submitted needs to be propagated into the new output. Clearly, the first time this form is requested there will be no data present and the code at the beginning of the program assigns default value (e.g., flashPeriod=”100″, command=”off”). If this is not performed then the program will suffer from segmentation faults. From that point onwards, the form output needs to maintain the state and that is why these values appear in the HTML generation code. For example,

is a clever piece of code that compares the command string to the string “on”. If they are equal then the word “checked” appears in the HTML form at that point in the code (thanks to the output stream operator <<); however, if they are not equal then the string “” (nothing) appears at that point in the HTML code. This allows a radio item or checkbox item to remain checked or unchecked. Finally towards the end of the program the command is processed and the code to display the status is placed.

The ? is called the conditional operator or often the ternary operator (the latter is slightly incorrect as it is a ternary operator, as it takes three operands, but it may not be the only ternary operator in all languages). An example of this operator in C++ is:

     cout << (s.length() < t.length() ? s : t) << endl;

This line of code will display the shorter of the strings s and t.

Conclusions

This discussion has just scratched the surface on what can be performed using CGI and C++ on the BeagleBone. For very complex applications you may be better placed to examine other frameworks, but for simple high-performance web interfaces, the GNU Cgicc library provides a very appropriate solution. There are several limitations with the current solution. It is a single session solution -- If two users, on two different machines, access the postLED.cgi script at the same time then very strange things will happen! For example, each browser will store an independent state that is likely to be contradictory. However, given that there is only one USR3 LED on the BeagleBone PCB that is not a very significant issue. For more complex applications, session management is important.

For more information on the Cgicc library please see the GNU cgicc library documentation. You will see that the library is capable of handling cookies, file transfers and much more by browsing the Class List.