The Barracuda CSP tag language

This article will show you how to use the server side tag language integrated into the Barracuda Embedded Web-Server. It is suggested that you read the introduction to Barracuda prior to reading this article.

Server side scripting, a method used in web-servers to dynamically create HTML, is typically used in embedded devices as a way to dynamically create a user interface. The dynamic HTML rendered in the server may, for example, show the dynamic changes in a power meter in a device.

Barracuda supports a very advanced type of server side scripting, which we call CSP. CSP is similar to Active Server Pages, ASP, which was invented by Microsoft. With CSP, you can embed C or C++ directly into an HTML template page created by an HTML designer.

This article assumes that you are a C or C++ programmer with some HTML knowledge and some experience in server side scripting. An introduction to server side scripting is outside the scope of this article, but since Barracuda is similar to ASP, one can refer to an ASP book. The ASP tag language is similar to CSP and the ASP API is similar to the API provided by Barracuda, except for that Barracuda is using C or C++ for server side scripting.

A good introduction to ASP can be found online: http://www.w3schools.com/asp/

Hangman game

We will demonstrate how one can design the classic hangman game using CSP. The objective of the game is to guess the word before the man is hung.

Start Example

The computer randomly selects a word from its dictionary. The correct number of blank spaces will appear above the gallows. The gamer should click on a letter of the alphabet to guess that letter. If the gamer is correct, that letter will appear. If the gamer is incorrect, more of the gallows will be drawn.

The hangman game is one CSP page, which is installed into the virtual file system at system startup. The web-browser will send an initial HTTP GET request to the server the first time the gamer requests the page. The server will forward the request to the compiled CSP page, which is now part of the virtual file system. Subsequent requests from the browser will be HTTP POST requests, which transmit data from the browser to the server.

The compiled CSP page renders a new HTML page and sends the page back to the browser for every request. The generated HTML file will therefore look different for every request. It is the C code embedded into the CSP page, which generates the dynamic part.

A CSP page is an ordinary HTML file with added C or C++ code for rendering the dynamic parts of the page. The C or C++ code is surrounded by, for example, the delimiters <% and %>. The tags are similar to the ASP tags, but there is a difference between ASP and CSP. ASP is compiled inside the web-server, but CSP is pre-compiled into C or C++ code on a host computer. This code is then compiled with a C/C++ compiler and linked with your embedded system.

Designing the hangman framework

The first part of the design is to identify the static components of the game. The static components are the parts that will always look identical. This is typically done by an HTML designer. We have deliberately made a very basic HTML framework. A real-world application, which is designed by an HTML designer, would usually have a more appealing and professional looking user interface.

You can open the complete hangman game source code in a separate window and use the source code as a reference when we discuss various code snippets from the game.

The HTML framework designed by the HTML designer:
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Draft//EN'> <html> <head><title> hangman </title></head> <body bgcolor='white' text='#000010' link='blue' vlink='#ff00ff' link='#ffff00'> <div align=center> <font color='#ff3333' size=+5>H</font> <font color='#cc6633' size=+5>a</font> <font color='#999900' size=+5>n</font> <font color='#33cc33' size=+5>g</font> <font color='#339999' size=+5>m</font> <font color='#3366cc' size=+5>a</font> <font color='#0033ff' size=+5>n</font> </div> <div align=center> <font size=+3 color='#336699'> <!-- Letters of the correct word and blank spaces here --> </font> </div> <br/> <div align=center> <!-- one of the 8 gallows images here --> <!-- more dynamic text here --> <!-- The following form should only be emitted when playing a game --> <form method='post' action='hangman.html'> <!-- The 3 value attributes below must be dynamically updated --> <input type='hidden' name='wordDbIndex' value=''/> <input type='hidden' name='guess' value=''/> <input type='hidden' name='noOfUsedGues' value=''/> <input type='submit' name='ch' value='A'/> <input type='submit' name='ch' value='B'/> <!-Letter C to Y omitted, must be added --> <input type='submit' name='ch' value='Z'/> </form> <p> <a href = "hangman_src.html" target="_blank">view html source code</a> </p> </div> </body> </html>

Designing the C code infrastructure

The HTML designer left a number of HTML comments in the above HTML page. It is now the C programmer's job to replace these comments with C or C++ code enclosed within server side tags.

Before the C programmer can start filling in the blank spaces (replace the comments) in the CSP file, the infrastructure for the game must be designed. The C code for handling this logic should normally be left outside of the CSP file, but we have included all the code into the CSP page for the purpose of this article. Web-designers always talk about separating the presentation and the logic and one should therefore limit the amount of CSP tags with C or C++ code in the CSP file.

One problem with designing the hangman game is that we must have some mechanism that can keep state information in between HTML page requests. HTTP is a stateless protocol and can not help us in maintaining the state information. There are basically two methods for maintaining state information between page requests.

Barracuda supports persistent session objects, but the HTML designer, which designed the above HTML template, assumed we wanted to use hidden variables. Hidden variables are adequate for the hangman game, but the use of hidden variables can easily get ugly in more advanced applications. This is when session object comes to the rescue and can be used when a more advanced state architecture is required.

Game state information is stored in 3 hidden HTML variables:
<!-- The 3 value attributes below must be dynamically updated --> <input type='hidden' name='wordDbIndex' value=''/> <input type='hidden' name='guess' value=''/> <input type='hidden' name='noOfUsedGues' value=''/>

The HTML designer assumed we needed 3 hidden variables for storing state information. It is the C programmer's responsibility to update these variables in between page requests. The state variables stored in the HTML page maintains the game's internal state information for the current gamer.

An interesting feature of this game is that it is possible to cheat by pressing the back button in the browser. Say that you almost got hung, but you got some letters right, then all you have to do is to press the back button until you do not see the gallows. You can now restart the game and enter the letters you had right so far. This works because the state variables are stored in the HTML page and the browser cached the old pages. By pressing the back button, you are in fact rewinding the game.

Using a session object for storing the state information would have made it impossible for the gamer to cheat as the state information would have been stored on the server. As you can see, storing state information in hidden variables can lead to unwanted results and a possible security breach in your system.

Writing the C code

We have designed this version of the hangman game in C++. Barracuda is a C library with special C++ wrappers in the header files. The C interface is similar to the C++ interface.

