| 1 |
\chapter{The high-level interconnect API}\label{chap:h-in} |
| 2 |
\index{high-level interconnect} |
| 3 |
|
| 4 |
\section{Introduction} |
| 5 |
In this chapter, we discuss the {\tt h\_in}-API offered by the NoTA reference |
| 6 |
implementation. |
| 7 |
|
| 8 |
The {\tt h\_in}-API found in the NoTA reference implementation is inspired by |
| 9 |
the BSD Socket API, famously documented by |
| 10 |
Stevens~\cite{Stevens2003}. Generally, the name of the NoTA-function is the |
| 11 |
same as the corresponding BSD function, prefixed with {\tt H}, and taking an |
| 12 |
extra \texttt{h\_in\_t*}-value as its first parameter. |
| 13 |
|
| 14 |
However, as mentioned before, there can be semantic differences between the |
| 15 |
{\tt h\_in}-function and their BSD-counterparts, so you should carefully read |
| 16 |
the documentation -- we try to point out those differences. |
| 17 |
|
| 18 |
\Note{in many cases, using the stub-generator (chapter |
| 19 |
\ref{chap:stubgen}), is an easier alternative to developing NoTA-services than |
| 20 |
using the {\tt h\_in}-API discussed here, directly. However, the stub |
| 21 |
generator is not perfect, and details of {\tt h\_in} may leak through, for |
| 22 |
example when debugging a system. Therefore, a good understanding of what the |
| 23 |
{\tt h\_in} is very useful for understanding NoTA programming as a whole.} |
| 24 |
|
| 25 |
\section{NoTA socket functions} |
| 26 |
|
| 27 |
In this section, we discuss all of the NoTA socket\index{socket} functions |
| 28 |
that the {\tt h\_in}-API offers, in (roughly) the order of appearance in a |
| 29 |
typical program. |
| 30 |
|
| 31 |
Before we go into the functions, first a general note about error |
| 32 |
handling. Errors are an unavoidable aspect of programming after all, and in |
| 33 |
particular network-related programming. |
| 34 |
|
| 35 |
The {\tt h\_in}-API emulates the BSD-API, including its error-handling - |
| 36 |
usually you can get information about errors by inspecting \texttt{errno}, and |
| 37 |
you can get an human-readable version of that by using the |
| 38 |
\texttt{strerror}-function call. The man-pages on your systems have the |
| 39 |
details -- such as the need for some include files to use \texttt{errno} and \texttt{strerror}: |
| 40 |
\begin{lstlisting} |
| 41 |
#include <errno.h> |
| 42 |
#include <string.h> |
| 43 |
\end{lstlisting} |
| 44 |
|
| 45 |
Now, let's go through the function the \texttt{h\_in}-API provides. |
| 46 |
|
| 47 |
\subsection{{\tt Hgetinstance()}} |
| 48 |
\begin{lstlisting} |
| 49 |
h_in_t* Hgetinstance (void); |
| 50 |
\end{lstlisting} |
| 51 |
|
| 52 |
The first thing you need to do when you write a NoTA-program, is acquiring a |
| 53 |
NoTA {\em instance pointer}. The function to do so is called {\tt |
| 54 |
Hgetinstance}; it does not have a counterpart in the BSD-socket API. |
| 55 |
|
| 56 |
Note that you can call this function multiple times, but in the same process |
| 57 |
it will always return the same pointer. Also note that there is no need to |
| 58 |
free the instance pointer; the instance pointer and related resources will be |
| 59 |
freed automatically upon process termination. |
| 60 |
|
| 61 |
\begin{lstlisting} |
| 62 |
h_in_t *inst = Hgetinstance (); |
| 63 |
\end{lstlisting} |
| 64 |
|
| 65 |
Both AN and SN need to get the instance pointer before doing anything else, as |
| 66 |
all other NoTA-function require you to pass this pointer. |
| 67 |
|
| 68 |
\subsubsection{Errors} |
| 69 |
In case of error, \texttt{Hgetinstance} will return \texttt{NULL}. You can |
| 70 |
inspect \texttt{errno} to find out more. A common reason for a failing |
| 71 |
\texttt{Hgetinstance} would be some issue with the runtime-environment; please |
| 72 |
see appendix~\ref{chap:running} for some possible causes and solutions. |
| 73 |
|
| 74 |
\subsection{{\tt Hsocket()}} |
| 75 |
\begin{lstlisting} |
| 76 |
int Hsocket(h_in_t* core, int domain, int type, int protocol); |
| 77 |
\end{lstlisting} |
| 78 |
|
| 79 |
To connect to other NoTA-node, the NoTA reference implementation provides {\em |
| 80 |
sockets}, very similar to BSD-sockets\index{socket}. The reason for this is |
| 81 |
that it provides a familiar API for programmers with a |
| 82 |
UNIX\index{UNIX}-background and there is a lot of documentation available for |
| 83 |
programmers coming from different backgrounds. The {\tt Hsocket}-call is |
| 84 |
analogous to the {\tt socket(3)} call of the BSD socket API. |
| 85 |
|
| 86 |
NoTA sockets come in two flavors: |
| 87 |
\begin{itemize} |
| 88 |
|
| 89 |
\item there are {\em stream sockets}, which are meant for streaming bulk data, |
| 90 |
and |
| 91 |
\item {\em message sockets}, which, instead are use for sending {\em NoTA |
| 92 |
messages} (to be discussed later in this chapter). |
| 93 |
\end{itemize} |
| 94 |
|
| 95 |
NoTA guarantees the message borders on message sockets - that means, messages |
| 96 |
are received as a whole; in contrast, when you use a stream socket, you might |
| 97 |
get only a subset of the message, and getting the rest would require reading |
| 98 |
more from the socket. |
| 99 |
|
| 100 |
\begin{lstlisting} |
| 101 |
/* stream socket */ |
| 102 |
int sock = Hsocket (inst, AF_NOTA, SOCK_STREAM, 0); |
| 103 |
\end{lstlisting} |
| 104 |
\begin{lstlisting} |
| 105 |
/* message socket */ |
| 106 |
int sock = Hsocket (inst, AF_NOTA, SOCK_SEQPACKET, 0); |
| 107 |
\end{lstlisting} |
| 108 |
|
| 109 |
Stream sockets are more efficient for bulk data; message sockets are more |
| 110 |
efficient (and easier to use) for NoTA messages. |
| 111 |
|
| 112 |
If you plan to use \texttt{SOCK\_SEQPACKET}, see the important notes about |
| 113 |
that in the discussion about \texttt{Hrecv}. Here we note that \textbf{both |
| 114 |
sides} of a connection must have the \textbf{same} type, either |
| 115 |
\texttt{SOCK\_STREAM} or \texttt{SOCK\_SEQPACKET}. |
| 116 |
|
| 117 |
As with BSD-sockets, sockets are represented by small integers, and need to be |
| 118 |
closed ({\tt Hclose}) when done with them. |
| 119 |
|
| 120 |
\subsubsection{Errors} |
| 121 |
In case of error, \texttt{Hsocket} will return a negative value, and |
| 122 |
\texttt{errno} will contain an error code: |
| 123 |
\begin{itemize} |
| 124 |
\item \texttt{EINVAL} if \texttt{inst} is invalid, or some internal error occurred; |
| 125 |
\item \texttt{EAFNOSUPPORT} if \texttt{domain} not is \texttt{AF\_NOTA}; |
| 126 |
\item \texttt{EPROTONOSUPPORT} if \texttt{type} not either |
| 127 |
\texttt{SOCK\_STREAM} or \texttt{SOCK\_SEQPACKET}, or if \texttt{protocol} |
| 128 |
not is \texttt{0} (zero); |
| 129 |
\item \texttt{ENONET} if the \texttt{inst} is not ready yet. |
| 130 |
\end{itemize} |
| 131 |
|
| 132 |
Other errors may occur as well. The errors of the BSD's |
| 133 |
\texttt{socket}-function may provide some suggestion as to what went wrong. |
| 134 |
|
| 135 |
\subsection{{\tt Hclose()}} |
| 136 |
\begin{lstlisting} |
| 137 |
int Hclose(h_in_t* core, int sock); |
| 138 |
\end{lstlisting} |
| 139 |
|
| 140 |
When you no longer need a NoTA socket, you should close it, so NoTA can free |
| 141 |
any related resources. Closing a NoTA sockets is done using the {\tt Hclose()} |
| 142 |
call (similar to the UNIX\index{UNIX}{\tt close(3)}-call for file descriptors. |
| 143 |
|
| 144 |
\begin{lstlisting} |
| 145 |
int rv = Hclose (inst, sock); |
| 146 |
\end{lstlisting} |
| 147 |
|
| 148 |
We'd like to emphasize that closing unused NoTA sockets is important as they |
| 149 |
consume quite some system resources. Also, in many cases, a NoTA-socket will |
| 150 |
embed operating system sockets, and there are only of limited number of those |
| 151 |
available (for example, Linux allows \texttt{1024} file descriptors |
| 152 |
(sockets) per process when using default settings). |
| 153 |
|
| 154 |
\subsubsection{Errors} |
| 155 |
As with {\tt close(3)}, it is recommended that you {\bf do} check the return |
| 156 |
value of this call. |
| 157 |
|
| 158 |
In case of error, \texttt{Hclose} will return a negative value, and |
| 159 |
\texttt{errno} will contain an error code: |
| 160 |
\begin{itemize} |
| 161 |
\item \texttt{EINVAL} if \texttt{inst} is invalid, or some internal error |
| 162 |
occurred, |
| 163 |
\item \texttt{EFAULT} if \texttt{inst} is busy or a number of other problems |
| 164 |
occurred; |
| 165 |
\item \texttt{ENOTSOCK} if \texttt{sock} is not a NoTA-socket; |
| 166 |
\item \texttt{EBUSY} if \texttt{sock} is busy. |
| 167 |
\end{itemize} |
| 168 |
|
| 169 |
Other errors may occur as well. The errors of the BSD's |
| 170 |
\texttt{close}-function may provide some suggestion as to what went wrong. |
| 171 |
|
| 172 |
\subsection{{\tt Hconnect()}} |
| 173 |
\begin{lstlisting} |
| 174 |
int Hconnect(h_in_t* core, int sockid, struct sockaddr* addr, |
| 175 |
socklen_t addrlen); |
| 176 |
\end{lstlisting} |
| 177 |
|
| 178 |
Application nodes use the {\tt Hconnect}-function to connect to service |
| 179 |
nodes, very similar to what the {\tt connect(3)} call does in the BSD API. |
| 180 |
|
| 181 |
\begin{lstlisting} |
| 182 |
static nota addr t addr = { 1, 1 }; /* NoTA-address */ |
| 183 |
int rv = Hconnect (inst, sock, (struct sockaddr*)&addr, sizeof(addr)); |
| 184 |
\end{lstlisting} |
| 185 |
|
| 186 |
This call will (try to) connect to some NoTA-id, which is a structure of three |
| 187 |
values; the {\tt h\_in} defines it as follows: |
| 188 |
\begin{lstlisting} |
| 189 |
typedef unsigned int sid_t; |
| 190 |
typedef unsigned int vdid_t; |
| 191 |
|
| 192 |
struct nota_addr { |
| 193 |
sid_t sid; /* service identifier */ |
| 194 |
unsigned int port; /* port of the sid */ |
| 195 |
vdid_t device; /* virtual device id */ |
| 196 |
}; |
| 197 |
typedef struct nota_addr nota_addr_t; |
| 198 |
\end{lstlisting} |
| 199 |
|
| 200 |
The virtual device id is not currently in use; the other two values are: |
| 201 |
\begin{itemize} |
| 202 |
\item the {\em service id}(SID)\index{service-id}. This number uniquely |
| 203 |
references a specific Service Node - unique within the context of a NoTA |
| 204 |
network. |
| 205 |
\item the {\em port number}\index{port-number}. Similar to a TCP/UDP-port |
| 206 |
number, this number identifies a specific service exposed by a service |
| 207 |
node. For example, a Service Node could have one port open for commands |
| 208 |
({\tt play()}, {\tt pause()}), and another one for actually streaming the |
| 209 |
data. |
| 210 |
\end{itemize} |
| 211 |
|
| 212 |
The recommended way to get these numbers is by using the resource manager (to |
| 213 |
be discussed in chapter~\ref{chap:rm}); however, for simple examples you can |
| 214 |
define them manually as well. |
| 215 |
|
| 216 |
Also note that \texttt{Hsocket} is a \emph{blocking} call. If, for example, no |
| 217 |
\texttt{NOTA\_LMANAGER} has been defined (see appendix~\ref{chap:running}), |
| 218 |
the call might hang your application, and you cannot mark the socket as |
| 219 |
'non-blocking'. |
| 220 |
|
| 221 |
\subsubsection{Errors} |
| 222 |
In case of error, \texttt{Hconnect} will return a negative value, and |
| 223 |
\texttt{errno} will contain an error code: |
| 224 |
\begin{itemize} |
| 225 |
\item \texttt{EINVAL} if \texttt{inst} is invalid, or some internal error |
| 226 |
occurred, |
| 227 |
\item \texttt{EFAULT} if \texttt{inst} is busy or a number of other problems |
| 228 |
occurred; |
| 229 |
\item \texttt{ECONNREFUSE} the other side of the connection was not |
| 230 |
listening, or not accepting connections; |
| 231 |
\item \texttt{ENETUNREACH} if \texttt{sock} cannot reach the |
| 232 |
network\footnote{the internal error is that IA cannot be retrieved; further |
| 233 |
discussion is beyond the scope of this document}; |
| 234 |
\item \texttt{ENOTSOCK} if \texttt{sock} is not a NoTA-socket. |
| 235 |
\end{itemize} |
| 236 |
|
| 237 |
Other errors may occur as well. The errors of the BSD's |
| 238 |
\texttt{connect}-function may provide some suggestion as to what went wrong. |
| 239 |
|
| 240 |
\subsection{{\tt Hsend()}} |
| 241 |
\begin{lstlisting} |
| 242 |
int Hsend(h_in_t* core, int sockid, const void* buf, int len, int flags); |
| 243 |
\end{lstlisting} |
| 244 |
|
| 245 |
Now, let's assume we have connected to some Service Node (using {\tt |
| 246 |
Hconnect()}. We can send some data to it, using the {\tt Hsend}-function, |
| 247 |
similar to what the {\tt send(3)} function does in the BSD-API. |
| 248 |
|
| 249 |
\begin{lstlisting} |
| 250 |
const char* str = ¨Hello, world!¨; |
| 251 |
int sent = Hsend (inst, sock, str, strlen(str), 0); |
| 252 |
\end{lstlisting} |
| 253 |
This will send the data through the socket. The function returns the number of |
| 254 |
bytes actually sent (in case of streaming sockets, this may be smaller than |
| 255 |
the amount requested), or -1 in case of error. In case of errors, you {\tt |
| 256 |
errno} to get some information about what went wrong. |
| 257 |
|
| 258 |
Most of the arguments should be straightforward to understand, but let's look |
| 259 |
at the last one, {\tt flags}. This parameter should be either zero (default |
| 260 |
behavior), or {\tt MSG\_DONTWAIT}. In the latter case, we're sending data in |
| 261 |
{\em non-blocking}-mode\index{non-blocking}: if the data cannot be sent |
| 262 |
immediately (that is, it would block if we would try), the function will |
| 263 |
return with a value of {\tt EAGAIN} (think: '\textit{try again later}'). |
| 264 |
|
| 265 |
{\bf Important note}: in the above example, we are sending some simple string |
| 266 |
over the NoTA-socket; this is a valid way when sending opaque data to some |
| 267 |
Service Node. However, to send specific messages to other NoTA-nodes (for |
| 268 |
example, sending a {\tt play()} or {\tt pause()} message to an music player |
| 269 |
SN), we need the the NoTA service signal syntax which is discussed in |
| 270 |
section~\ref{sec:notaservicesignals}. |
| 271 |
|
| 272 |
Another important thing to remember is that for scalability and dealing with |
| 273 |
many sockets at the same time, you might want to use {\tt Hselect()}, to be |
| 274 |
discussed later. |
| 275 |
|
| 276 |
\subsubsection{Errors} |
| 277 |
In case of error, \texttt{Hsend} will return a negative value, and |
| 278 |
\texttt{errno} will contain an error code: |
| 279 |
\begin{itemize} |
| 280 |
\item \texttt{EINVAL} if \texttt{inst} is invalid, or some internal error |
| 281 |
occurred, |
| 282 |
\item \texttt{EFAULT} if \texttt{inst} is busy or a number of other problems |
| 283 |
occurred; |
| 284 |
\item \texttt{EMSGSIZE} if the message size is exceeding the |
| 285 |
maximum\footnote{currently defined at \texttt{4096}} (on |
| 286 |
\texttt{SOCK\_SEQPACKET}-sockets; |
| 287 |
\item \texttt{ENOTCONN} if the socket is not connected; |
| 288 |
\item \texttt{ENOTSOCK} if \texttt{sock} is not a NoTA-socket. |
| 289 |
\end{itemize} |
| 290 |
|
| 291 |
Other errors may occur as well. The errors of the BSD's |
| 292 |
\texttt{send}-function may provide some suggestion as to what went wrong. |
| 293 |
|
| 294 |
\subsection{{\tt Hrecv()}} |
| 295 |
\begin{lstlisting} |
| 296 |
int Hrecv(h_in_t* core, int sockid, void* buf, int len, int flags); |
| 297 |
\end{lstlisting} |
| 298 |
|
| 299 |
To receive data from a NoTA socket, we can use the {\tt Hrecv}-function, which |
| 300 |
is the NoTA-version of {\tt recv(3)}. |
| 301 |
|
| 302 |
Let's assume we are connected to some Service Node, we've sent it some message |
| 303 |
(see section~\label{sec:notaservicesignals}), and we are now waiting for the |
| 304 |
the SN to send us some bytes in reply. For this, we need {\tt Hrecv}. An |
| 305 |
example: |
| 306 |
\begin{lstlisting} |
| 307 |
char buf[10]; |
| 308 |
int received = Hrecv (inst, sock, buf, sizeof(buf), 0); |
| 309 |
\end{lstlisting} |
| 310 |
This will get us up to 10 bytes from the socket. |
| 311 |
|
| 312 |
\subsubsection{Blocking or not} |
| 313 |
The {\bf flags} argument influences how the \texttt{Hrecv} operates; if you specify |
| 314 |
{\tt MSG\_DONTWAIT}, we receive data in {\em non-blocking}-mode; that is, if |
| 315 |
data cannot be received immediately, the function will return with a value of |
| 316 |
{\tt EAGAIN}, instead of blocking, which is the default. If you specify {\tt |
| 317 |
MSG\_WAITALL}, the function will not return until the function received {\tt |
| 318 |
len} bytes. In practice, this is of limited use. You can specify multiple |
| 319 |
flags by doing a bitwise-OR, just like with the BSD-{\tt recv}. |
| 320 |
|
| 321 |
\subsubsection{Using \texttt{MSG\_PEEK} and \texttt{MSG\_TRUNC}} |
| 322 |
Two other important flags to \texttt{Hrecv} are \texttt{MSG\_PEEK} and |
| 323 |
\texttt{MSG\_TRUNC}. The first one causes the \texttt{Hrecv} \textbf{not} to |
| 324 |
consume the read data -- if you read again, you will get the same data. The |
| 325 |
use of \texttt{MSG\_PEEK} is not necessarily implemented for all transports, |
| 326 |
which can lead to problems. We therefore discourage its use in most cases. |
| 327 |
|
| 328 |
There is one exception to this: when using \texttt{SOCK\_SEQPACKET}, it is |
| 329 |
often useful to find out the size of the next \emph{message}, so sufficient buffer |
| 330 |
space can be allocated. We discuss messages only later in this chapter, but |
| 331 |
here it suffices today that NoTA-messages are of \emph{variable-length}, and one |
| 332 |
cannot determine the actual length of the whole message without parsing |
| 333 |
it. This would make parsing message very tedious and involving many little |
| 334 |
\texttt{Hrecv}s, error checking an so on. |
| 335 |
|
| 336 |
Thankfully, there is a way to get the length of the next available |
| 337 |
message\footnote{The BSD-API also offers \texttt{recvmsg} and |
| 338 |
\texttt{sendmsg}, but they don't have NoTA counterparts}: using the |
| 339 |
\texttt{MSG\_TRUNC}-flag. This flag causes \texttt{Hrecv} return the length |
| 340 |
of the \emph{next available message} - even if this length is more than the |
| 341 |
\texttt{len}-argument to \texttt{Hrecv}. So, what happens when the message |
| 342 |
size is bigger than the buffer size? |
| 343 |
|
| 344 |
Good question. Look at the name of the flag again - \texttt{MSG\_TRUNC} - |
| 345 |
indeed, the rest of the data will be \emph{truncated}, i.e., thrown away. That |
| 346 |
is usually not what we want, so we can use \texttt{MSG\_PEEK} for that. |
| 347 |
|
| 348 |
The pattern to read a full message in one go would then be: |
| 349 |
\begin{lstlisting} |
| 350 |
sock = Hsocket (inst, AF_NOTA, SOCK_SEQPACKET, 0); |
| 351 |
[...] /* waiting for some message...*/ |
| 352 |
|
| 353 |
int size = Hrecv (inst, sock, dummy, 1, MSG_TRUNC|MSG_PEEK); |
| 354 |
if (size > 0) { |
| 355 |
/* get a 'buf' of a least `size' bytes */ |
| 356 |
read = Hrecv (inst, sock, buf, size, 0); |
| 357 |
/* now we should have the full message in `buf` */ |
| 358 |
} else .... |
| 359 |
\end{lstlisting} |
| 360 |
|
| 361 |
Again, you'll probably need to go through chapter~\ref{chap:messages} (about |
| 362 |
NoTA messages) to fully appreciate this - just take a mental note now. |
| 363 |
|
| 364 |
\subsubsection{Errors} |
| 365 |
In case of error, \texttt{Hrecv} will return a negative value, and |
| 366 |
\texttt{errno} will contain an error code: |
| 367 |
\begin{itemize} |
| 368 |
\item \texttt{EINVAL} if \texttt{inst} is invalid, or some internal error |
| 369 |
occurred, |
| 370 |
\item \texttt{EFAULT} if \texttt{inst} is busy or a number of other problems |
| 371 |
occurred; |
| 372 |
\item \texttt{ENOTSOCK} if \texttt{sock} is not a NoTA-socket. |
| 373 |
\end{itemize} |
| 374 |
|
| 375 |
Other errors may occur as well. The errors of the BSD's |
| 376 |
\texttt{recv}-function may provide some suggestion as to what went wrong. |
| 377 |
|
| 378 |
\subsection{{\tt Hbind()}} |
| 379 |
\begin{lstlisting} |
| 380 |
int Hbind(h_in_t* core, int sockfd, struct sockaddr* my_addr, |
| 381 |
socklen_t addrlen); |
| 382 |
\end{lstlisting} |
| 383 |
|
| 384 |
To bind our socket to a certain (NoTA) port, we need {\em Hbind} to that port, |
| 385 |
similar to what BSD's {\tt bind(3)} does. This would look something like the |
| 386 |
following: |
| 387 |
\begin{lstlisting} |
| 388 |
static nota_addr_t addr = { 1, 1 }; |
| 389 |
int rv = Hbind (inst, sock, (struct sockaddr*)&addr, |
| 390 |
sizeof(addr)); |
| 391 |
\end{lstlisting} |
| 392 |
|
| 393 |
{\tt Hbind} is useful for NoTA Service Nodes, to make them available for |
| 394 |
application nodes. After you have successfully called {\tt Hbind}, you should |
| 395 |
call {\tt Hlisten} to actually start the listening. Application nodes could |
| 396 |
use {\tt Hbind} as well, to specify the port {\em they} would like to use - |
| 397 |
but often, we don't really care about that. |
| 398 |
|
| 399 |
It's important to remember that while they have the same function, NoTA ports |
| 400 |
are {\bf not} the same as TCP/UDP-ports. |
| 401 |
|
| 402 |
Also note that \texttt{Hbind} is a \emph{blocking} call. If, for example, no |
| 403 |
\texttt{NOTA\_LMANAGER} has been defined (see appendix~\ref{chap:running}), |
| 404 |
the call might hang your application, and you cannot mark the socket as |
| 405 |
'non-blocking'. |
| 406 |
|
| 407 |
\subsubsection{Errors} |
| 408 |
In case of error, \texttt{Hbind} will return a negative value, and |
| 409 |
\texttt{errno} will contain an error code: |
| 410 |
\begin{itemize} |
| 411 |
\item \texttt{EINVAL} if there is something wrong with the parameters, |
| 412 |
\item \texttt{EFAULT} if the \texttt{sock} could not be found, or something |
| 413 |
else is wrong; |
| 414 |
\item \texttt{EBADF} if \texttt{sock} is invalid; |
| 415 |
\item \texttt{ENOTSOCK} if \texttt{sock} is of the wrong type; |
| 416 |
\item \texttt{EADDRINUSE} if the address has already been bound; |
| 417 |
\end{itemize} |
| 418 |
|
| 419 |
Other errors may occur as well. The errors of the BSD's |
| 420 |
\texttt{bind}-function may provide some suggestion as to what went wrong. |
| 421 |
|
| 422 |
\subsection{{\tt Hlisten()}} |
| 423 |
\begin{lstlisting} |
| 424 |
int Hlisten(h_in_t* core, int sockid, int backlog); |
| 425 |
\end{lstlisting} |
| 426 |
|
| 427 |
After you have bound a socket to some port with {\tt Hbind}, you can put the |
| 428 |
socket in listening mode with {\tt Hlisten}, similar to BSD's {\tt |
| 429 |
listen(3)}. You can specify the maximum number of outstanding connections |
| 430 |
with the {\tt backlog} parameter. |
| 431 |
|
| 432 |
\begin{lstlisting} |
| 433 |
int rv = Hlisten (core, sock, 1); |
| 434 |
\end{lstlisting} |
| 435 |
|
| 436 |
After this, your socket is ready to accept connections. This is mostly useful |
| 437 |
for service nodes. After setting your socket to listening mode, you can start |
| 438 |
the actual listening with {\tt Haccept}. |
| 439 |
|
| 440 |
\subsubsection{Errors} |
| 441 |
In case of error, \texttt{Hlisten} will return a negative value, and |
| 442 |
\texttt{errno} will contain an error code: |
| 443 |
\begin{itemize} |
| 444 |
\item \texttt{EINVAL} if there is something wrong with the parameters, |
| 445 |
\item \texttt{EFAULT} if the \texttt{sock} could not be found, or something |
| 446 |
else is wrong; |
| 447 |
\item \texttt{ENOTSOCK} if \texttt{sock} is of the wrong type; |
| 448 |
\item \texttt{ENOTSUP} if \texttt{sock} does not support listening. |
| 449 |
\end{itemize} |
| 450 |
|
| 451 |
Other errors may occur as well. The errors of the BSD's |
| 452 |
\texttt{listen}-function may provide some suggestion as to what went wrong. |
| 453 |
|
| 454 |
\subsection{{\tt Haccept()}} |
| 455 |
\begin{lstlisting} |
| 456 |
int Haccept(h_in_t* core, int sockid, struct sockaddr* addr, |
| 457 |
socklen_t* addrlen); |
| 458 |
\end{lstlisting} |
| 459 |
Now, after we have bound our socket to a port (using {\tt Hbind}), and set it |
| 460 |
to listening mode (using {\tt Hlisten)}), we are now ready to accept |
| 461 |
connections from clients. This final step is done with {\tt Haccept}, which |
| 462 |
blocks\index{blocking} until some client (application node) opens a |
| 463 |
connection. When the connection is accepted, {\tt Haccept} returns the {\em |
| 464 |
peer socket}, that is, a socket on which the communication with the client |
| 465 |
can take place. |
| 466 |
|
| 467 |
For example: |
| 468 |
\begin{lstlisting} |
| 469 |
peersock = Haccept (inst, sock, NULL, NULL); |
| 470 |
\end{lstlisting} |
| 471 |
|
| 472 |
In a diversion from BSD's {\tt accept(3)}, {\tt Haccept} does {\bf not} return |
| 473 |
any information about this peer socket in its last two arguments. {\tt |
| 474 |
Haccept} includes them for the sake of following BSD as close as possible, |
| 475 |
but the actual parameters are ignored. |
| 476 |
|
| 477 |
Note that {\tt Haccept} is a synchronous, {\bf blocking}\index{blocking} |
| 478 |
call. Thus, in order to be able to serve multiple clients (Application |
| 479 |
Nodes), some multiprocessing mechanism is needed, such as forking or |
| 480 |
threading. |
| 481 |
|
| 482 |
\subsubsection{Errors} |
| 483 |
In case of error, \texttt{Haccept} returns a negative value, and |
| 484 |
\texttt{errno} will contain an error code: |
| 485 |
\begin{itemize} |
| 486 |
\item \texttt{EINVAL} if there is something wrong with the parameters; |
| 487 |
\item \texttt{EFAULT} if the \texttt{sock} could not be found, or something |
| 488 |
else is wrong; |
| 489 |
\item \texttt{ENOTSOCK} if \texttt{sock} is not a socket, or of the wrong |
| 490 |
type; |
| 491 |
\item \texttt{ENOTCONN} if \texttt{sock} is not connected. |
| 492 |
\end{itemize} |
| 493 |
|
| 494 |
Other errors may occur as well. The errors of the BSD's |
| 495 |
\texttt{accept}-function may provide some suggestion as to what went wrong. |
| 496 |
|
| 497 |
|
| 498 |
\subsection{{\tt Hselect()}} |
| 499 |
\begin{lstlisting} |
| 500 |
int Hselect(h_in_t* inst, int nfd, fd_set* read_fds, fd_set* write_fds, |
| 501 |
fd_set* error_fds, struct timeval* tv); |
| 502 |
\end{lstlisting} |
| 503 |
The {\tt Hselect} function allows you to multiplex over sets of NoTA |
| 504 |
sockets. That is, it monitors sets of NoTA sockets, and finds out which ones |
| 505 |
are ready for reading or writing, and for which ones errors |
| 506 |
occurred. '\emph{Ready}' here means that they can be either read or written |
| 507 |
without blocking. |
| 508 |
|
| 509 |
The final {\tt tv} argument (a {\tt struct timeval*}) specifies the maximum |
| 510 |
amount of time {\tt Hselect} is allowed to take\footnote{Note that the actual |
| 511 |
timeout the reference implementation uses {\tt ceil(tv->tv\_sec + |
| 512 |
tv->tv\_usec)}; timeout values with sub-second resolution are not |
| 513 |
possible.}. |
| 514 |
A value of zero means that the function will \textbf{instantly return}; |
| 515 |
passing \texttt{NULL}-pointer means that \texttt{Hselect} should wait |
| 516 |
indefinitely until one some changes for one of the sockets it manages -- |
| 517 |
becomes ready for reading or writing, or some error occurred. |
| 518 |
|
| 519 |
For dealing with the {\tt fd\_set}-arguments, the familiar {\tt FD\_}-macros |
| 520 |
can be used: |
| 521 |
\begin{itemize} |
| 522 |
\item {\tt FD\_ZERO} - clears a set; |
| 523 |
\item {\tt FD\_SET} - add a given NoTA socket to the set; |
| 524 |
\item {\tt FD\_CLEAR} - remove a given NoTA socket from the set; |
| 525 |
\item {\tt FD\_ISSET} - is the given NoTA socket an element of the set? |
| 526 |
\end{itemize} |
| 527 |
|
| 528 |
Like its counterpart \texttt{select}, \texttt{Hselect} is a rather complicated |
| 529 |
function; hopefully we can clarify with the example below. It describes a |
| 530 |
function \texttt{is\_socket\_ready\_for\_reading}, that check whether one |
| 531 |
specific socket can now be read without blocking, while the |
| 532 |
\texttt{Hselect}-call itself blocks for up to two seconds. |
| 533 |
|
| 534 |
If you \textbf{don't} want to block at all, you should set the |
| 535 |
\texttt{tv}-parameters to \texttt{\{0,0\}}. If you set it to \texttt{NULL}, |
| 536 |
there is no timeout (i.e., \texttt{Hselect} may block indefinitely in that |
| 537 |
case). |
| 538 |
|
| 539 |
\begin{lstlisting} |
| 540 |
int |
| 541 |
is_socket_ready_for_reading (fd_set fds_socks, int socks_num, int sock) |
| 542 |
{ |
| 543 |
int rv; |
| 544 |
|
| 545 |
struct timeval tv = { 2, 0 }; /* wait two seconds at most */ |
| 546 |
fd_set read_fds = fds_socks; /* fd_sets are just numbers */ |
| 547 |
|
| 548 |
rv = Hselect (inst, sock_num, |
| 549 |
&read_fds, /* read */ |
| 550 |
NULL, /* write */ |
| 551 |
NULL, /* error */ |
| 552 |
&tv); /* timeout */ |
| 553 |
if (rv < 0) |
| 554 |
/* error handling... */; |
| 555 |
|
| 556 |
|
| 557 |
/* return 1 if socket is ready for reading, 0 otherwise */ |
| 558 |
return FD_ISSET(sock, read_fds); |
| 559 |
} |
| 560 |
\end{lstlisting} |
| 561 |
|
| 562 |
\subsubsection{Errors} |
| 563 |
In case of error, \texttt{Hselect} will return a negative value, and |
| 564 |
\texttt{errno} will contain an error code: |
| 565 |
\begin{itemize} |
| 566 |
\item \texttt{EINVAL} if there is something wrong with the parameters; |
| 567 |
\item \texttt{EFAULT} if the \texttt{sock} could not be found, or something |
| 568 |
else is wrong; |
| 569 |
\item \texttt{EBADF} if there's some invalid socket in any of the sets; |
| 570 |
\item \texttt{ENOMEM} if there's not enough memory available. |
| 571 |
\end{itemize} |
| 572 |
|
| 573 |
Other errors may occur as well. The errors of the BSD's |
| 574 |
\texttt{select}-function may provide some suggestion as to what went wrong. |
| 575 |
|
| 576 |
\subsection{{\tt Hsetsockopt()}} |
| 577 |
\begin{lstlisting} |
| 578 |
int Hsetsockopt(h_in_t* core, int sockid, int level, int optname, |
| 579 |
void* optval, socklen_t optlen); |
| 580 |
\end{lstlisting} |
| 581 |
With the {\tt Hsetsockopt}-function, one can manipulate various NoTA socket |
| 582 |
details, similar to BSD's {\tt setsockopt(3)}. |
| 583 |
|
| 584 |
Currently, the only option one can set on a NoTA socket is {\tt SO\_PASSCRED}; |
| 585 |
also, the {\bf level}-parameter must be equal to {\tt SOL\_SOCKET}. |
| 586 |
\begin{lstlisting} |
| 587 |
const char* str = ¨JOSHUA¨; |
| 588 |
rv = Hsetsockopt(inst, sock, SOL_SOCKET, SO_PASSCRED, str, strlen(str)); |
| 589 |
\end{lstlisting} |
| 590 |
|
| 591 |
The {\tt SO\_PASSCRED}-parameter can be read on the other side of the |
| 592 |
connection (with {\tt Hgetsockopt()}, and as such be use for somewhat secure |
| 593 |
authentication if there is some out-of-band mechanism for sharing the secret |
| 594 |
securely beforehand. |
| 595 |
|
| 596 |
\subsubsection{Errors} |
| 597 |
In case of error, \texttt{Hsetsockopt} will return a negative value, and |
| 598 |
\texttt{errno} will contain an error code: |
| 599 |
\begin{itemize} |
| 600 |
\item \texttt{EINVAL} if there is something wrong with the parameters; note, |
| 601 |
currently level \textbf{must} be \texttt{SOL\_SOCKET} and \texttt{optname} |
| 602 |
\textbf{must} be \texttt{SO\_PASSCRED}; |
| 603 |
\item \texttt{EFAULT} if the \texttt{sock} could not be found, or something |
| 604 |
else is wrong. |
| 605 |
\end{itemize} |
| 606 |
|
| 607 |
Other errors may occur as well. The errors of the BSD's |
| 608 |
\texttt{setsockopt}-function may provide some suggestion as to what went wrong. |
| 609 |
|
| 610 |
\subsection{{\tt Hgetsockopt()}} |
| 611 |
\begin{lstlisting} |
| 612 |
int Hgetsockopt(h_in_t* core, int sockid, int level, int optname, |
| 613 |
void* optval, socklen_t* optlen); |
| 614 |
\end{lstlisting} |
| 615 |
With the {\tt Hgetsockopt}-function, you can retrieve various NoTA socket |
| 616 |
details, similar to BSD's {\tt getsockopt(3)}. |
| 617 |
|
| 618 |
Currently, the only option available on a NoTA socket is {\tt SO\_PASSCRED}; |
| 619 |
also, the {\bf level} parameter must be equal to {\tt SOL\_SOCKET}. |
| 620 |
\begin{lstlisting} |
| 621 |
char buf[16]; |
| 622 |
rv = Hgetsockopt(inst, sock, SOL_SOCKET, SO_PASSCRED, |
| 623 |
&buf, sizeof(buf)); |
| 624 |
\end{lstlisting} |
| 625 |
|
| 626 |
The {\tt SO\_PASSCRED}-parameter (which may be set with {\tt Hsetsockopt} on |
| 627 |
the other side of the connection) can be used for authentication purposes, |
| 628 |
using some pre-shared secret with 'the other side'. |
| 629 |
|
| 630 |
\subsubsection{Errors} |
| 631 |
In case of error, \texttt{Hgetsockopt} will return a negative value, and |
| 632 |
\texttt{errno} will contain an error code: |
| 633 |
\begin{itemize} |
| 634 |
\item \texttt{EINVAL} if there is something wrong with the parameters; note, |
| 635 |
currently level \textbf{must} be \texttt{SOL\_SOCKET} and \texttt{optname} |
| 636 |
\textbf{must} be \texttt{SO\_PASSCRED}; also \texttt{*optlen} must be $>$ 0; |
| 637 |
\item \texttt{EFAULT} if the \texttt{sock} could not be found, or something |
| 638 |
else is wrong. |
| 639 |
\end{itemize} |
| 640 |
|
| 641 |
Other errors may occur as well. The errors of the BSD's |
| 642 |
\texttt{getsockopt}-function may provide some suggestion as to what went wrong. |
| 643 |
|
| 644 |
\section{Questions} |
| 645 |
To test your understanding of this chapter, you could try to answer some of |
| 646 |
these questions. You can find the answers to these question in |
| 647 |
appendix~\ref{chap:answers}. |
| 648 |
\begin{enumerate} |
| 649 |
\item Can you list some differences between the BSD socket API and the |
| 650 |
NoTA H\_in API? |
| 651 |
\item Which API function can you use to send data to another node? |
| 652 |
\end{enumerate} |