| 1 |
\chapter{Using the stub-generator: an example}\label{chap:stubgen-example} |
| 2 |
\index{stub-generator} |
| 3 |
|
| 4 |
\section{Introduction} |
| 5 |
In this chapter we'll redo the Caesar-Cypher example of |
| 6 |
chapter~\ref{chap:h-in-example}, now using the stub-generator. You will see |
| 7 |
that it saves quite a bit of work. Also, as the emphasis is less on byte-level |
| 8 |
details, it's easier to think about what our ANs and SNs should actually |
| 9 |
accomplish. |
| 10 |
|
| 11 |
\section{Writing the service definition} |
| 12 |
\subsection{Messages and types} |
| 13 |
Let's look at the messages for the Caesar Cypher again. Using the shorthand |
| 14 |
notation that we invented in the previous chapter, they would look something |
| 15 |
like: |
| 16 |
\begin{verbatim} |
| 17 |
in: [0x0001] caesar_crypt_req (nota:bdata text, nota:int8 shift); |
| 18 |
out: [0x0002] caesar_crypt_rsp (nota:bdata text); |
| 19 |
out: [0x0003] caesar_crypt_error_rsp (caesar:error_t code); |
| 20 |
\end{verbatim} |
| 21 |
So, we define three messages, one to be implemented by the SN, and the two |
| 22 |
others to be implemented by the AN. |
| 23 |
|
| 24 |
Furthermore, we define on custom type, \texttt{caesar:status\_t}, which |
| 25 |
describes an error code. |
| 26 |
|
| 27 |
\subsection{Writing some XML} |
| 28 |
The next step is to rewrite our shorthand notation into the proper service |
| 29 |
file syntax. |
| 30 |
|
| 31 |
\subsubsection{Definitions} |
| 32 |
First, we need to write the \texttt{definitions}-element; as we mentioned in |
| 33 |
the previous chapter, it's attributes are ignored for now, but for |
| 34 |
informational value, we fill in the \texttt{name}-attribute: |
| 35 |
\begin{verbatim} |
| 36 |
<definitions name="caesar"> |
| 37 |
\end{verbatim} |
| 38 |
|
| 39 |
\subsubsection{Types} |
| 40 |
Then comes the \texttt{types}-section, for custom types. In this case, we only |
| 41 |
have one custom type, \texttt{caesar:error\_t}, which is a simple enumeration; |
| 42 |
we write: |
| 43 |
\begin{lstlisting}[language=XML] |
| 44 |
<types> |
| 45 |
<simpleType name="caesar:error_t"> |
| 46 |
<restriction base="nota:uns8"> |
| 47 |
<enumeration value="0x1000">E_GENERAL_ERROR</enumeration> |
| 48 |
<enumeration value="0x1010">E_INVALID_DATA</enumeration> |
| 49 |
<enumeration value="0x1020">E_INVALID_SHIFT</enumeration> |
| 50 |
</restriction> |
| 51 |
</simpleType> |
| 52 |
</types> |
| 53 |
\end{lstlisting} |
| 54 |
|
| 55 |
\subsubsection{Messages} |
| 56 |
Now all that is left is to write down the XML for \texttt{caesar\_crypt\_req}, |
| 57 |
\texttt{caesar\_crypt\_rsp} and \texttt{caesar\_crypt\_error\_rsp}. With what |
| 58 |
we have learned so far, we think the definition of these messages should be |
| 59 |
pretty straightforward. |
| 60 |
|
| 61 |
\begin{lstlisting}[language=XML] |
| 62 |
<message name="caesar_crypt_req" code="0x0001" direction="in"> |
| 63 |
<documentation> |
| 64 |
request Caesar crypt operation on data |
| 65 |
</documentation> |
| 66 |
<part name="text" type="nota:bdata"> |
| 67 |
<documentation> |
| 68 |
Data to crypt or encrypt |
| 69 |
</documentation> |
| 70 |
</part> |
| 71 |
<part name="shift" type="nota:int8"> |
| 72 |
<documentation> |
| 73 |
Positions to shift (rotate) |
| 74 |
</documentation> |
| 75 |
</part> |
| 76 |
</message> |
| 77 |
|
| 78 |
<message name="caesar_crypt_cnf" code="0x0002" direction="out"> |
| 79 |
<documentation> |
| 80 |
Return the encrypted or decrypted data |
| 81 |
</documentation> |
| 82 |
<part name="text" type="nota:bdata"> |
| 83 |
<documentation> |
| 84 |
Encrypted or decrypted data |
| 85 |
</documentation> |
| 86 |
</part> |
| 87 |
</message> |
| 88 |
|
| 89 |
<message name="caesar_crypt_error_rsp" code="0x0003" direction="out"> |
| 90 |
<documentation> |
| 91 |
Return an error code |
| 92 |
</documentation> |
| 93 |
<part name="code" type="caesar:error_t"> |
| 94 |
<documentation> |
| 95 |
Error code in case some encryption/decryption operation went wrong |
| 96 |
</documentation> |
| 97 |
</part> |
| 98 |
</message> |
| 99 |
\end{lstlisting} |
| 100 |
|
| 101 |
And that was all. You can find the complete \texttt{caesar.xml} in appendix~\ref{chap:example}. |
| 102 |
|
| 103 |
\section{Generating the stubs} |
| 104 |
As discussed in chapter~\ref{chap:stubgen}, we can use the stub-generator to |
| 105 |
generate stubs\index{stub}, i.e. machine generated source code files that take |
| 106 |
care of lot of the low-level plumbing code. Let's see what happens. |
| 107 |
|
| 108 |
\begin{lstlisting}[language=sh] |
| 109 |
nota-stubgen3.pl -platform posix . ./caesar.xml |
| 110 |
\end{lstlisting} |
| 111 |
|
| 112 |
will create: |
| 113 |
\begin{itemize} |
| 114 |
\item For the application node: \texttt{caesar\_user.c} and |
| 115 |
\texttt{caesar\_user.h}. |
| 116 |
|
| 117 |
For each message in the service description with |
| 118 |
\texttt{direction=\"in\"}, a wrapper function is generated. For messages |
| 119 |
with \texttt{direction=\"out\"} a declaration is generated, for which we |
| 120 |
need to write an implementation. In both cases, the stub-generator takes |
| 121 |
care of translating the bytes in function arguments and vice versa; |
| 122 |
|
| 123 |
\item For the Service Node: \texttt{caesar\_service.c} and |
| 124 |
\texttt{caesar\_service.h}. |
| 125 |
|
| 126 |
The code that is generated is similar to that for application node, but with |
| 127 |
the \texttt{direction=\"in\"} and \texttt{direction=\"out\"} swapped' |
| 128 |
|
| 129 |
\item \texttt{caesar\_common.h}: common definitions for \texttt{user} and |
| 130 |
\texttt{service}. |
| 131 |
|
| 132 |
\end{itemize} |
| 133 |
|
| 134 |
\section{Writing the Service Node} |
| 135 |
Now, let's take a look at the implementing the service node. As seen in the |
| 136 |
previous section, we have \texttt{caesar\_service.c} and |
| 137 |
\texttt{caesar\_service.h}. Looking at the header file |
| 138 |
(\texttt{caesar\_service.h}), we find the following\footnote{if you worry |
| 139 |
about the double \texttt{caesar\_}-prefix: this is due to the message having |
| 140 |
caesar in their names, and also as the overall namespace. Nothing to worry |
| 141 |
about} |
| 142 |
\begin{lstlisting}[language=c,caption={\texttt{caesar\_service.h} (fragment)}] |
| 143 |
/* Stubs that can be used to send messages */ |
| 144 |
|
| 145 |
/* Return the encrypted or decrypted data */ |
| 146 |
/* Encrypted or decrypted data */ |
| 147 |
int caesar_caesar_crypt_cnf( struct context_pointer* context, uns8* text, |
| 148 |
uns16 text_len ); |
| 149 |
|
| 150 |
/* Return an error code */ |
| 151 |
/* Error code in case some encryption/decryption operation went wrong */ |
| 152 |
int caesar_caesar_crypt_error_rsp( struct context_pointer* context, |
| 153 |
error_code_t code ); |
| 154 |
|
| 155 |
|
| 156 |
/* Skeleton prototypes; user must implement them. */ |
| 157 |
void caesar_caesar_crypt_req_process( struct context_pointer* context, |
| 158 |
uns8* text, uns16 text_len, int8 shift ); |
| 159 |
|
| 160 |
\end{lstlisting} |
| 161 |
|
| 162 |
So, all we need to do is implement the last function |
| 163 |
\texttt{caesar\_caesar\_crypt\_req\_process}. |
| 164 |
|
| 165 |
\texttt{caesar\_service.c} contains the plumbing code, and you \textbf{could} |
| 166 |
add your implementation there. However, it's better to put your own |
| 167 |
implementation in a separate \texttt{.c}-file. This is much easier if your |
| 168 |
WSDL ever changes and you need to regenerate the stubs. |
| 169 |
|
| 170 |
In general, it is not a very good idea to change the WSDL after your code has |
| 171 |
left the development phase - interfaces should be stable. If you \emph{do} |
| 172 |
change interfaces that are used by others, make sure you don't leave your name |
| 173 |
in the source code. |
| 174 |
|
| 175 |
It's also a good idea to put the service-startup code in a separate file; so, |
| 176 |
we add two files: \texttt{caesar\_service\_impl.c} (with our implementation of |
| 177 |
the \texttt{caesar\_service.h}-functions) and \texttt{caesar-sn.c}, which |
| 178 |
contains \texttt{main()} and the starts the service. |
| 179 |
|
| 180 |
\section{Writing an application node} |
| 181 |
|
| 182 |
\begin{lstlisting}[language=c,caption={\texttt{caesar\_user.h}(fragment)}] |
| 183 |
/* Stubs that can be used to send messages */ |
| 184 |
|
| 185 |
/* request Caesar crypt operation on data */ |
| 186 |
/* Data to crypt or encrypt */ |
| 187 |
/* Positions to shift (rotate) */ |
| 188 |
int caesar_caesar_crypt_req( struct context_pointer* context, uns8* text, |
| 189 |
uns16 text_len, int8 shift ); |
| 190 |
|
| 191 |
|
| 192 |
/* Skeleton prototypes; user must implement them. */ |
| 193 |
void caesar_caesar_crypt_cnf_process( struct context_pointer* context, |
| 194 |
uns8* text, uns16 text_len ); |
| 195 |
|
| 196 |
void caesar_caesar_crypt_error_rsp_process( struct context_pointer* context, |
| 197 |
error_code_t code ); |
| 198 |
|
| 199 |
\end{lstlisting} |
| 200 |
|
| 201 |
Analogous to what we did for the SN, we add two files: |
| 202 |
\texttt{caesar\_user\_impl.c} (with our implementation of the |
| 203 |
\texttt{caesar\_user.h}-functions) and \texttt{caesar-an.c}, which contains |
| 204 |
\texttt{main()} and the starts the application node. |
| 205 |
|
| 206 |
We need to implement So, all we need to do is implement the last function |
| 207 |
\texttt{caesar\_caesar\_crypt\_cnf\_process} and |
| 208 |
\texttt{caesar\_caesar\_crypt\_error\_rsp\_process}. |
| 209 |
|
| 210 |
|
| 211 |
\section{Building and running} |
| 212 |
Now that we have written the code for AN and SN, it'd be nice to compile and |
| 213 |
run them. |
| 214 |
|
| 215 |
\subsection{Makefile} |
| 216 |
The easiest way to build the AN and SN is by creating a \texttt{Makefile}. The |
| 217 |
details of writing Makefiles is out of the scope of this guide, |
| 218 |
|
| 219 |
|
| 220 |
\subsection{running} |
| 221 |
|
| 222 |
|
| 223 |
\section{Questions} |
| 224 |
To test your understanding of this chapter, you could try to answer some of |
| 225 |
these questions. You can find the answers to these question in |
| 226 |
appendix~\ref{chap:answers}. |
| 227 |
\begin{enumerate} |
| 228 |
\item Why is it not a good idea to add you own code to |
| 229 |
\texttt{caesar\_service.c} or \texttt{caesar\_user.c}? |
| 230 |
\end{enumerate} |