| 1 |
\chapter{Using the H\_IN: an example}\label{chap:h-in-example} |
| 2 |
\begin{quote} |
| 3 |
Nihil nobis metuendum est, pr{\ae}ter metum ipsum.\\ |
| 4 |
-- Julius Caesar |
| 5 |
\end{quote} |
| 6 |
|
| 7 |
In chapter~\ref{chap:h-in}, we discussed the {\tt h\_in}-API and in |
| 8 |
chapter~\ref{chap:messages} we went through the message syntax. |
| 9 |
|
| 10 |
In this chapter we combine and apply that knowledge in a |
| 11 |
simple\footnote{simple in concept, not so much in implementation} example. We |
| 12 |
hope that this clarifies the material shown before, and also answers some of |
| 13 |
the greater questions of where this all leads to. |
| 14 |
|
| 15 |
{\bf Caveat lector:} this chapter discusses the details of programming NoTA |
| 16 |
using the {\tt H\_IN}-API directly. This is good for understanding the |
| 17 |
backgrounds, but you may not need all of that. You can use the {\bf stub |
| 18 |
generator} (discussed in chapter~\ref{chap:stubgen}) instead, which hides |
| 19 |
many of the low-level details |
| 20 |
|
| 21 |
The previous chapters are a prerequisite for understanding this chapter; you |
| 22 |
might also find it useful to have the {\tt h\_in}-man pages available. The |
| 23 |
man-pages are part of your NoTA-installation; see |
| 24 |
appendix~\ref{chap:installation} for details. |
| 25 |
|
| 26 |
\section{Caesar cypher}\index{Caesar cypher} |
| 27 |
To gain some good understanding of the {\tt h\_in} \index{high-level |
| 28 |
interconnect}, simple examples work best. So, we hope that you can forgive |
| 29 |
us that the example is rather useless as a real-world use case. And, already |
| 30 |
in the simple example, the implementation gets rather complicated. |
| 31 |
|
| 32 |
For the example in this chapter, we will use a service node (SN) that |
| 33 |
implements a {\em Caesar cypher}\footnote{for some background, see: {\tt |
| 34 |
http://en.wikipedia.org/wiki/Caesar\_cipher}}\index{Caesar cypher} - a simple |
| 35 |
encryption technique where the characters in a string (circularly) shifted |
| 36 |
over some fixed number of positions up or down the alphabet. |
| 37 |
|
| 38 |
Now, suppose we want to implement a server that can handle the encryption |
| 39 |
operation. It should handle messages\index{message} of the form: |
| 40 |
\begin{verbatim} |
| 41 |
caesar_crypt_req (bdat1 text, int8 shift); |
| 42 |
\end{verbatim} |
| 43 |
Some notes: |
| 44 |
\begin{itemize} |
| 45 |
\item it would be natural to think of this as a {\em function}, but for our |
| 46 |
purposes, it's better to think of as a {\em message}. For example, it does |
| 47 |
not have a return value; |
| 48 |
\item we call the function {\tt caesar\_crypt\_{\bf req}} to emphasize that it |
| 49 |
is a {\bf request}; note that it can be used for both encryption and |
| 50 |
decryption; |
| 51 |
\item we only support the 26 lower-case characters in the English |
| 52 |
alphabet, so {\tt shift} parameter has an effective range of [-25, 25]. |
| 53 |
\end{itemize} |
| 54 |
|
| 55 |
Now, after the service node has received such a {\tt |
| 56 |
caesar\_crypt\_req}-message and all the parameters are correct, it can execute |
| 57 |
the operation and respond with a message: |
| 58 |
\begin{verbatim} |
| 59 |
caesar_crypt_rsp (bdat1 text); |
| 60 |
\end{verbatim} |
| 61 |
Of course, it could be that we received {\em incorrect} parameters. For |
| 62 |
example, the text should not contain a characters outside the {\tt |
| 63 |
[a-z]}-range, and the shift parameter should be in range as well. In case of |
| 64 |
such a problem, we can respond with an error notification: |
| 65 |
\begin{verbatim} |
| 66 |
caesar_crypt_error_rsp (uint8 code); |
| 67 |
\end{verbatim} |
| 68 |
|
| 69 |
Summarizing, there are three messages: two to be handled by the server (SN), |
| 70 |
one by the client. |
| 71 |
|
| 72 |
\section{Implementation} |
| 73 |
Now, let's look at implementing an AN and an SN for this, to show how it all |
| 74 |
works. For our implementation, we use plain C, and we're assuming a |
| 75 |
UNIX/Linux-like environment. We need to do the following: |
| 76 |
\begin{itemize} |
| 77 |
\item write the common definitions; |
| 78 |
\item write the service node; |
| 79 |
\item write the client node. |
| 80 |
\end{itemize} |
| 81 |
You could choose a different order, of course. |
| 82 |
|
| 83 |
\subsection{Common definitions} |
| 84 |
The first thing we should do is to identify the common things that are needed |
| 85 |
for both AN and SN, put those in a common header file {\tt caesar-common.h}. |
| 86 |
|
| 87 |
The first thing we need to do, is to define an address\footnote{In a more |
| 88 |
realistic case, you could get the address from the resource manager (discussed |
| 89 |
in chapter~\ref{chap:rm})} for the SN -- a {\tt nota\_addr\_t} that the AN can |
| 90 |
use to find it, similar to having a IP-number in a network. |
| 91 |
|
| 92 |
For this example, we simply hard-code it. As we saw in in the previous |
| 93 |
chapter, a NoTA-address is defined as an array of two numbers. So, we define |
| 94 |
our service address (arbitrarily): |
| 95 |
\begin{lstlisting} |
| 96 |
#define CAESAR_SN_ADDRESS {1,1} |
| 97 |
\end{lstlisting} |
| 98 |
The other common definitions are the signal-id's for the three messages we |
| 99 |
need: |
| 100 |
\begin{lstlisting} |
| 101 |
/* signal id's: */ |
| 102 |
/* (1) implemented by the SN */ |
| 103 |
#define CAESAR_CRYPT_REQ_SIGID 0x0001 |
| 104 |
|
| 105 |
/* (2) implemented by the AN */ |
| 106 |
#define CAESAR_CRYPT_RSP_SIGID 0x0002 |
| 107 |
#define CAESAR_CRYPT_ERROR_RSP_SIGID 0x0003 |
| 108 |
\end{lstlisting} |
| 109 |
|
| 110 |
We also declare the \texttt{caesar\_handle\_message}-function, which we can |
| 111 |
reuse in both AN and SN. |
| 112 |
|
| 113 |
That's all for {\tt caesar-common.h}. |
| 114 |
|
| 115 |
\subsection{Writing a service node} |
| 116 |
|
| 117 |
\subsubsection{Service node socket handling} |
| 118 |
Now, let's see how we can write a service node\index{service node}. If you |
| 119 |
have ever written servers using BSD-sockets, this will all look very |
| 120 |
familiar. If you are not familiar with BSD-sockets, see |
| 121 |
\cite{Beej2009}\footnote{direct URL: http://www.beej.us/guide/bgnet/} for a |
| 122 |
gentle introduction. |
| 123 |
|
| 124 |
In the following, we'll go through this implementation. The full source code |
| 125 |
is available in appendix~\ref{chap:example}; here we show a slightly shorter |
| 126 |
version -- without error checking. The example {\bf has} error-checking |
| 127 |
though, as it is very important, especially since examples are sometimes |
| 128 |
copy-pasted for use in 'real' programs... |
| 129 |
|
| 130 |
The first thing is {\em not} in BSD though -- we start by getting a NoTA |
| 131 |
instance pointer: |
| 132 |
\begin{lstlisting} |
| 133 |
h_in_t *inst; |
| 134 |
inst = Hgetinstance (); |
| 135 |
\end{lstlisting} |
| 136 |
|
| 137 |
Easy. If that went well, we can ask NoTA to give us a a socket. |
| 138 |
\begin{lstlisting} |
| 139 |
int sock; |
| 140 |
sock = Hsocket (inst, AF_NOTA, SOCK_SEQPACKET, 0); |
| 141 |
\end{lstlisting} |
| 142 |
|
| 143 |
Note that we are using {\tt SOCK\_SEQPACKET} here; as explained in the |
| 144 |
previous chapter, this is the best choice when a socket is meant for messages |
| 145 |
as in this case, as the system guarantees that we get the {\bf whole message |
| 146 |
in one go}. |
| 147 |
|
| 148 |
The alternative, {\tt SOCK\_STREAM}, is more efficient for sending bulk data, |
| 149 |
such as files and multimedia content. |
| 150 |
|
| 151 |
Now we have our socket, and like to {\em bind} it to some address - we're |
| 152 |
telling the system that this sockets has some particular address. For that, |
| 153 |
there is the {\tt Hbind}-function: |
| 154 |
\begin{lstlisting} |
| 155 |
nota_addr_t addr = CAESAR_SN_ADDRESS; |
| 156 |
Hbind (inst, sock, (struct sockaddr*)&addr, sizeof(addr)); |
| 157 |
\end{lstlisting} |
| 158 |
This will bind our socket to {\tt CAESAR\_SN\_ADDRESS}, so the AN can find it. |
| 159 |
|
| 160 |
Before that, we have to put the socket in {\em listening mode}, using {\tt |
| 161 |
Hlisten}: |
| 162 |
\begin{lstlisting} |
| 163 |
Hlisten (inst, sock, 1); |
| 164 |
\end{lstlisting} |
| 165 |
We set the last {\em backlog} parameter to 1, but it's not really important |
| 166 |
in this simple example. |
| 167 |
|
| 168 |
Now, we have done all the preparatory things, and we can start listening on |
| 169 |
the socket for incoming messages. We use the simplest possible way of doing |
| 170 |
that: using {\tt Haccept}: |
| 171 |
\begin{lstlisting} |
| 172 |
int peersock; |
| 173 |
peersock = Haccept (inst, sock, NULL, NULL); |
| 174 |
\end{lstlisting} |
| 175 |
|
| 176 |
This function will {\bf block} (i.e., wait) for an incoming connection. When |
| 177 |
there is an incoming connection, it will return a socket in {\tt peersock}, |
| 178 |
which is the socket over which the communication with the other side (the |
| 179 |
peer) can take place. |
| 180 |
|
| 181 |
Note that the last two parameters are {\tt NULL}, as they are ignored in NoTA |
| 182 |
(not in BSD) - see the previous chapter for the details. |
| 183 |
|
| 184 |
After we accepted a connection (with {\tt Haccept}), we need to decode the |
| 185 |
bytes we get and figure out what to do with them. This is discussed in the |
| 186 |
next paragraph; here, we continue with the discussion of the socket handling. |
| 187 |
|
| 188 |
Finally, when we are done with our with our SN, we can close the socket with |
| 189 |
{\tt Hclose}: |
| 190 |
\begin{lstlisting} |
| 191 |
Hclose (inst, sock); |
| 192 |
\end{lstlisting} |
| 193 |
In this example, we never really reach that code, as the SN will only be |
| 194 |
terminated by manual interaction (e.g.., {\tt Ctrl-C}), and all it's sockets |
| 195 |
will be closed then. |
| 196 |
|
| 197 |
\subsubsection{Service node message handling}\label{subsubsec:snmsghandling} |
| 198 |
So, we accepted a connection from 'the other side'. We'd now like to read the |
| 199 |
bytes available, and decode that into a message (if needed, consult |
| 200 |
chapter~\ref{chap:messages} for the details on coding/decoding). |
| 201 |
|
| 202 |
In both the service node and the application node, we will need message |
| 203 |
handling, so we define a function \texttt{caesar\_get\_message} in |
| 204 |
\texttt{caesar-common.h}; see the appendix for the actual code, but you will |
| 205 |
probably agree that it requires some careful coding to read NoTA-messages. |
| 206 |
|
| 207 |
\texttt{caesar\_get\_message} returns us the signal-id for the received |
| 208 |
message; we then need to write the code for the various message handling |
| 209 |
functions to extract the parameters from the data. This is rather tedious, as |
| 210 |
we have to be check at each step; we can never assume that the data is |
| 211 |
correct. For example, BDAT-values have their length embedded --if we blindly |
| 212 |
accept that value, it would easily lead to buffer overflows\index{buffer |
| 213 |
overflow}. |
| 214 |
|
| 215 |
We defined only one possible message for the service node: |
| 216 |
\begin{verbatim} |
| 217 |
caesar_crypt_req (bdat1 text, int8 shift); |
| 218 |
\end{verbatim} |
| 219 |
|
| 220 |
What would the corresponding bytes look like? Well: |
| 221 |
\begin{itemize} |
| 222 |
\item the message should start with the typecode for a signal-id, followed |
| 223 |
by the signal-id itself. As we've seen, the typecode for a two-byte signal |
| 224 |
id is {\tt 0xa2}. And we defined the signal id as {\tt |
| 225 |
CAESAR\_CRYPT\_REQ\_SIGID} (value: {\tt 0x0001}); |
| 226 |
\item then follows the {\tt text} parameter, the string in a {\tt BDAT1}; this will |
| 227 |
be encoded as {\tt 0x41} followed by one byte for the {\em length}, and |
| 228 |
then the bytes for the string itself; |
| 229 |
\item finally, there is the {\tt shift} parameter, which is in {\tt INT8}; |
| 230 |
this will be encoded as {\tt 0x21} followed by one byte for the value. |
| 231 |
\end{itemize} |
| 232 |
|
| 233 |
To put it all together: |
| 234 |
\begin{tabular} {| l | l | l |} |
| 235 |
\hline |
| 236 |
{\tt 0xa2} {\tt 0x0001} & {\tt 0x41} {\em n} {\em $bytes_{1\dots n}$} & {\tt |
| 237 |
0x21} {\em byte} \\ |
| 238 |
\hline |
| 239 |
\end{tabular} |
| 240 |
|
| 241 |
Using this information, we can read the bytes from the socket using {\tt |
| 242 |
Hrecv}. This is rather tedious, as we must verify that we get what we are |
| 243 |
supposed to get. The Service Node cannot make any assumptions on the validity |
| 244 |
of the data. |
| 245 |
|
| 246 |
\subsubsection{{\tt caesar-sn.c}} |
| 247 |
Now, we have discussed all the relevant details for writing the Caesar service |
| 248 |
node; see {\tt caesar-sn.c} in appendix~\ref{chap:example}. Additionally, |
| 249 |
appendix~\ref{chap:building} has information on how to build the examples, |
| 250 |
link with the NoTA-libraries and so on. |
| 251 |
|
| 252 |
\subsection{Writing an application node}\label{subsec:appnode} |
| 253 |
We have seen how we can write the service node for our Caesar example. We now |
| 254 |
continue with the application node\index{application node}. As before, we go |
| 255 |
through the relevant details here, and then refer to |
| 256 |
appendix~\ref{chap:example} for the actual source code. And as before, the |
| 257 |
code is bit tedious because of the manual processing of the bytes in the |
| 258 |
message. |
| 259 |
|
| 260 |
We go through the code once more. We omit the error handling here, but there |
| 261 |
{\bf is} error handling in the example code. The first implementation steps |
| 262 |
for the AN are the same as those for the SN: we need to get an instance |
| 263 |
pointer\index{instance pointer} and a socket\index{socket}: |
| 264 |
|
| 265 |
\begin{lstlisting} |
| 266 |
h_in_t *inst; |
| 267 |
int sock; |
| 268 |
|
| 269 |
inst = Hgetinstance (); |
| 270 |
sock = Hsocket (inst, AF_NOTA, SOCK_SEQPACKET, 0); |
| 271 |
\end{lstlisting} |
| 272 |
|
| 273 |
Again, we are using {\tt SOCK\_SEQPACKET}, which is the best choice for NoTA |
| 274 |
messages. |
| 275 |
|
| 276 |
For an application node, we usually don't care about its (source) port; |
| 277 |
therefore it is {\em not necessary} to call {\tt Hbind} to connect it to a |
| 278 |
particular port. We'll happily leave that to NoTA. Also, we don't need to call |
| 279 |
{\tt Hlisten} to put our socket in {\em listening mode}, because the AN |
| 280 |
initiates the connection. |
| 281 |
|
| 282 |
We can now connect to the Service Node using {\tt Hconnect}: |
| 283 |
\begin{lstlisting} |
| 284 |
nota_addr_t addr = CAESAR_SN_ADDRESS; |
| 285 |
Hconnect (inst, sock, (struct sockaddr*)&addr, sizeof(addr)); |
| 286 |
\end{lstlisting} |
| 287 |
|
| 288 |
When {\tt Hconnect} has succeeded, we are ready to send our messages to the |
| 289 |
SN. We have already seen how to {\em de}code a message in the discussion about |
| 290 |
the service node; now we need to {\em en}code such a message. |
| 291 |
|
| 292 |
\subsubsection{Sending requests to the service node} |
| 293 |
Remember, the message for the service node looks like the following: |
| 294 |
\begin{verbatim} |
| 295 |
caesar_crypt_req (bdat1 text, int8 shift); |
| 296 |
\end{verbatim} |
| 297 |
Obviously, the message we sent should have the same format as the one the SN |
| 298 |
is to receive; have a look at the details in |
| 299 |
paragraph~\ref{subsubsec:snmsghandling}. As we have seen, the final result |
| 300 |
looks like this: |
| 301 |
\begin{tabular} {| l | l | l |} |
| 302 |
\hline |
| 303 |
{\tt 0xa2} {\tt 0x0001} & {\tt 0x41} {\em n} {\em $bytes_{1\dots n}$} & {\tt |
| 304 |
0x21} {\em byte} \\ |
| 305 |
\hline |
| 306 |
\end{tabular} |
| 307 |
|
| 308 |
We can send these bytes to the SN using {\tt Hsend}. Refer to |
| 309 |
appendix~\ref{chap:example} for the source code. |
| 310 |
|
| 311 |
\subsubsection{Handling responses from the service node} |
| 312 |
|
| 313 |
\section{Compiling and running the example} |
| 314 |
Now, let's see how we can run the Caesar cypher example. |
| 315 |
\subsection{Compilation} |
| 316 |
The first step is to {\em compile} the example. Please refer to |
| 317 |
appendix\ref{chap:building} for general information about compiling NoTA-based |
| 318 |
software, and see appendix~\ref{chap:example} for a {\tt Makefile} for the |
| 319 |
Caesar cypher example. |
| 320 |
\subsection{Running} |
| 321 |
TODO |
| 322 |
|
| 323 |
\section{Questions} |
| 324 |
To test your understanding of this chapter, you could try to answer some of |
| 325 |
these questions. You can find the answers to these question in |
| 326 |
appendix~\ref{chap:answers}. |
| 327 |
\begin{enumerate} |
| 328 |
\item In the examples, we read from the socket using {\tt MSG\_WAITALL}; |
| 329 |
however, we can be sure that it won't block in all but the first {\tt |
| 330 |
Hrecv}. Why can we be sure? (Hint: think about the kind of socket this is). |
| 331 |
\item NoTA nodes (ANs and SNs) can communicate fully asynchronously; so how |
| 332 |
can the AN know which of the {\tt caesar\_crypt\_rsp} (or {\tt |
| 333 |
caesar\_crypt\_error\_rsp}) is a response to which {\tt |
| 334 |
caesar\_crypt\_rsp}? (Hint: this is a trick question) |
| 335 |
\item Suppose that someone complains that our Caesar cypher is not secure |
| 336 |
enough. For extra security, we'd like to add the functionality to {\em |
| 337 |
revert} a text too. Adapt the Service Node such that it accepts a second |
| 338 |
message |
| 339 |
\begin{verbatim} |
| 340 |
caesar_revert_req (bdat1 text); |
| 341 |
\end{verbatim} |
| 342 |
which will cause the text to be reverted (for the signal id, you can use |
| 343 |
{\tt 0x0004}). Also, update the AN to send this message. |
| 344 |
\item (Bonus question) The Caesar cypher with a shift parameter of 13 is |
| 345 |
better known as {\tt ROT-13}. What's the longest word you can find that has |
| 346 |
the property that its ROT-13 encoding is equal to the {\em reverse} of the |
| 347 |
word? |
| 348 |
\end{enumerate} |