diff options
Diffstat (limited to 'doc/gnunet-c-tutorial.tex')
-rw-r--r-- | doc/gnunet-c-tutorial.tex | 285 |
1 files changed, 114 insertions, 171 deletions
diff --git a/doc/gnunet-c-tutorial.tex b/doc/gnunet-c-tutorial.tex index 069c1838f..2b4a0d8e1 100644 --- a/doc/gnunet-c-tutorial.tex +++ b/doc/gnunet-c-tutorial.tex | |||
@@ -1,12 +1,13 @@ | |||
1 | \documentclass[10pt]{article} | 1 | \documentclass[10pt]{article} |
2 | \usepackage[ansinew]{inputenc} | 2 | \usepackage[ansinew]{inputenc} |
3 | \usepackage{makeidx,amsmath,amssymb,exscale,multicol,epsfig,graphics,verbatim,ulem} | 3 | \usepackage{makeidx,amsmath,amssymb,exscale,multicol,epsfig,graphics,verbatim,ulem} |
4 | \usepackage{epsfig,geometry,url,listings, subcaption} | 4 | \usepackage{epsfig,geometry,url,listings,subcaption} |
5 | \usepackage{boxedminipage} | 5 | \usepackage{boxedminipage} |
6 | \usepackage[T1]{fontenc}%required | 6 | \usepackage[T1]{fontenc}%required |
7 | \usepackage{textcomp} | 7 | \usepackage{textcomp} |
8 | \geometry{headsep=3ex,hscale=0.9} | 8 | \geometry{headsep=3ex,hscale=0.9} |
9 | \usepackage{hyperref} | 9 | \usepackage{hyperref} |
10 | \usepackage{color} | ||
10 | \hypersetup{pdftitle={GNUnet C Tutorial}, | 11 | \hypersetup{pdftitle={GNUnet C Tutorial}, |
11 | pdfsubject={GNUnet}, | 12 | pdfsubject={GNUnet}, |
12 | pdfauthor={Christian Grothoff <christian@grothoff.org>}, | 13 | pdfauthor={Christian Grothoff <christian@grothoff.org>}, |
@@ -28,6 +29,26 @@ literate={*}{{\char42}}1 | |||
28 | 29 | ||
29 | \begin{document} | 30 | \begin{document} |
30 | 31 | ||
32 | \lstset{ % | ||
33 | language=C, % choose the language of the code | ||
34 | basicstyle=\footnotesize, % the size of the fonts that are used for the code | ||
35 | numbers=left, % where to put the line-numbers | ||
36 | numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers | ||
37 | stepnumber=1, % the step between two line-numbers. If it is 1 each line will be numbered | ||
38 | numbersep=5pt, % how far the line-numbers are from the code | ||
39 | backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color} | ||
40 | showspaces=false, % show spaces adding particular underscores | ||
41 | showstringspaces=false, % underline spaces within strings | ||
42 | showtabs=false, % show tabs within strings adding particular underscores | ||
43 | frame=single, % adds a frame around the code | ||
44 | tabsize=2, % sets default tabsize to 2 spaces | ||
45 | captionpos=b, % sets the caption-position to bottom | ||
46 | breaklines=true, % sets automatic line breaking | ||
47 | breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace | ||
48 | escapeinside={\%*}{*)} % if you want to add a comment within your code | ||
49 | } | ||
50 | |||
51 | |||
31 | \begin{center} | 52 | \begin{center} |
32 | \large {A Tutorial for GNUnet 0.10.x (C version)} | 53 | \large {A Tutorial for GNUnet 0.10.x (C version)} |
33 | 54 | ||
@@ -68,20 +89,25 @@ You should also download the signature file and verify the integrity of the tarb | |||
68 | \url{ftp://ftp.gnu.org/gnu/gnunet/gnunet-0.10.x.tar.gz.sig} | 89 | \url{ftp://ftp.gnu.org/gnu/gnunet/gnunet-0.10.x.tar.gz.sig} |
69 | \end{center} | 90 | \end{center} |
70 | To verify the signature you should first import the GPG key used to sign the tarball | 91 | To verify the signature you should first import the GPG key used to sign the tarball |
92 | \lstset{language=bash} | ||
71 | \begin{lstlisting} | 93 | \begin{lstlisting} |
72 | $ gpg --keyserver keys.gnupg.net --recv-keys 48426C7E | 94 | $ gpg --keyserver keys.gnupg.net --recv-keys 48426C7E |
73 | \end{lstlisting} | 95 | \end{lstlisting} |
74 | And use this key to verify the tarball's signature | 96 | And use this key to verify the tarball's signature |
97 | \lstset{language=bash} | ||
75 | \begin{lstlisting} | 98 | \begin{lstlisting} |
76 | $ gpg --verify gnunet-0.10.x.tar.gz.sig gnunet-0.10.x.tar.gz | 99 | $ gpg --verify gnunet-0.10.x.tar.gz.sig gnunet-0.10.x.tar.gz |
77 | \end{lstlisting} | 100 | \end{lstlisting} |
78 | After successfully verifying the integrity you can extract the tarball using | 101 | After successfully verifying the integrity you can extract the tarball using |
102 | \lstset{language=bash} | ||
79 | \begin{lstlisting} | 103 | \begin{lstlisting} |
80 | $ tar xvzf gnunet-0.10.x.tar.gz | 104 | $ tar xvzf gnunet-0.10.x.tar.gz |
81 | $ mv gnunet-0.10.x gnunet # we will use the directory "gnunet" in the remainder of this document | 105 | $ mv gnunet-0.10.x gnunet # we will use the directory "gnunet" in the remainder of this document |
82 | $ cd gnunet | 106 | $ cd gnunet |
83 | \end{lstlisting} | 107 | \end{lstlisting} |
84 | 108 | ||
109 | However, please note that stable versions can be very outdated, as a developer | ||
110 | you are strongly encouraged to use the version from \url{https://gnunet.org/git/}. | ||
85 | 111 | ||
86 | \subsection{Installing Build Tool Chain and Dependencies} | 112 | \subsection{Installing Build Tool Chain and Dependencies} |
87 | 113 | ||
@@ -116,15 +142,15 @@ The remainder of this tutorial assumes that you have Git Master checked out. | |||
116 | \subsection{Compiling and Installing GNUnet} | 142 | \subsection{Compiling and Installing GNUnet} |
117 | 143 | ||
118 | First, you need to install at least {\tt libgnupgerror} version | 144 | First, you need to install at least {\tt libgnupgerror} version |
119 | 1.12\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.12.tar.bz2}} | 145 | 1.27\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.27.tar.bz2}} |
120 | and {\tt libgcrypt} version | 146 | and {\tt libgcrypt} version |
121 | 1.6\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.6.0.tar.bz2}}. | 147 | 1.7.6\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.6.tar.bz2}}. |
122 | 148 | ||
123 | \lstset{language=bash} | 149 | \lstset{language=bash} |
124 | \begin{lstlisting} | 150 | \begin{lstlisting} |
125 | $ wget ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.12.tar.bz2 | 151 | $ wget ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.27.tar.bz2 |
126 | $ tar xf libgpg-error-1.12.tar.bz2 | 152 | $ tar xf libgpg-error-1.27.tar.bz2 |
127 | $ cd libgpg-error-1.12 | 153 | $ cd libgpg-error-1.27 |
128 | $ ./configure | 154 | $ ./configure |
129 | $ sudo make install | 155 | $ sudo make install |
130 | $ cd .. | 156 | $ cd .. |
@@ -132,9 +158,9 @@ $ cd .. | |||
132 | 158 | ||
133 | \lstset{language=bash} | 159 | \lstset{language=bash} |
134 | \begin{lstlisting} | 160 | \begin{lstlisting} |
135 | $ wget ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.6.0.tar.bz2 | 161 | $ wget ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.6.tar.bz2 |
136 | $ tar xf libgcrypt-1.6.0.tar.bz2 | 162 | $ tar xf libgcrypt-1.7.6.tar.bz2 |
137 | $ cd libgcrypt-1.6.0 | 163 | $ cd libgcrypt-1.7.6 |
138 | $ ./configure | 164 | $ ./configure |
139 | $ sudo make install | 165 | $ sudo make install |
140 | $ cd .. | 166 | $ cd .. |
@@ -176,12 +202,14 @@ $ touch ~/.config/gnunet.conf | |||
176 | You should check your installation to ensure that installing GNUnet | 202 | You should check your installation to ensure that installing GNUnet |
177 | was successful up to this point. You should be able to access GNUnet's | 203 | was successful up to this point. You should be able to access GNUnet's |
178 | binaries and run GNUnet's self check. | 204 | binaries and run GNUnet's self check. |
205 | \lstset{language=bash} | ||
179 | \begin{lstlisting} | 206 | \begin{lstlisting} |
180 | $ which gnunet-arm | 207 | $ which gnunet-arm |
181 | \end{lstlisting} | 208 | \end{lstlisting} |
182 | should return \lstinline|$PREFIX/bin/gnunet-arm|. It should be | 209 | should return \lstinline|$PREFIX/bin/gnunet-arm|. It should be |
183 | located in your GNUnet installation and the output should not be | 210 | located in your GNUnet installation and the output should not be |
184 | empty. If you see an output like: | 211 | empty. If you see an output like: |
212 | \lstset{language=bash} | ||
185 | \begin{lstlisting} | 213 | \begin{lstlisting} |
186 | $ which gnunet-arm | 214 | $ which gnunet-arm |
187 | $ | 215 | $ |
@@ -189,29 +217,20 @@ $ | |||
189 | check your {\tt PATH} variable to ensure GNUnet's {\tt bin} directory is included. | 217 | check your {\tt PATH} variable to ensure GNUnet's {\tt bin} directory is included. |
190 | 218 | ||
191 | GNUnet provides tests for all of its subcomponents. Run | 219 | GNUnet provides tests for all of its subcomponents. Run |
220 | \lstset{language=bash} | ||
192 | \begin{lstlisting} | 221 | \begin{lstlisting} |
193 | $ make check | 222 | $ make check |
194 | \end{lstlisting} | 223 | \end{lstlisting} |
195 | to execute tests for all components. {\tt make check} traverses all subdirectories in {\tt src}. | 224 | to execute tests for all components. {\tt make check} traverses all subdirectories in {\tt src}. |
196 | For every subdirectory you should get a message like this: | 225 | For every subdirectory you should get a message like this: |
197 | 226 | ||
198 | \begin{lstlisting} | 227 | \begin{verbatim} |
199 | make[2]: Entering directory `/home/$USER/gnunet/contrib' | 228 | make[2]: Entering directory `/home/$USER/gnunet/contrib' |
200 | PASS: test_gnunet_prefix | 229 | PASS: test_gnunet_prefix |
201 | ============= | 230 | ============= |
202 | 1 test passed | 231 | 1 test passed |
203 | ============= | 232 | ============= |
204 | \end{lstlisting} | 233 | \end{verbatim} |
205 | |||
206 | If you see a message like this: | ||
207 | |||
208 | \begin{lstlisting} | ||
209 | Mar 12 16:57:56-642482 resolver-api-19449 ERROR Must specify `HOSTNAME' for `resolver' in configuration! | ||
210 | Mar 12 16:57:56-642573 test_program-19449 ERROR Assertion failed at resolver_api.c:204. | ||
211 | /bin/bash: line 5: 19449 Aborted (core dumped) ${dir}$tst | ||
212 | FAIL: test_program | ||
213 | \end{lstlisting} | ||
214 | double check the steps performed in ~\ref{sub:install} | ||
215 | 234 | ||
216 | 235 | ||
217 | \section{Background: GNUnet Architecture} | 236 | \section{Background: GNUnet Architecture} |
@@ -262,6 +281,7 @@ First of all we need to configure your peer. Each peer is started with a configu | |||
262 | 281 | ||
263 | Since we want to start additional peers later, we need | 282 | Since we want to start additional peers later, we need |
264 | some modifications from the default configuration. We need to create a separate service home and a file containing our modifications for this peer: | 283 | some modifications from the default configuration. We need to create a separate service home and a file containing our modifications for this peer: |
284 | \lstset{language=bash} | ||
265 | \begin{lstlisting} | 285 | \begin{lstlisting} |
266 | $ mkdir ~/gnunet1/ | 286 | $ mkdir ~/gnunet1/ |
267 | $ touch peer1.conf | 287 | $ touch peer1.conf |
@@ -271,12 +291,12 @@ Now add the following lines to peer1.conf to use this directory. For | |||
271 | simplified usage we want to prevent the peer to connect to the GNUnet | 291 | simplified usage we want to prevent the peer to connect to the GNUnet |
272 | network since this could lead to confusing output. This modifications | 292 | network since this could lead to confusing output. This modifications |
273 | will replace the default settings: | 293 | will replace the default settings: |
274 | \begin{lstlisting} | 294 | \begin{verbatim} |
275 | [PATHS] | 295 | [PATHS] |
276 | GNUNET_HOME = ~/gnunet1/ # Use this directory to store GNUnet data | 296 | GNUNET_HOME = ~/gnunet1/ # Use this directory to store GNUnet data |
277 | [hostlist] | 297 | [hostlist] |
278 | SERVERS = # prevent bootstrapping | 298 | SERVERS = # prevent bootstrapping |
279 | \end{lstlisting} | 299 | \end{verbatim} |
280 | 300 | ||
281 | 301 | ||
282 | \subsection{Start a peer} | 302 | \subsection{Start a peer} |
@@ -322,6 +342,7 @@ $ cd ~/gnunet/src/dht; | |||
322 | $ ./gnunet-dht-monitor -c ~/peer1.conf -k KEY | 342 | $ ./gnunet-dht-monitor -c ~/peer1.conf -k KEY |
323 | \end{lstlisting} | 343 | \end{lstlisting} |
324 | Now open a separate terminal and change again to the \lstinline|gnunet/src/dht| directory: | 344 | Now open a separate terminal and change again to the \lstinline|gnunet/src/dht| directory: |
345 | \lstset{language=bash} | ||
325 | \begin{lstlisting} | 346 | \begin{lstlisting} |
326 | $ cd ~/gnunet/src/dht | 347 | $ cd ~/gnunet/src/dht |
327 | $ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE # put VALUE under KEY in the DHT | 348 | $ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE # put VALUE under KEY in the DHT |
@@ -348,6 +369,7 @@ To configure the second peer, use the files {\tt | |||
348 | configuration file: | 369 | configuration file: |
349 | % | 370 | % |
350 | \lstset{language=bash} | 371 | \lstset{language=bash} |
372 | \lstset{language=bash} | ||
351 | \begin{lstlisting} | 373 | \begin{lstlisting} |
352 | $ cat $PREFIX/share/gnunet/config.d/*.conf > peer2.conf | 374 | $ cat $PREFIX/share/gnunet/config.d/*.conf > peer2.conf |
353 | \end{lstlisting} | 375 | \end{lstlisting} |
@@ -399,10 +421,10 @@ If you want the two peers to connect, you have multiple options: | |||
399 | To setup peer 1 as bootstrapping server change the configuration of | 421 | To setup peer 1 as bootstrapping server change the configuration of |
400 | the first one to be a hostlist server by adding the following lines to | 422 | the first one to be a hostlist server by adding the following lines to |
401 | \texttt{peer1.conf} to enable bootstrapping server: | 423 | \texttt{peer1.conf} to enable bootstrapping server: |
402 | \begin{lstlisting} | 424 | \begin{verbatim} |
403 | [hostlist] | 425 | [hostlist] |
404 | OPTIONS = -p | 426 | OPTIONS = -p |
405 | \end{lstlisting} | 427 | \end{verbatim} |
406 | 428 | ||
407 | Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with | 429 | Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with |
408 | ``\texttt{http://localhost:8080/}''. Restart both peers using: | 430 | ``\texttt{http://localhost:8080/}''. Restart both peers using: |
@@ -432,6 +454,7 @@ If you want to use the \texttt{peerinfo} tool to connect your peers, you should: | |||
432 | 454 | ||
433 | Check that they are connected using {\tt gnunet-core -c peer1.conf}, which should give you the other peer's | 455 | Check that they are connected using {\tt gnunet-core -c peer1.conf}, which should give you the other peer's |
434 | peer identity: | 456 | peer identity: |
457 | \lstset{language=bash} | ||
435 | \begin{lstlisting} | 458 | \begin{lstlisting} |
436 | $ gnunet-core -c peer1.conf | 459 | $ gnunet-core -c peer1.conf |
437 | Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG' | 460 | Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG' |
@@ -463,7 +486,8 @@ found in the testbed default configuration file \texttt{src/testbed/testbed.conf | |||
463 | 486 | ||
464 | With the testbed API, a sample test case can be structured as follows: | 487 | With the testbed API, a sample test case can be structured as follows: |
465 | % <lynX> Is there a way to pick a more readable font for this include? | 488 | % <lynX> Is there a way to pick a more readable font for this include? |
466 | \lstinputlisting[language=C]{testbed_test.c} | 489 | \lstset{language=C} |
490 | \lstinputlisting{testbed_test.c} | ||
467 | The source code for the above listing can be found at | 491 | The source code for the above listing can be found at |
468 | \url{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c} | 492 | \url{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c} |
469 | or in the {\tt doc/} folder of your repository check-out. | 493 | or in the {\tt doc/} folder of your repository check-out. |
@@ -593,7 +617,7 @@ command-line options, setup the scheduler and then invoke the {\tt | |||
593 | to the parsed configuration (and the configuration file name that was | 617 | to the parsed configuration (and the configuration file name that was |
594 | used, which is typically not needed): | 618 | used, which is typically not needed): |
595 | 619 | ||
596 | \lstset{language=c} | 620 | \lstset{language=C} |
597 | \begin{lstlisting} | 621 | \begin{lstlisting} |
598 | #include <gnunet/platform.h> | 622 | #include <gnunet/platform.h> |
599 | #include <gnunet/gnunet_util_lib.h> | 623 | #include <gnunet/gnunet_util_lib.h> |
@@ -606,7 +630,7 @@ run (void *cls, | |||
606 | const char *cfgfile, | 630 | const char *cfgfile, |
607 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 631 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
608 | { | 632 | { |
609 | /* main code here */ | 633 | // main code here |
610 | ret = 0; | 634 | ret = 0; |
611 | } | 635 | } |
612 | 636 | ||
@@ -632,6 +656,7 @@ expanding the {\tt options} array. For example, the following would | |||
632 | add a string-option and a binary flag (defaulting to {\tt NULL} and | 656 | add a string-option and a binary flag (defaulting to {\tt NULL} and |
633 | {\tt GNUNET\_NO} respectively): | 657 | {\tt GNUNET\_NO} respectively): |
634 | 658 | ||
659 | \lstset{language=C} | ||
635 | \begin{lstlisting} | 660 | \begin{lstlisting} |
636 | static char *string_option; | 661 | static char *string_option; |
637 | static int a_flag; | 662 | static int a_flag; |
@@ -696,7 +721,7 @@ file). | |||
696 | Before a client library can implement the application-specific protocol | 721 | Before a client library can implement the application-specific protocol |
697 | with the service, a connection must be created: | 722 | with the service, a connection must be created: |
698 | 723 | ||
699 | \lstset{language=c} | 724 | \lstset{language=C} |
700 | \begin{lstlisting} | 725 | \begin{lstlisting} |
701 | struct GNUNET_MQ_MessageHandlers handlers[] = { | 726 | struct GNUNET_MQ_MessageHandlers handlers[] = { |
702 | // ... | 727 | // ... |
@@ -723,36 +748,26 @@ In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_Message | |||
723 | in big endian format. This header defines the size and the type of the | 748 | in big endian format. This header defines the size and the type of the |
724 | message, the payload follows after this header. | 749 | message, the payload follows after this header. |
725 | 750 | ||
726 | \lstset{language=c} | 751 | \lstset{language=C} |
727 | \begin{lstlisting} | 752 | \begin{lstlisting} |
728 | struct GNUNET_MessageHeader | 753 | struct GNUNET_MessageHeader |
729 | { | 754 | { |
730 | |||
731 | /** | ||
732 | * The length of the struct (in bytes, including the length field itself), | ||
733 | * in big-endian format. | ||
734 | */ | ||
735 | uint16_t size GNUNET_PACKED; | 755 | uint16_t size GNUNET_PACKED; |
736 | |||
737 | /** | ||
738 | * The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format. | ||
739 | */ | ||
740 | uint16_t type GNUNET_PACKED; | 756 | uint16_t type GNUNET_PACKED; |
741 | |||
742 | }; | 757 | }; |
743 | \end{lstlisting} | 758 | \end{lstlisting} |
744 | 759 | ||
745 | Existing message types are defined in {\tt gnunet\_protocols.h}\\ | 760 | Existing message types are defined in {\tt gnunet\_protocols.h}\\ |
746 | A common way to create a message is with an envelope: | 761 | A common way to create a message is with an envelope: |
747 | 762 | ||
748 | \lstset{language=c} | 763 | \lstset{language=C} |
749 | \begin{lstlisting} | 764 | \begin{lstlisting} |
750 | struct GNUNET_MQ_Envelope *env; | 765 | struct GNUNET_MQ_Envelope *env; |
751 | struct GNUNET_MessageHeader *msg; | 766 | struct GNUNET_MessageHeader *msg; |
752 | 767 | ||
753 | env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE); | 768 | env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE); |
754 | memcpy (&msg[1], &payload, payload_size); | 769 | memcpy (&msg[1], &payload, payload_size); |
755 | /* Send message via message queue 'mq': */ | 770 | // Send message via message queue 'mq' |
756 | GNUNET_mq_send (mq, env); | 771 | GNUNET_mq_send (mq, env); |
757 | \end{lstlisting} | 772 | \end{lstlisting} |
758 | 773 | ||
@@ -785,38 +800,19 @@ and {\tt handle\_} are mandatory. | |||
785 | 800 | ||
786 | \lstset{language=c} | 801 | \lstset{language=c} |
787 | \begin{lstlisting} | 802 | \begin{lstlisting} |
788 | /** | ||
789 | * Function called with MyMessage messages from service. | ||
790 | * | ||
791 | * @param cls closure | ||
792 | * @param msg message received | ||
793 | */ | ||
794 | static void | 803 | static void |
795 | handle_fix (void *cls, const struct MyMessage *msg) | 804 | handle_fix (void *cls, const struct MyMessage *msg) |
796 | { | 805 | { |
797 | // process 'msg' | 806 | // process 'msg' |
798 | } | 807 | } |
799 | 808 | ||
800 | /** | ||
801 | * Function called with MyVarMessage messages from service. | ||
802 | * | ||
803 | * @param cls closure | ||
804 | * @param msg message received | ||
805 | * @return #GNUNET_OK if @a msg is well-formed | ||
806 | */ | ||
807 | static int | 809 | static int |
808 | check_var (void *cls, const struct MyVarMessage *msg) | 810 | check_var (void *cls, const struct MyVarMessage *msg) |
809 | { | 811 | { |
810 | // check 'msg' is well-formed | 812 | // check 'msg' is well-formed |
811 | return GNUNET_OK; /* suppose yes */ | 813 | return GNUNET_OK; |
812 | } | 814 | } |
813 | 815 | ||
814 | /** | ||
815 | * Function called with MyMessage messages from service. | ||
816 | * | ||
817 | * @param cls closure | ||
818 | * @param msg message received | ||
819 | */ | ||
820 | static void | 816 | static void |
821 | handle_var (void *cls, const struct MyVarMessage *msg) | 817 | handle_var (void *cls, const struct MyVarMessage *msg) |
822 | { | 818 | { |
@@ -900,13 +896,6 @@ like this: | |||
900 | 896 | ||
901 | \lstset{language=c} | 897 | \lstset{language=c} |
902 | \begin{lstlisting} | 898 | \begin{lstlisting} |
903 | /** | ||
904 | * Launch service. | ||
905 | * | ||
906 | * @param cls closure | ||
907 | * @param c configuration to use | ||
908 | * @param service the initialized service | ||
909 | */ | ||
910 | static void | 899 | static void |
911 | run (void *cls, | 900 | run (void *cls, |
912 | const struct GNUNET_CONFIGURATION_Handle *c, | 901 | const struct GNUNET_CONFIGURATION_Handle *c, |
@@ -914,14 +903,6 @@ run (void *cls, | |||
914 | { | 903 | { |
915 | } | 904 | } |
916 | 905 | ||
917 | /** | ||
918 | * Callback called when a client connects to the service. | ||
919 | * | ||
920 | * @param cls closure for the service | ||
921 | * @param c the new client that connected to the service | ||
922 | * @param mq the message queue used to send messages to the client | ||
923 | * @return @a c | ||
924 | */ | ||
925 | static void * | 906 | static void * |
926 | client_connect_cb (void *cls, | 907 | client_connect_cb (void *cls, |
927 | struct GNUNET_SERVICE_Client *c, | 908 | struct GNUNET_SERVICE_Client *c, |
@@ -930,13 +911,6 @@ client_connect_cb (void *cls, | |||
930 | return c; | 911 | return c; |
931 | } | 912 | } |
932 | 913 | ||
933 | /** | ||
934 | * Callback called when a client disconnected from the service | ||
935 | * | ||
936 | * @param cls closure for the service | ||
937 | * @param c the client that disconnected | ||
938 | * @param internal_cls should be equal to @a c | ||
939 | */ | ||
940 | static void | 914 | static void |
941 | client_disconnect_cb (void *cls, | 915 | client_disconnect_cb (void *cls, |
942 | struct GNUNET_SERVICE_Client *c, | 916 | struct GNUNET_SERVICE_Client *c, |
@@ -988,11 +962,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
988 | GNUNET_CORE_StartupCallback init, | 962 | GNUNET_CORE_StartupCallback init, |
989 | GNUNET_CORE_ConnectEventHandler connects, | 963 | GNUNET_CORE_ConnectEventHandler connects, |
990 | GNUNET_CORE_DisconnectEventHandler disconnects, | 964 | GNUNET_CORE_DisconnectEventHandler disconnects, |
991 | GNUNET_CORE_MessageCallback inbound_notify, | 965 | const struct GNUNET_MQ_MessageHandler *handlers); |
992 | int inbound_hdr_only, | ||
993 | GNUNET_CORE_MessageCallback outbound_notify, | ||
994 | int outbound_hdr_only, | ||
995 | const struct GNUNET_CORE_MessageHandler *handlers); | ||
996 | \end{lstlisting} | 966 | \end{lstlisting} |
997 | 967 | ||
998 | \subsection{New P2P connections} | 968 | \subsection{New P2P connections} |
@@ -1003,45 +973,33 @@ which communicates the identity of the new peer to the service: | |||
1003 | 973 | ||
1004 | \lstset{language=C} | 974 | \lstset{language=C} |
1005 | \begin{lstlisting} | 975 | \begin{lstlisting} |
1006 | void | 976 | void * |
1007 | connects (void *cls, | 977 | connects (void *cls, |
1008 | const struct GNUNET_PeerIdentity * peer) | 978 | const struct GNUNET_PeerIdentity *peer, |
979 | struct GNUNET_MQ_Handle *mq) | ||
1009 | { | 980 | { |
1010 | /* Save identity for later use */ | 981 | return mq; |
1011 | /* Optional: start sending messages to peer */ | ||
1012 | } | 982 | } |
1013 | \end{lstlisting} | 983 | \end{lstlisting} |
1014 | 984 | ||
985 | Note that whatever you return from {\tt connects} is given as the | ||
986 | {\it cls} argument to the message handlers for messages from | ||
987 | the respective peer. | ||
988 | |||
1015 | \exercise{Create a service that connects to the \texttt{CORE}. Then | 989 | \exercise{Create a service that connects to the \texttt{CORE}. Then |
1016 | start (and connect) two peers and print a message once your connect | 990 | start (and connect) two peers and print a message once your connect |
1017 | callback is invoked.} | 991 | callback is invoked.} |
1018 | 992 | ||
1019 | \subsection{Receiving P2P Messages} | 993 | \subsection{Receiving P2P Messages} |
1020 | 994 | ||
1021 | To receive messages from \texttt{CORE}, services register a set of handlers | 995 | To receive messages from \texttt{CORE}, you pass the desired |
1022 | (parameter {\tt *handlers} in the \lstinline|GNUNET_CORE_connect| call that are called by \texttt{CORE} | 996 | {\em handlers} to the {\tt GNUNET\_CORE\_connect()} function, |
1023 | when a suitable message arrives. | 997 | just as we showed for services. |
1024 | 998 | ||
1025 | \lstset{language=c} | 999 | It is your responsibility to process messages fast enough or |
1026 | \begin{lstlisting} | 1000 | to implement flow control. If an application does not process |
1027 | static int | 1001 | CORE messages fast enough, CORE will randomly drop messages |
1028 | callback_function_for_type_one(void *cls, | 1002 | to not keep a very long queue in memory. |
1029 | const struct GNUNET_PeerIdentity *peer, | ||
1030 | const struct GNUNET_MessageHeader *message) | ||
1031 | { | ||
1032 | /* Do stuff */ | ||
1033 | return GNUNET_OK; /* or GNUNET_SYSERR to close the connection */ | ||
1034 | } | ||
1035 | |||
1036 | /** | ||
1037 | * Functions to handle messages from core | ||
1038 | */ | ||
1039 | static struct GNUNET_CORE_MessageHandler core_handlers[] = { | ||
1040 | {&callback_function_for_type_one, GNUNET_MESSAGE_TYPE_MYSERVICE_TYPE_ONE, 0}, | ||
1041 | /* more handlers*/ | ||
1042 | {NULL, 0, 0} | ||
1043 | }; | ||
1044 | \end{lstlisting} | ||
1045 | 1003 | ||
1046 | \exercise{Start one peer with a new service that has a message | 1004 | \exercise{Start one peer with a new service that has a message |
1047 | handler and start a second peer that only has your ``old'' service | 1005 | handler and start a second peer that only has your ``old'' service |
@@ -1051,29 +1009,13 @@ the two peers are connected? Why?} | |||
1051 | 1009 | ||
1052 | \subsection{Sending P2P Messages} | 1010 | \subsection{Sending P2P Messages} |
1053 | 1011 | ||
1054 | In response to events (connect, disconnect, inbound messages, | 1012 | You can transmit messages to other peers using the {\it mq} you were |
1055 | timing, etc.) services can then use this API to transmit messages: | 1013 | given during the {\tt connect} callback. Note that the {\it mq} |
1014 | automatically is released upon {\tt disconnect} and that you must | ||
1015 | not use it afterwards. | ||
1056 | 1016 | ||
1057 | \lstset{language=C} | 1017 | It is your responsibility to not over-fill the message queue, GNUnet |
1058 | \begin{lstlisting} | 1018 | will send the messages roughly in the order given as soon as possible. |
1059 | typedef size_t | ||
1060 | (*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls, | ||
1061 | size_t size, | ||
1062 | void *buf) | ||
1063 | { | ||
1064 | /* Fill "*buf" with up to "size" bytes, must start with GNUNET_MessageHeader */ | ||
1065 | return n; /* Total size of the message put in "*buf" */ | ||
1066 | } | ||
1067 | |||
1068 | struct GNUNET_CORE_TransmitHandle * | ||
1069 | GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, | ||
1070 | int cork, uint32_t priority, | ||
1071 | struct GNUNET_TIME_Relative maxdelay, | ||
1072 | const struct GNUNET_PeerIdentity *target, | ||
1073 | size_t notify_size, | ||
1074 | GNUNET_CONNECTION_TransmitReadyNotify notify, | ||
1075 | void *notify_cls); | ||
1076 | \end{lstlisting} | ||
1077 | 1019 | ||
1078 | \exercise{Write a service that upon connect sends messages as | 1020 | \exercise{Write a service that upon connect sends messages as |
1079 | fast as possible to the other peer (the other peer should run a | 1021 | fast as possible to the other peer (the other peer should run a |
@@ -1258,22 +1200,21 @@ and other unfavorable events, just make several PUT requests! | |||
1258 | 1200 | ||
1259 | \lstset{language=C} | 1201 | \lstset{language=C} |
1260 | \begin{lstlisting} | 1202 | \begin{lstlisting} |
1261 | void | 1203 | static void |
1262 | message_sent_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 1204 | message_sent_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
1263 | { | 1205 | { |
1264 | /* Request has left local node */ | 1206 | // Request has left local node |
1265 | } | 1207 | } |
1266 | 1208 | ||
1267 | struct GNUNET_DHT_PutHandle * | 1209 | struct GNUNET_DHT_PutHandle * |
1268 | GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, | 1210 | GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, |
1269 | const struct GNUNET_HashCode *key, | 1211 | const struct GNUNET_HashCode *key, |
1270 | uint32_t desired_replication_level, | 1212 | uint32_t desired_replication_level, |
1271 | enum GNUNET_DHT_RouteOption options, /* Route options, see next call */ | 1213 | enum GNUNET_DHT_RouteOption options, |
1272 | enum GNUNET_BLOCK_Type type, size_t size, const void *data, | 1214 | enum GNUNET_BLOCK_Type type, size_t size, const void *data, |
1273 | struct GNUNET_TIME_Absolute exp, /* When does the data expire? */ | 1215 | struct GNUNET_TIME_Absolute exp, |
1274 | struct GNUNET_TIME_Relative timeout, /* How long to try to send the request */ | 1216 | struct GNUNET_TIME_Relative timeout, |
1275 | GNUNET_DHT_PutContinuation cont, | 1217 | GNUNET_DHT_PutContinuation cont, void *cont_cls) |
1276 | void *cont_cls) | ||
1277 | \end{lstlisting} | 1218 | \end{lstlisting} |
1278 | 1219 | ||
1279 | \exercise{Store a value in the DHT periodically to make sure it is available | 1220 | \exercise{Store a value in the DHT periodically to make sure it is available |
@@ -1305,9 +1246,8 @@ get_result_iterator (void *cls, struct GNUNET_TIME_Absolute expiration, | |||
1305 | unsigned int put_path_length, | 1246 | unsigned int put_path_length, |
1306 | enum GNUNET_BLOCK_Type type, size_t size, const void *data) | 1247 | enum GNUNET_BLOCK_Type type, size_t size, const void *data) |
1307 | { | 1248 | { |
1308 | /* Do stuff with the data and/or route */ | 1249 | // Optionally: |
1309 | /* Optionally: */ | 1250 | GNUNET_DHT_get_stop (get_handle); |
1310 | GNUNET_DHT_get_stop (get_handle); | ||
1311 | } | 1251 | } |
1312 | 1252 | ||
1313 | get_handle = | 1253 | get_handle = |
@@ -1315,9 +1255,9 @@ get_handle = | |||
1315 | block_type, | 1255 | block_type, |
1316 | &key, | 1256 | &key, |
1317 | replication, | 1257 | replication, |
1318 | GNUNET_DHT_RO_NONE, /* Route options */ | 1258 | GNUNET_DHT_RO_NONE, |
1319 | NULL, /* xquery: not used here */ | 1259 | NULL, |
1320 | 0, /* xquery size */ | 1260 | 0, |
1321 | &get_result_iterator, | 1261 | &get_result_iterator, |
1322 | cls) | 1262 | cls) |
1323 | \end{lstlisting} | 1263 | \end{lstlisting} |
@@ -1356,13 +1296,13 @@ static enum GNUNET_BLOCK_EvaluationResult | |||
1356 | block_plugin_SERVICE_evaluate (void *cls, | 1296 | block_plugin_SERVICE_evaluate (void *cls, |
1357 | enum GNUNET_BLOCK_Type type, | 1297 | enum GNUNET_BLOCK_Type type, |
1358 | struct GNUNET_BlockGroup *bg, | 1298 | struct GNUNET_BlockGroup *bg, |
1359 | const GNUNET_HashCode *query, | 1299 | const GNUNET_HashCode *query, |
1360 | const void *xquery, | 1300 | const void *xquery, |
1361 | size_t xquery_size, | 1301 | size_t xquery_size, |
1362 | const void *reply_block, | 1302 | const void *reply_block, |
1363 | size_t reply_block_size) | 1303 | size_t reply_block_size) |
1364 | { | 1304 | { |
1365 | /* Verify type, block and bg */ | 1305 | // Verify type, block and bg |
1366 | } | 1306 | } |
1367 | \end{lstlisting} | 1307 | \end{lstlisting} |
1368 | 1308 | ||
@@ -1385,10 +1325,10 @@ just fine with such blocks). | |||
1385 | \begin{lstlisting} | 1325 | \begin{lstlisting} |
1386 | static int | 1326 | static int |
1387 | block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type, | 1327 | block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type, |
1388 | const void *block, size_t block_size, | 1328 | const void *block, size_t block_size, |
1389 | struct GNUNET_HashCode *key) | 1329 | struct GNUNET_HashCode *key) |
1390 | { | 1330 | { |
1391 | /* Store the key in the key argument, return GNUNET_OK on success. */ | 1331 | // Store the key in the key argument, return GNUNET_OK on success. |
1392 | } | 1332 | } |
1393 | \end{lstlisting} | 1333 | \end{lstlisting} |
1394 | 1334 | ||
@@ -1407,8 +1347,8 @@ libgnunet_plugin_block_SERVICE_init (void *cls) | |||
1407 | { | 1347 | { |
1408 | static enum GNUNET_BLOCK_Type types[] = | 1348 | static enum GNUNET_BLOCK_Type types[] = |
1409 | { | 1349 | { |
1410 | GNUNET_BLOCK_TYPE_SERVICE_BLOCKYPE, /* list of blocks we care about, from gnunet_block_lib.h */ | 1350 | GNUNET_BLOCK_TYPE_SERVICE_BLOCKYPE, |
1411 | GNUNET_BLOCK_TYPE_ANY /* end of list */ | 1351 | GNUNET_BLOCK_TYPE_ANY |
1412 | }; | 1352 | }; |
1413 | struct GNUNET_BLOCK_PluginFunctions *api; | 1353 | struct GNUNET_BLOCK_PluginFunctions *api; |
1414 | 1354 | ||
@@ -1483,7 +1423,7 @@ to allow for filtering of messages. When an event happens, the appropiate callba | |||
1483 | is called with all the information about the event. | 1423 | is called with all the information about the event. |
1484 | \lstset{language=C} | 1424 | \lstset{language=C} |
1485 | \begin{lstlisting} | 1425 | \begin{lstlisting} |
1486 | void | 1426 | static void |
1487 | get_callback (void *cls, | 1427 | get_callback (void *cls, |
1488 | enum GNUNET_DHT_RouteOption options, | 1428 | enum GNUNET_DHT_RouteOption options, |
1489 | enum GNUNET_BLOCK_Type type, | 1429 | enum GNUNET_BLOCK_Type type, |
@@ -1495,7 +1435,8 @@ get_callback (void *cls, | |||
1495 | { | 1435 | { |
1496 | } | 1436 | } |
1497 | 1437 | ||
1498 | void | 1438 | |
1439 | static void | ||
1499 | get_resp_callback (void *cls, | 1440 | get_resp_callback (void *cls, |
1500 | enum GNUNET_BLOCK_Type type, | 1441 | enum GNUNET_BLOCK_Type type, |
1501 | const struct GNUNET_PeerIdentity *get_path, | 1442 | const struct GNUNET_PeerIdentity *get_path, |
@@ -1509,7 +1450,8 @@ get_resp_callback (void *cls, | |||
1509 | { | 1450 | { |
1510 | } | 1451 | } |
1511 | 1452 | ||
1512 | void | 1453 | |
1454 | static void | ||
1513 | put_callback (void *cls, | 1455 | put_callback (void *cls, |
1514 | enum GNUNET_DHT_RouteOption options, | 1456 | enum GNUNET_DHT_RouteOption options, |
1515 | enum GNUNET_BLOCK_Type type, | 1457 | enum GNUNET_BLOCK_Type type, |
@@ -1524,13 +1466,14 @@ put_callback (void *cls, | |||
1524 | { | 1466 | { |
1525 | } | 1467 | } |
1526 | 1468 | ||
1469 | |||
1527 | monitor_handle = GNUNET_DHT_monitor_start (dht_handle, | 1470 | monitor_handle = GNUNET_DHT_monitor_start (dht_handle, |
1528 | block_type, /* GNUNET_BLOCK_TYPE_ANY for all */ | 1471 | block_type, |
1529 | key, /* NULL for all */ | 1472 | key, |
1530 | &get_callback, | 1473 | &get_callback, |
1531 | &get_resp_callback, | 1474 | &get_resp_callback, |
1532 | &put_callback, | 1475 | &put_callback, |
1533 | cls); | 1476 | cls); |
1534 | \end{lstlisting} | 1477 | \end{lstlisting} |
1535 | 1478 | ||
1536 | 1479 | ||