The first we need is the dictionary:
86 struct Word 87 { 88 const char* clue; 89 const char* answer; 90 }; 91 92 const Word wordDB[] = { 93 {"action", "drool"}, 94 {"action", "forecast"}, 95 {"action", "forget"}, ----- more code

This is declared within the <%g %>, the CSP Global tag is typically used for declaring static data in the CSP file.

We can now start looking at what goes into the CSP page's service function. The service function is automatically generated by the CSP compiler. You would not normally see this function unless you look at the C or C++ code generated by the CSP compiler. The web-server calls the service function when the browser requests the page. The C/C++ code in the following CSP tags are executed within the service function: <%p %>, <%e %>, <% %> and <%= %>.

The service function has the following prototype:
Hangman::service(HttpRequest* request, HttpResponse *response)

The request object contains all the information you can possibly get from the client. This information is pre-processed and presented as sub-objects within the request object. For example, a client sending data to the server using POST is pre-parsed by the web-server and stored as objects in the request object.

The response object is used for sending the response message. For example, the CSP compiler extracts all the static HTML data in a CSP file and automatically creates C code for sending the data back to the client using the response object. The embedded C/C++ code within the CSP tags can also use the response object for sending data to the client.

The following code snippet is from within the prolog CSP tag, the <%p > tag. C code within the prolog tag is guaranteed to execute first within the page service function, no matter where in the HTML file you insert the tag:

252 unsigned int i; 253 const char* ch=0; 254 const Word* word=0; 255 int wordDbIndex; 256 const char* guess=0; 257 char* newGuess=0; 258 int noOfUsedGues = 0; 259 HttpParameterIterator fIter(request); 260 /* Extract data from form in the above html */ 261 for( ; fIter.hasMoreElements() ; fIter.nextElement()) 262 { 263 if( ! strcmp(fIter.getName(), "guess") ) 264 guess = fIter.getValue(); 265 else if( ! strcmp(fIter.getName(), "ch") ) 266 ch = fIter.getValue(); 267 else if( ! strcmp(fIter.getName(), "wordDbIndex") ) 268 { 269 wordDbIndex = atoi(fIter.getValue()); 270 word = &wordDB[wordDbIndex]; 271 } 272 else if( ! strcmp(fIter.getName(), "noOfUsedGues") ) 273 noOfUsedGues = atoi(fIter.getValue()); 274 } 275 if(word) /* Should be true unless first time or a new game. 276 * This works since the form in the html above is only 277 * emitted if we are playing a game 278 */ 279 { /* See hangman game for complete source code */ 296 } 297 else /* First time or new game */ 298 { 299 wordDbIndex = rand() % (sizeof(wordDB) / sizeof(wordDB[0])); 300 word = &wordDB[wordDbIndex]; /* See hangman game for complete source code */ 304 }

The above code declares a parameter iterator (line 259), which is used for fetching all of the variables (including the hidden state variables) from the FORM declared in the CSP page. The first request is a GET request and the parameter container will therefore be empty. When the gamer press one of the A to Z letters, the browser will send a POST request and the FORM variables will be retrieved from the parameter container, by using the above HttpParameterIterator.

GET request (Line 298 - 304):

If it is a new game, a new word is randomly selected using "rand()". The current word offset position in the database is later stored in the wordDbIndex hidden HTML variable. This will be explained later.

POST request (Line 279 - 296):

If the gamer presses one of the buttons in the hangman game, the browser sends the FORM data to the server. The loop (line 261 - 274), using the iterator, in the above code extracts the current game's state variables and the A-Z button pressed.

Replacing the HTML comments with CSP tags

It is the C programmer's responsibility to add the dynamic HTML rendering to the HTML page. The C programmer should replace all the comments in the above HTML file with CSP tags.

The first HTML comment in the HTML page is:

<!-- Letters of the correct word and blank spaces here -->

We replace the above comment with the following code:

18 <% 19 for(i = 0; i < strlen(newGuess) ; i++) 20 response->printf("%c ", newGuess[i]); 21 %>

The newGuess variable is a C array, which contains the letters guessed so far. The array is initially filled with underscores and the underscores are replaced by the correct letters when the gamer correctly guesses the letter.

The above loop simply loops trough all the letters in the array and print out the letters and spaces in between. For example, the following may be emitted when a new game is started:

- - - - - - -

The response object is in charge of sending data back to the client. The CSP page automatically emits the static part of the HTML page to the response object. The CSP tags are inserted into the HTML such that we can inject the dynamic content into the page. The printf member function in the response object works like the regular printf function, except for that the data printed is not sent to some console, but to the client browser window.

The comment:

<!-- one of the 8 gallows images here -->

is replaced with:

26 <img src='images/hang<%="%d" noOfUsedGues%>.gif'/>

We have a total of 8 gallows images. The above code emits HTML code for selecting one of the 8 images. The variable noOfUsedGues is a number between 0 and 7, thus the emitted HTML will be <img src='images/hang0.gif'> if the variable noOfUsedGues is zero. The gamer has a total of 6 possible failures before hung, thus the first 6 images (0-5) are images of an appearing gallows. Image 6 is shown if the gamer failed and image 7 is shown if the gamer won.

The next HTML comment is:

<!-- more dynamic text here -->

is replaced with:

31 <p> 32 <font size=+3 color="#ff3333"> 33 <%= noOfUsedGues == 6 ? "Game over." : "You Won!!!"%> 34 </font> 35 </p> 36 <p> 37 <font size=+2 color="#3333cc"> 38 The correct answer is <B><%=word->answer%></B>. 39 </font> 40 </p> 41 Play another game of <a href='hangman.html'>Hangman</a> 42 <% 43 } 44 else 45 { 46 if(noOfUsedGues == 0) 47 { 48 %>

The first condition above is to test for noOfUsedGues = 6 or 7, which means that the game is over. The user won if it is 7 and failed if the variable is 6. A game is still in progress if the variable is between 0 and 5. Please refer to the hangman.html source code for the complete code.

The above CSP code snippets shows how one can make static HTML code conditional by enclosing the HTML code within CSP tags. For example:

<% if(someCondition) { %> <p> The condition is true. </p> <% } else { %> <p> The condition is false. </p> <% } %>

The HTML in the first section will be emitted if the someCondition variable is true, and the second HTML section will be emitted if the someCondition variable is false.

Creating the form and maintaining the state variables

61 <form method='post' action='hangman.html'> 62 <input type='hidden' name='wordDbIndex' value='<%="%d" wordDbIndex%>'/> 63 <input type='hidden' name='guess' value='<%=newGuess%>'/> 64 <input type='hidden' name='noOfUsedGues' value='<%="%d" noOfUsedGues%>'/> 65 <% for(i = 'A'; i <= 'Z'; i++) 66 response->printf("\t\t<input type='submit' name='ch' value='%c'/>\n",i); 67 %> 68 </form>

The first 3 hidden variables in the form are dynamically created by the CSP page every time the gamer fetches a new HTML page from the server. This is how we maintain the game's state information. We showed you how to extract the FORM data from a POST request in the above C++ code snipped (line 261 - 271), by using a HttpParameterIterator.

The next part of the form emits the A to Z buttons. The HTML framework designed by the HTML designer had 26 static input tag fields for the A to Z buttons. The C programmer realized that there is no need to have 26 static input fields when one can dynamically create the 26 fields from a simple loop. This makes the CSP page smaller and thus, one uses less memory.

How it works

A CSP page is converted into C or C++ code by using our CSP compiler. Our CSP compiler is known as CspCompile. The C or C++ code generated by the CspCompiler is compiled into object code using a C/C++ compiler and linked into your application. All of the C/C++ code enclosed within the CSP tags will go into the page service function, which is automatically generated by the CSP compiler.

The C/C++ code produced by the CSP compiler inherits from the HttpPage type. An instance of an HttpPage can be inserted into the virtual file system and will be called by the web-server when a user requests the page. A HttpPage is very similar in functionality to a Java Servlet.

It is also possible to write your own version of an HttpPage and insert the page into the virtual file system. It is sometimes better to write an HttpPage directly instead of using the CSP compiler if the page contains very little presentation but a lot of logic.

If you look at the C++ code generated by the CSP compiler for the Hangman game, you will see that all the C++ code we added to the CSP page is now part of the generated code. You will see the beginning of the service function if you go to line 184. You will also see a "C #line pre-processor directive" a few lines down. The CSP compiler emits line directives into the generated code such that a C compiler can show the correct line number in the HTML file. This means that the C compiler will show you the line of the error in the HTML file if you should make a typo in the embedded C code. Most C compiler supports the #line directive and will show you the CSP page and not the auto-generated C++ code. This is also the case when debugging the code with a debugger.

You will see the following code if you go to line 243:

if(httpWriteSection(this->data,response,this->blocks[0].offset,this->blocks[0].size)) goto L_epilogue;

The code emits one of the static HTML sections we had in the CSP page. The actual data is not embedded into the code, but kept separately in another file. Barracuda is very flexible in the way it handles HTML sections in the CSP pages.

One can have the web-server read the sections from:

If the "httpWriteSection" function returns a negative number, the processor will jump to the epilogue code. We do not use C++ exceptions since most embedded systems do not use them. Instead we use the "goto L_epilogue;", which is to where the <%e >, the code enclosed within the CSP epilogue tag is inserted.

Conclusion

We have now shown you how easy it is to use the CSP tag language for making advanced dynamic HTML on the server side. We have barely scratched the surface of the endless possibilities of the powerful CSP language. Barracuda also provides a massive C and C++ API for working with server side scripting.

Exercise

We discussed the danger of maintaining state information inside the HTML page and that it is better to use a persistent session object for maintaining the state information.

If you have the Barracuda development environment, a good exercise would be to rewrite the game to use a persistent session object for storing the state information.

The CSP page contains many CSP tags and can be hard to read. A better design is to break the CSP page into several pages such that it is easier to read. The pages can be combined at runtime using Httpresponse::include.