aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorng0 <ng0@infotropique.org>2017-08-24 13:36:06 +0000
committerng0 <ng0@infotropique.org>2017-08-24 13:36:06 +0000
commitdaa0f2090f74ef3a34a9ecff996e909369beb8af (patch)
treee7dd407c349d4ae479780ef703d6233d6c8f1d47 /doc
parent834f1ec8209254fb66dc2908d39852761f015c8f (diff)
downloadgnunet-daa0f2090f74ef3a34a9ecff996e909369beb8af.tar.gz
gnunet-daa0f2090f74ef3a34a9ecff996e909369beb8af.zip
+
Diffstat (limited to 'doc')
-rw-r--r--doc/gnunet-c-tutorial.texi188
1 files changed, 89 insertions, 99 deletions
diff --git a/doc/gnunet-c-tutorial.texi b/doc/gnunet-c-tutorial.texi
index 0c01cceab..dc6ebb1fb 100644
--- a/doc/gnunet-c-tutorial.texi
+++ b/doc/gnunet-c-tutorial.texi
@@ -369,13 +369,12 @@ error in the configuration).
369@subsubsection Start the second peer and connect the peers 369@subsubsection Start the second peer and connect the peers
370 370
371Then, you can start a second peer using: 371Then, you can start a second peer using:
372\lstset{language=bash} 372@example
373\begin{lstlisting}
374$ gnunet-arm -c peer2.conf -s 373$ gnunet-arm -c peer2.conf -s
375$ gnunet-arm -c peer2.conf -i dht 374$ gnunet-arm -c peer2.conf -i dht
376$ ~/gnunet/src/dht/gnunet-dht-put -c peer2.conf -k KEY -d VALUE 375$ ~/gnunet/src/dht/gnunet-dht-put -c peer2.conf -k KEY -d VALUE
377$ ~/gnunet/src/dht/gnunet-dht-get -c peer2.conf -k KEY 376$ ~/gnunet/src/dht/gnunet-dht-get -c peer2.conf -k KEY
378\end{lstlisting} 377@end example
379If you want the two peers to connect, you have multiple options: 378If you want the two peers to connect, you have multiple options:
380\begin{itemize} 379\begin{itemize}
381\itemsep0em 380\itemsep0em
@@ -386,10 +385,10 @@ If you want the two peers to connect, you have multiple options:
386To setup peer 1 as bootstrapping server change the configuration of 385To setup peer 1 as bootstrapping server change the configuration of
387the first one to be a hostlist server by adding the following lines to 386the first one to be a hostlist server by adding the following lines to
388\texttt{peer1.conf} to enable bootstrapping server: 387\texttt{peer1.conf} to enable bootstrapping server:
389 \begin{verbatim} 388 @example
390[hostlist] 389[hostlist]
391OPTIONS = -p 390OPTIONS = -p
392\end{verbatim} 391@end example
393 392
394Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with 393Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with
395``\texttt{http://localhost:8080/}''. Restart both peers using: 394``\texttt{http://localhost:8080/}''. Restart both peers using:
@@ -457,14 +456,13 @@ The source code for the above listing can be found at
457@uref{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c} 456@uref{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c}
458or in the {\tt doc/} folder of your repository check-out. 457or in the {\tt doc/} folder of your repository check-out.
459After installing GNUnet, the above source code can be compiled as: 458After installing GNUnet, the above source code can be compiled as:
460\lstset{language=bash} 459@example
461\begin{lstlisting}
462$ export CPPFLAGS="-I/path/to/gnunet/headers" 460$ export CPPFLAGS="-I/path/to/gnunet/headers"
463$ export LDFLAGS="-L/path/to/gnunet/libraries" 461$ export LDFLAGS="-L/path/to/gnunet/libraries"
464$ gcc $CPPFLAGS $LDFLAGS -o testbed-test testbed_test.c -lgnunettestbed -lgnunetdht -lgnunetutil 462$ gcc $CPPFLAGS $LDFLAGS -o testbed-test testbed_test.c -lgnunettestbed -lgnunetdht -lgnunetutil
465$ touch template.conf # Generate (empty) configuration 463$ touch template.conf # Generate (empty) configuration
466$ ./testbed-test # run it (press CTRL-C to stop) 464$ ./testbed-test # run it (press CTRL-C to stop)
467\end{lstlisting} 465@end example
468The \texttt{CPPFLAGS} and \texttt{LDFLAGS} are necessary if GNUnet is installed 466The \texttt{CPPFLAGS} and \texttt{LDFLAGS} are necessary if GNUnet is installed
469into a different directory other than \texttt{/usr/local}. 467into a different directory other than \texttt{/usr/local}.
470 468
@@ -506,9 +504,9 @@ called after the connect adapter has been called when the operation from
506\texttt{GNUNET\_TESTBED\_service\_connect()} is marked as ``done''. It has to 504\texttt{GNUNET\_TESTBED\_service\_connect()} is marked as ``done''. It has to
507disconnect from the service with the provided service handle (\texttt{op\_result}). 505disconnect from the service with the provided service handle (\texttt{op\_result}).
508 506
509\exercise{Find out how many peers you can run on your system.} 507Exercise: Find out how many peers you can run on your system.}
510 508
511\exercise{Find out how to create a 2D torus topology by changing the 509Exercise: Find out how to create a 2D torus topology by changing the
512 options in the configuration file.\footnote{See @uref{https://gnunet.org/supported-topologies}} 510 options in the configuration file.\footnote{See @uref{https://gnunet.org/supported-topologies}}
513 Then use the DHT API to store and retrieve values in the 511 Then use the DHT API to store and retrieve values in the
514 network.} 512 network.}
@@ -521,8 +519,7 @@ To develop a new peer-to-peer application or to extend GNUnet we provide
521a template build system for writing GNUnet extensions in C. It can be 519a template build system for writing GNUnet extensions in C. It can be
522obtained as follows: 520obtained as follows:
523 521
524\lstset{language=bash} 522@example
525\begin{lstlisting}
526$ git clone https://gnunet.org/git/gnunet-ext 523$ git clone https://gnunet.org/git/gnunet-ext
527$ cd gnunet-ext/ 524$ cd gnunet-ext/
528$ ./bootstrap 525$ ./bootstrap
@@ -530,7 +527,7 @@ $ ./configure --prefix=$PREFIX --with-gnunet=$PREFIX
530$ make 527$ make
531$ make install 528$ make install
532$ make check 529$ make check
533\end{lstlisting} 530@end example
534% $ 531% $
535 532
536The GNUnet ext template includes examples and a working buildsystem for a new GNUnet service. 533The GNUnet ext template includes examples and a working buildsystem for a new GNUnet service.
@@ -614,7 +611,7 @@ main (int argc, char *const *argv)
614 gettext_noop ("binary description text"), 611 gettext_noop ("binary description text"),
615 options, &run, NULL)) ? ret : 1; 612 options, &run, NULL)) ? ret : 1;
616} 613}
617\end{lstlisting} 614@end example
618 615
619@subsection Handling command-line options} 616@subsection Handling command-line options}
620 617
@@ -641,7 +638,7 @@ static int a_flag;
641 string_option = NULL; 638 string_option = NULL;
642 a_flag = GNUNET_SYSERR; 639 a_flag = GNUNET_SYSERR;
643// ... 640// ...
644\end{lstlisting} 641@end example
645 642
646Issues such as displaying some helpful text describing options using 643Issues such as displaying some helpful text describing options using
647the {\tt --help} argument and error handling are taken care of when 644the {\tt --help} argument and error handling are taken care of when
@@ -659,7 +656,7 @@ using some client library to interact with the service. The client
659library is supposed to implement the IPC whereas the service provides 656library is supposed to implement the IPC whereas the service provides
660more persistent P2P functions. 657more persistent P2P functions.
661 658
662\exercise{Add a few command-line options and print them inside 659Exercise: Add a few command-line options and print them inside
663of {\tt run}. What happens if the user gives invalid arguments?} 660of {\tt run}. What happens if the user gives invalid arguments?}
664 661
665@subsection Writing a Client Library} 662@subsection Writing a Client Library}
@@ -683,7 +680,7 @@ Unique message types must be defined for each message struct in the
683{\tt gnunet\_protocols.h} header (or an extension-specific include 680{\tt gnunet\_protocols.h} header (or an extension-specific include
684file). 681file).
685 682
686\subsubsection{Connecting to the Service} 683@subsubsection Connecting to the Service}
687 684
688Before a client library can implement the application-specific protocol 685Before a client library can implement the application-specific protocol
689with the service, a connection must be created: 686with the service, a connection must be created:
@@ -697,7 +694,7 @@ with the service, a connection must be created:
697 struct GNUNET_MQ_Handle *mq; 694 struct GNUNET_MQ_Handle *mq;
698 695
699 mq = GNUNET_CLIENT_connect (cfg, "service-name", handlers, &error_cb, NULL); 696 mq = GNUNET_CLIENT_connect (cfg, "service-name", handlers, &error_cb, NULL);
700\end{lstlisting} 697@end example
701 698
702As a result a {\tt GNUNET\_MQ\_Handle} is returned 699As a result a {\tt GNUNET\_MQ\_Handle} is returned
703which can to used henceforth to transmit messages to 700which can to used henceforth to transmit messages to
@@ -709,7 +706,7 @@ receive from the service, and which functions handle them.
709The {\tt error\_cb} is a function that is to be called whenever 706The {\tt error\_cb} is a function that is to be called whenever
710there are errors communicating with the service. 707there are errors communicating with the service.
711 708
712\subsubsection{Sending messages} 709@subsubsection Sending messages}
713 710
714In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_MessageHeader} 711In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_MessageHeader}
715in big endian format. This header defines the size and the type of the 712in big endian format. This header defines the size and the type of the
@@ -722,7 +719,7 @@ struct GNUNET_MessageHeader
722 uint16_t size GNUNET_PACKED; 719 uint16_t size GNUNET_PACKED;
723 uint16_t type GNUNET_PACKED; 720 uint16_t type GNUNET_PACKED;
724}; 721};
725\end{lstlisting} 722@end example
726 723
727Existing message types are defined in {\tt gnunet\_protocols.h}\\ 724Existing message types are defined in {\tt gnunet\_protocols.h}\\
728A common way to create a message is with an envelope: 725A common way to create a message is with an envelope:
@@ -736,23 +733,23 @@ env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE);
736memcpy (&msg[1], &payload, payload_size); 733memcpy (&msg[1], &payload, payload_size);
737// Send message via message queue 'mq' 734// Send message via message queue 'mq'
738GNUNET_mq_send (mq, env); 735GNUNET_mq_send (mq, env);
739\end{lstlisting} 736@end example
740 737
741\exercise{Define a message struct that includes a 32-bit 738Exercise: Define a message struct that includes a 32-bit
742unsigned integer in addition to the standard GNUnet MessageHeader. 739unsigned integer in addition to the standard GNUnet MessageHeader.
743Add a C struct and define a fresh protocol number for your message. 740Add a C struct and define a fresh protocol number for your message.
744(Protocol numbers in gnunet-ext are defined in \lstinline|gnunet-ext/src/include/gnunet_protocols_ext.h|)} 741(Protocol numbers in gnunet-ext are defined in \lstinline|gnunet-ext/src/include/gnunet_protocols_ext.h|)}
745 742
746\exercise{Find out how you can determine the number of messages in a message queue.} 743Exercise: Find out how you can determine the number of messages in a message queue.}
747 744
748\exercise{Find out how you can determine when a message you have queued was actually transmitted.} 745Exercise: Find out how you can determine when a message you have queued was actually transmitted.}
749 746
750\exercise{Define a helper function to transmit a 32-bit 747Exercise: Define a helper function to transmit a 32-bit
751unsigned integer (as payload) to a service using some given client 748unsigned integer (as payload) to a service using some given client
752handle.} 749handle.}
753 750
754 751
755\subsubsection{Receiving Replies from the Service} 752@subsubsection Receiving Replies from the Service}
756 753
757Clients can receive messages from the service using the handlers 754Clients can receive messages from the service using the handlers
758specified in the {\tt handlers} array we specified when connecting 755specified in the {\tt handlers} array we specified when connecting
@@ -798,14 +795,14 @@ struct GNUNET_MQ_MessageHandler handlers[] = {
798 795
799 GNUNET_MQ_handler_end () 796 GNUNET_MQ_handler_end ()
800}; 797};
801\end{lstlisting} 798@end example
802 799
803\exercise{Expand your helper function to receive a response message 800Exercise: Expand your helper function to receive a response message
804 (for example, containing just the {\tt struct GNUnet MessageHeader} 801 (for example, containing just the {\tt struct GNUnet MessageHeader}
805 without any payload). Upon receiving the service's response, you 802 without any payload). Upon receiving the service's response, you
806 should call a callback provided to your helper function's API.} 803 should call a callback provided to your helper function's API.}
807 804
808\exercise{Figure out where you can pass values to the closures ({\tt cls}).} 805Exercise: Figure out where you can pass values to the closures ({\tt cls}).}
809 806
810 807
811@subsection Writing a user interface} 808@subsection Writing a user interface}
@@ -814,7 +811,7 @@ Given a client library, all it takes to access a service now is to
814combine calls to the client library with parsing command-line 811combine calls to the client library with parsing command-line
815options. 812options.
816 813
817\exercise{Call your client API from your {\tt run()} method in your 814Exercise: Call your client API from your {\tt run()} method in your
818 client application to send a request to the service. For example, 815 client application to send a request to the service. For example,
819 send a 32-bit integer value based on a number given at the 816 send a 32-bit integer value based on a number given at the
820 command-line to the service.} 817 command-line to the service.}
@@ -851,7 +848,7 @@ GNUNET_SERVICE_MAIN
851 GNUNET_MQ_hd_fixed_size (...), 848 GNUNET_MQ_hd_fixed_size (...),
852 GNUNET_MQ_hd_var_size (...), 849 GNUNET_MQ_hd_var_size (...),
853 GNUNET_MQ_handler_end ()); 850 GNUNET_MQ_handler_end ());
854\end{lstlisting} 851@end example
855 852
856In addition to the service name and flags, the macro takes three 853In addition to the service name and flags, the macro takes three
857functions, typically called {\tt run}, {\tt client\_connect\_cb} and 854functions, typically called {\tt run}, {\tt client\_connect\_cb} and
@@ -885,17 +882,17 @@ client_disconnect_cb (void *cls,
885{ 882{
886 GNUNET_assert (c == internal_cls); 883 GNUNET_assert (c == internal_cls);
887} 884}
888\end{lstlisting} 885@end example
889 886
890\exercise{Write a stub service that processes no messages at all 887Exercise: Write a stub service that processes no messages at all
891 in your code. Create a default configuration for it, integrate it 888 in your code. Create a default configuration for it, integrate it
892 with the build system and start the service from {\tt 889 with the build system and start the service from {\tt
893 gnunet-service-arm} using {\tt gnunet-arm -i NAME}.} 890 gnunet-service-arm} using {\tt gnunet-arm -i NAME}.}
894 891
895\exercise{Figure out how to set the closure ({\tt cls}) for handlers 892Exercise: Figure out how to set the closure ({\tt cls}) for handlers
896 of a service.} 893 of a service.}
897 894
898\exercise{Figure out how to send messages from the service back to the 895Exercise: Figure out how to send messages from the service back to the
899 client.} 896 client.}
900 897
901Each handler function in the service {\bf must} eventually (possibly in some 898Each handler function in the service {\bf must} eventually (possibly in some
@@ -904,7 +901,7 @@ Only after this call additional messages from the same client may
904be processed. This way, the service can throttle processing messages 901be processed. This way, the service can throttle processing messages
905from the same client. 902from the same client.
906 903
907\exercise{Change the service to ``handle'' the message from your 904Exercise: Change the service to ``handle'' the message from your
908 client (for now, by printing a message). What happens if you 905 client (for now, by printing a message). What happens if you
909 forget to call {\tt GNUNET\_SERVICE\_client\_continue()}?} 906 forget to call {\tt GNUNET\_SERVICE\_client\_continue()}?}
910 907
@@ -930,7 +927,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
930 GNUNET_CORE_ConnectEventHandler connects, 927 GNUNET_CORE_ConnectEventHandler connects,
931 GNUNET_CORE_DisconnectEventHandler disconnects, 928 GNUNET_CORE_DisconnectEventHandler disconnects,
932 const struct GNUNET_MQ_MessageHandler *handlers); 929 const struct GNUNET_MQ_MessageHandler *handlers);
933\end{lstlisting} 930@end example
934 931
935@subsection New P2P connections} 932@subsection New P2P connections}
936 933
@@ -947,17 +944,17 @@ connects (void *cls,
947{ 944{
948 return mq; 945 return mq;
949} 946}
950\end{lstlisting} 947@end example
951 948
952Note that whatever you return from {\tt connects} is given as the 949Note that whatever you return from {\tt connects} is given as the
953{\it cls} argument to the message handlers for messages from 950{\it cls} argument to the message handlers for messages from
954the respective peer. 951the respective peer.
955 952
956\exercise{Create a service that connects to the \texttt{CORE}. Then 953Exercise: Create a service that connects to the \texttt{CORE}. Then
957start (and connect) two peers and print a message once your connect 954start (and connect) two peers and print a message once your connect
958callback is invoked.} 955callback is invoked.}
959 956
960@subsection Receiving P2P Messages} 957@subsection Receiving P2P Messages
961 958
962To receive messages from \texttt{CORE}, you pass the desired 959To receive messages from \texttt{CORE}, you pass the desired
963{\em handlers} to the {\tt GNUNET\_CORE\_connect()} function, 960{\em handlers} to the {\tt GNUNET\_CORE\_connect()} function,
@@ -968,13 +965,13 @@ to implement flow control. If an application does not process
968CORE messages fast enough, CORE will randomly drop messages 965CORE messages fast enough, CORE will randomly drop messages
969to not keep a very long queue in memory. 966to not keep a very long queue in memory.
970 967
971\exercise{Start one peer with a new service that has a message 968Exercise: Start one peer with a new service that has a message
972handler and start a second peer that only has your ``old'' service 969handler and start a second peer that only has your ``old'' service
973without message handlers. Which ``connect'' handlers are invoked when 970without message handlers. Which ``connect'' handlers are invoked when
974the two peers are connected? Why?} 971the two peers are connected? Why?}
975 972
976 973
977@subsection Sending P2P Messages} 974@subsection Sending P2P Messages
978 975
979You can transmit messages to other peers using the {\it mq} you were 976You can transmit messages to other peers using the {\it mq} you were
980given during the {\tt connect} callback. Note that the {\it mq} 977given during the {\tt connect} callback. Note that the {\it mq}
@@ -984,7 +981,7 @@ not use it afterwards.
984It is your responsibility to not over-fill the message queue, GNUnet 981It is your responsibility to not over-fill the message queue, GNUnet
985will send the messages roughly in the order given as soon as possible. 982will send the messages roughly in the order given as soon as possible.
986 983
987\exercise{Write a service that upon connect sends messages as 984Exercise: Write a service that upon connect sends messages as
988fast as possible to the other peer (the other peer should run a 985fast as possible to the other peer (the other peer should run a
989service that ``processes'' those messages). How fast is the 986service that ``processes'' those messages). How fast is the
990transmission? Count using the STATISTICS service on both ends. Are 987transmission? Count using the STATISTICS service on both ends. Are
@@ -1009,9 +1006,9 @@ disconnects (void *cls,
1009 /* Remove peer's identity from known peers */ 1006 /* Remove peer's identity from known peers */
1010 /* Make sure no messages are sent to peer from now on */ 1007 /* Make sure no messages are sent to peer from now on */
1011} 1008}
1012\end{lstlisting} 1009@end example
1013 1010
1014\exercise{Fix your service to handle peer disconnects.} 1011Exercise: Fix your service to handle peer disconnects.}
1015 1012
1016@section Storing peer-specific data using the PEERSTORE service 1013@section Storing peer-specific data using the PEERSTORE service
1017 1014
@@ -1033,7 +1030,7 @@ The first step is to start a connection to the PEERSTORE service:
1033#include "gnunet_peerstore_service.h" 1030#include "gnunet_peerstore_service.h"
1034 1031
1035peerstore_handle = GNUNET_PEERSTORE_connect (cfg); 1032peerstore_handle = GNUNET_PEERSTORE_connect (cfg);
1036\end{lstlisting} 1033@end example
1037The service handle \lstinline|peerstore_handle| will be needed for all subsequent 1034The service handle \lstinline|peerstore_handle| will be needed for all subsequent
1038PEERSTORE operations. 1035PEERSTORE operations.
1039 1036
@@ -1052,7 +1049,7 @@ GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
1052 enum GNUNET_PEERSTORE_StoreOption options, 1049 enum GNUNET_PEERSTORE_StoreOption options,
1053 GNUNET_PEERSTORE_Continuation cont, 1050 GNUNET_PEERSTORE_Continuation cont,
1054 void *cont_cls); 1051 void *cont_cls);
1055\end{lstlisting} 1052@end example
1056 1053
1057The \lstinline|options| parameter can either be \lstinline|GNUNET_PEERSTORE_STOREOPTION_MULTIPLE| 1054The \lstinline|options| parameter can either be \lstinline|GNUNET_PEERSTORE_STOREOPTION_MULTIPLE|
1058which means that multiple values can be stored under the same key combination (subsystem, peerid, key), 1055which means that multiple values can be stored under the same key combination (subsystem, peerid, key),
@@ -1068,9 +1065,9 @@ can be used to cancel the store operation only before the continuation function
1068\begin{lstlisting} 1065\begin{lstlisting}
1069void 1066void
1070GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc); 1067GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc);
1071\end{lstlisting} 1068@end example
1072 1069
1073@subsection Retrieving records} 1070@subsection Retrieving records
1074 1071
1075To retrieve stored records, use the following function: 1072To retrieve stored records, use the following function:
1076\begin{lstlisting} 1073\begin{lstlisting}
@@ -1082,7 +1079,7 @@ GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h,
1082 struct GNUNET_TIME_Relative timeout, 1079 struct GNUNET_TIME_Relative timeout,
1083 GNUNET_PEERSTORE_Processor callback, 1080 GNUNET_PEERSTORE_Processor callback,
1084 void *callback_cls); 1081 void *callback_cls);
1085\end{lstlisting} 1082@end example
1086The values of \lstinline|peer| and \lstinline|key| can be \lstinline|NULL|. This allows the 1083The values of \lstinline|peer| and \lstinline|key| can be \lstinline|NULL|. This allows the
1087iteration over values stored under any of the following key combinations: 1084iteration over values stored under any of the following key combinations:
1088\begin{itemize} 1085\begin{itemize}
@@ -1100,7 +1097,7 @@ The \lstinline|GNUNET_PEERSTORE_iterate| function returns a handle to the iterat
1100handle can be used to cancel the iterate operation only before the callback function is called with 1097handle can be used to cancel the iterate operation only before the callback function is called with
1101a \lstinline|NULL| record. 1098a \lstinline|NULL| record.
1102 1099
1103@subsection Monitoring records} 1100@subsection Monitoring records
1104 1101
1105PEERSTORE offers the functionality of monitoring for new records stored under a specific key 1102PEERSTORE offers the functionality of monitoring for new records stored under a specific key
1106combination (subsystem, peerid, key). To start the monitoring, use the following function: 1103combination (subsystem, peerid, key). To start the monitoring, use the following function:
@@ -1112,7 +1109,7 @@ GNUNET_PEERSTORE_watch (struct GNUNET_PEERSTORE_Handle *h,
1112 const char *key, 1109 const char *key,
1113 GNUNET_PEERSTORE_Processor callback, 1110 GNUNET_PEERSTORE_Processor callback,
1114 void *callback_cls); 1111 void *callback_cls);
1115\end{lstlisting} 1112@end example
1116 1113
1117Whenever a new record is stored under the given key combination, the \lstinline|callback| function 1114Whenever a new record is stored under the given key combination, the \lstinline|callback| function
1118will be called with this new record. This will continue until the connection to the PEERSTORE service 1115will be called with this new record. This will continue until the connection to the PEERSTORE service
@@ -1120,16 +1117,16 @@ is broken or the watch operation is canceled:
1120\begin{lstlisting} 1117\begin{lstlisting}
1121void 1118void
1122GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext *wc); 1119GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext *wc);
1123\end{lstlisting} 1120@end example
1124 1121
1125@subsection Disconnecting from PEERSTORE} 1122@subsection Disconnecting from PEERSTORE
1126 1123
1127When the connection to the PEERSTORE service is no longer needed, disconnect using the following 1124When the connection to the PEERSTORE service is no longer needed, disconnect using the following
1128function: 1125function:
1129\begin{lstlisting} 1126\begin{lstlisting}
1130void 1127void
1131GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, int sync_first); 1128GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, int sync_first);
1132\end{lstlisting} 1129@end example
1133 1130
1134If the \lstinline|sync_first| flag is set to \lstinline|GNUNET_YES|, the API will delay the 1131If the \lstinline|sync_first| flag is set to \lstinline|GNUNET_YES|, the API will delay the
1135disconnection until all store requests are received by the PEERSTORE service. Otherwise, 1132disconnection until all store requests are received by the PEERSTORE service. Otherwise,
@@ -1145,12 +1142,12 @@ thing to do is to connect to the DHT service:
1145\lstset{language=C} 1142\lstset{language=C}
1146\begin{lstlisting} 1143\begin{lstlisting}
1147dht_handle = GNUNET_DHT_connect (cfg, parallel_requests); 1144dht_handle = GNUNET_DHT_connect (cfg, parallel_requests);
1148\end{lstlisting} 1145@end example
1149The second parameter indicates how many requests in parallel to expect. 1146The second parameter indicates how many requests in parallel to expect.
1150It is not a hard limit, but a good approximation will make the DHT more 1147It is not a hard limit, but a good approximation will make the DHT more
1151efficient. 1148efficient.
1152 1149
1153@subsection Storing data in the DHT} 1150@subsection Storing data in the DHT
1154Since the DHT is a dynamic environment (peers join and leave frequently) 1151Since the DHT is a dynamic environment (peers join and leave frequently)
1155the data that we put in the DHT does not stay there indefinitely. It is 1152the data that we put in the DHT does not stay there indefinitely. It is
1156important to ``refresh'' the data periodically by simply storing it again, 1153important to ``refresh'' the data periodically by simply storing it again,
@@ -1182,14 +1179,14 @@ GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
1182 struct GNUNET_TIME_Absolute exp, 1179 struct GNUNET_TIME_Absolute exp,
1183 struct GNUNET_TIME_Relative timeout, 1180 struct GNUNET_TIME_Relative timeout,
1184 GNUNET_DHT_PutContinuation cont, void *cont_cls) 1181 GNUNET_DHT_PutContinuation cont, void *cont_cls)
1185\end{lstlisting} 1182@end example
1186 1183
1187\exercise{Store a value in the DHT periodically to make sure it is available 1184Exercise: Store a value in the DHT periodically to make sure it is available
1188over time. You might consider using the function GNUNET\_SCHEDULER\_add\_delayed and 1185over time. You might consider using the function GNUNET\_SCHEDULER\_add\_delayed and
1189call GNUNET\_DHT\_put from inside a helper function.} 1186call GNUNET\_DHT\_put from inside a helper function.}
1190 1187
1191 1188
1192@subsection Obtaining data from the DHT} 1189@subsection Obtaining data from the DHT
1193As we saw in the previous example, the DHT works in an asynchronous mode. 1190As we saw in the previous example, the DHT works in an asynchronous mode.
1194Each request to the DHT is executed ``in the background'' and the API 1191Each request to the DHT is executed ``in the background'' and the API
1195calls return immediately. In order to receive results from the DHT, the 1192calls return immediately. In order to receive results from the DHT, the
@@ -1227,13 +1224,13 @@ get_handle =
1227 0, 1224 0,
1228 &get_result_iterator, 1225 &get_result_iterator,
1229 cls) 1226 cls)
1230\end{lstlisting} 1227@end example
1231 1228
1232\exercise{Store a value in the DHT and after a while retrieve it. Show the IDs of all 1229Exercise: Store a value in the DHT and after a while retrieve it. Show the IDs of all
1233the peers the requests have gone through. In order to convert a peer ID to a string, use 1230the peers the requests have gone through. In order to convert a peer ID to a string, use
1234the function GNUNET\_i2s. Pay attention to the route option parameters in both calls!} 1231the function GNUNET\_i2s. Pay attention to the route option parameters in both calls!}
1235 1232
1236@subsection Implementing a block plugin} 1233@subsection Implementing a block plugin
1237 1234
1238In order to store data in the DHT, it is necessary to provide a block 1235In order to store data in the DHT, it is necessary to provide a block
1239plugin. The DHT uses the block plugin to ensure that only well-formed 1236plugin. The DHT uses the block plugin to ensure that only well-formed
@@ -1244,7 +1241,7 @@ The block plugin should be put in a file {\tt
1244mandatory functions that need to be implemented for a block plugin are 1241mandatory functions that need to be implemented for a block plugin are
1245described in the following sections. 1242described in the following sections.
1246 1243
1247\subsubsection{Validating requests and replies} 1244@subsubsection Validating requests and replies
1248 1245
1249The evaluate function should validate a reply or a request. It returns 1246The evaluate function should validate a reply or a request. It returns
1250a {\tt GNUNET\_BLOCK\_EvaluationResult}, which is an enumeration. All 1247a {\tt GNUNET\_BLOCK\_EvaluationResult}, which is an enumeration. All
@@ -1271,7 +1268,7 @@ block_plugin_SERVICE_evaluate (void *cls,
1271{ 1268{
1272 // Verify type, block and bg 1269 // Verify type, block and bg
1273} 1270}
1274\end{lstlisting} 1271@end example
1275 1272
1276Note that it is mandatory to detect duplicate replies in this function 1273Note that it is mandatory to detect duplicate replies in this function
1277and return the respective status code. Duplicate detection is 1274and return the respective status code. Duplicate detection is
@@ -1279,7 +1276,7 @@ typically done using the Bloom filter block group provided by {\tt
1279 libgnunetblockgroup.so}. Failure to do so may cause replies to 1276 libgnunetblockgroup.so}. Failure to do so may cause replies to
1280circle in the network. 1277circle in the network.
1281 1278
1282\subsubsection{Deriving a key from a reply} 1279@subsubsection Deriving a key from a reply
1283 1280
1284The DHT can operate more efficiently if it is possible to derive a key 1281The DHT can operate more efficiently if it is possible to derive a key
1285from the value of the corresponding block. The {\tt get\_key} 1282from the value of the corresponding block. The {\tt get\_key}
@@ -1288,8 +1285,7 @@ means of hashing. If deriving the key is not possible, the function
1288should simply return {\tt GNUNET\_SYSERR} (the DHT will still work 1285should simply return {\tt GNUNET\_SYSERR} (the DHT will still work
1289just fine with such blocks). 1286just fine with such blocks).
1290 1287
1291\lstset{language=C} 1288@example
1292\begin{lstlisting}
1293static int 1289static int
1294block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type, 1290block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type,
1295 const void *block, size_t block_size, 1291 const void *block, size_t block_size,
@@ -1297,9 +1293,9 @@ block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type,
1297{ 1293{
1298 // Store the key in the key argument, return GNUNET_OK on success. 1294 // Store the key in the key argument, return GNUNET_OK on success.
1299} 1295}
1300\end{lstlisting} 1296@end example
1301 1297
1302\subsubsection{Initialization of the plugin} 1298@subsubsection Initialization of the plugin
1303 1299
1304The plugin is realized as a shared C library. The library must export 1300The plugin is realized as a shared C library. The library must export
1305an initialization function which should initialize the plugin. The 1301an initialization function which should initialize the plugin. The
@@ -1307,8 +1303,7 @@ initialization function specifies what block types the plugin cares
1307about and returns a struct with the functions that are to be used for 1303about and returns a struct with the functions that are to be used for
1308validation and obtaining keys (the ones just defined above). 1304validation and obtaining keys (the ones just defined above).
1309 1305
1310\lstset{language=C} 1306@example
1311\begin{lstlisting}
1312void * 1307void *
1313libgnunet_plugin_block_SERVICE_init (void *cls) 1308libgnunet_plugin_block_SERVICE_init (void *cls)
1314{ 1309{
@@ -1325,16 +1320,15 @@ libgnunet_plugin_block_SERVICE_init (void *cls)
1325 api->types = types; 1320 api->types = types;
1326 return api; 1321 return api;
1327} 1322}
1328\end{lstlisting} 1323@end example
1329 1324
1330\subsubsection{Shutdown of the plugin} 1325@subsubsection Shutdown of the plugin
1331 1326
1332Following GNUnet's general plugin API concept, the plugin must 1327Following GNUnet's general plugin API concept, the plugin must
1333export a second function for cleaning up. It usually does very 1328export a second function for cleaning up. It usually does very
1334little. 1329little.
1335 1330
1336\lstset{language=C} 1331@example
1337\begin{lstlisting}
1338void * 1332void *
1339libgnunet_plugin_block_SERVICE_done (void *cls) 1333libgnunet_plugin_block_SERVICE_done (void *cls)
1340{ 1334{
@@ -1343,16 +1337,15 @@ libgnunet_plugin_block_SERVICE_done (void *cls)
1343 GNUNET_free (api); 1337 GNUNET_free (api);
1344 return NULL; 1338 return NULL;
1345} 1339}
1346\end{lstlisting} 1340@end example
1347 1341
1348 1342
1349\subsubsection{Integration of the plugin with the build system} 1343@subsubsection Integration of the plugin with the build system
1350 1344
1351In order to compile the plugin, the {\tt Makefile.am} file for the 1345In order to compile the plugin, the Makefile.am file for the
1352service \texttt{SERVICE} should contain a rule similar to this: 1346service SERVICE should contain a rule similar to this:
1353 1347
1354\lstset{language=make} 1348@example
1355\begin{lstlisting}
1356 plugindir = $(libdir)/gnunet 1349 plugindir = $(libdir)/gnunet
1357 1350
1358 plugin_LTLIBRARIES = \ 1351 plugin_LTLIBRARIES = \
@@ -1367,15 +1360,12 @@ service \texttt{SERVICE} should contain a rule similar to this:
1367 $(GN_PLUGIN_LDFLAGS) 1360 $(GN_PLUGIN_LDFLAGS)
1368 libgnunet_plugin_block_ext_la_DEPENDENCIES = \ 1361 libgnunet_plugin_block_ext_la_DEPENDENCIES = \
1369 $(prefix)/lib/libgnunetblock.la 1362 $(prefix)/lib/libgnunetblock.la
1370\end{lstlisting} 1363@end example
1371% $
1372 1364
1373 1365
1374\exercise{Write a block plugin that accepts all queries 1366Exercise: Write a block plugin that accepts all queries
1375and all replies but prints information about queries and replies 1367and all replies but prints information about queries and replies
1376when the respective validation hooks are called.} 1368when the respective validation hooks are called.
1377
1378
1379 1369
1380@subsection Monitoring the DHT 1370@subsection Monitoring the DHT
1381It is possible to monitor the functioning of the local DHT service. When monitoring 1371It is possible to monitor the functioning of the local DHT service. When monitoring
@@ -1388,8 +1378,7 @@ Since the different events have different associated data, the API gets 3
1388different callbacks (one for each message type) and optional type and key parameters, 1378different callbacks (one for each message type) and optional type and key parameters,
1389to allow for filtering of messages. When an event happens, the appropiate callback 1379to allow for filtering of messages. When an event happens, the appropiate callback
1390is called with all the information about the event. 1380is called with all the information about the event.
1391\lstset{language=C} 1381@example
1392\begin{lstlisting}
1393static void 1382static void
1394get_callback (void *cls, 1383get_callback (void *cls,
1395 enum GNUNET_DHT_RouteOption options, 1384 enum GNUNET_DHT_RouteOption options,
@@ -1441,7 +1430,7 @@ monitor_handle = GNUNET_DHT_monitor_start (dht_handle,
1441 &get_resp_callback, 1430 &get_resp_callback,
1442 &put_callback, 1431 &put_callback,
1443 cls); 1432 cls);
1444\end{lstlisting} 1433@end example
1445 1434
1446 1435
1447@section Debugging with gnunet-arm 1436@section Debugging with gnunet-arm
@@ -1451,20 +1440,18 @@ Even if services are managed by {\tt gnunet-arm}, you can start them with
1451to your configuration file to start the DHT service in a {\tt gdb} session in a 1440to your configuration file to start the DHT service in a {\tt gdb} session in a
1452fresh {\tt xterm}: 1441fresh {\tt xterm}:
1453 1442
1454\begin{verbatim} 1443@example
1455[dht] 1444[dht]
1456PREFIX=xterm -e gdb --args 1445PREFIX=xterm -e gdb --args
1457\end{verbatim} 1446@end example
1458 1447
1459Alternatively, you can stop a service that was started via ARM and run it manually: 1448Alternatively, you can stop a service that was started via ARM and run it manually:
1460 1449
1461\lstset{language=bash} 1450@example
1462\begin{lstlisting}
1463$ gnunet-arm -k dht 1451$ gnunet-arm -k dht
1464$ gdb --args gnunet-service-dht -L DEBUG 1452$ gdb --args gnunet-service-dht -L DEBUG
1465$ valgrind gnunet-service-dht -L DEBUG 1453$ valgrind gnunet-service-dht -L DEBUG
1466\end{lstlisting} 1454@end example
1467% $
1468 1455
1469Assuming other services are well-written, they will automatically re-integrate the 1456Assuming other services are well-written, they will automatically re-integrate the
1470restarted service with the peer. 1457restarted service with the peer.
@@ -1481,9 +1468,12 @@ You should also probably enable the creation of core files, by setting
1481Then you can investigate the core dumps with {\tt gdb}, which is often 1468Then you can investigate the core dumps with {\tt gdb}, which is often
1482the fastest method to find simple errors. 1469the fastest method to find simple errors.
1483 1470
1484\exercise{Add a memory leak to your service and obtain a trace 1471Exercise: Add a memory leak to your service and obtain a trace
1485pointing to the leak using {\tt valgrind} while running the service 1472pointing to the leak using {\tt valgrind} while running the service
1486from {\tt gnunet-service-arm}.} 1473from {\tt gnunet-service-arm}.}
1487 1474
1475@bye
1488 1476
1489\end{document} 1477@c Local Variables:
1478@c ispell-local-dictionary: ``american'';
1479@c End: