diff options
author | ng0 <ng0@infotropique.org> | 2017-08-24 13:36:06 +0000 |
---|---|---|
committer | ng0 <ng0@infotropique.org> | 2017-08-24 13:36:06 +0000 |
commit | daa0f2090f74ef3a34a9ecff996e909369beb8af (patch) | |
tree | e7dd407c349d4ae479780ef703d6233d6c8f1d47 /doc | |
parent | 834f1ec8209254fb66dc2908d39852761f015c8f (diff) | |
download | gnunet-daa0f2090f74ef3a34a9ecff996e909369beb8af.tar.gz gnunet-daa0f2090f74ef3a34a9ecff996e909369beb8af.zip |
+
Diffstat (limited to 'doc')
-rw-r--r-- | doc/gnunet-c-tutorial.texi | 188 |
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 | ||
371 | Then, you can start a second peer using: | 371 | Then, 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 |
379 | If you want the two peers to connect, you have multiple options: | 378 | If 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: | |||
386 | To setup peer 1 as bootstrapping server change the configuration of | 385 | To setup peer 1 as bootstrapping server change the configuration of |
387 | the first one to be a hostlist server by adding the following lines to | 386 | the 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] |
391 | OPTIONS = -p | 390 | OPTIONS = -p |
392 | \end{verbatim} | 391 | @end example |
393 | 392 | ||
394 | Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with | 393 | Then 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} |
458 | or in the {\tt doc/} folder of your repository check-out. | 457 | or in the {\tt doc/} folder of your repository check-out. |
459 | After installing GNUnet, the above source code can be compiled as: | 458 | After 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 |
468 | The \texttt{CPPFLAGS} and \texttt{LDFLAGS} are necessary if GNUnet is installed | 466 | The \texttt{CPPFLAGS} and \texttt{LDFLAGS} are necessary if GNUnet is installed |
469 | into a different directory other than \texttt{/usr/local}. | 467 | into 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 |
507 | disconnect from the service with the provided service handle (\texttt{op\_result}). | 505 | disconnect 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.} | 507 | Exercise: 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 | 509 | Exercise: 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 | |||
521 | a template build system for writing GNUnet extensions in C. It can be | 519 | a template build system for writing GNUnet extensions in C. It can be |
522 | obtained as follows: | 520 | obtained 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 | ||
536 | The GNUnet ext template includes examples and a working buildsystem for a new GNUnet service. | 533 | The 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 | ||
646 | Issues such as displaying some helpful text describing options using | 643 | Issues such as displaying some helpful text describing options using |
647 | the {\tt --help} argument and error handling are taken care of when | 644 | the {\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 | |||
659 | library is supposed to implement the IPC whereas the service provides | 656 | library is supposed to implement the IPC whereas the service provides |
660 | more persistent P2P functions. | 657 | more persistent P2P functions. |
661 | 658 | ||
662 | \exercise{Add a few command-line options and print them inside | 659 | Exercise: Add a few command-line options and print them inside |
663 | of {\tt run}. What happens if the user gives invalid arguments?} | 660 | of {\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 |
684 | file). | 681 | file). |
685 | 682 | ||
686 | \subsubsection{Connecting to the Service} | 683 | @subsubsection Connecting to the Service} |
687 | 684 | ||
688 | Before a client library can implement the application-specific protocol | 685 | Before a client library can implement the application-specific protocol |
689 | with the service, a connection must be created: | 686 | with 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 | ||
702 | As a result a {\tt GNUNET\_MQ\_Handle} is returned | 699 | As a result a {\tt GNUNET\_MQ\_Handle} is returned |
703 | which can to used henceforth to transmit messages to | 700 | which can to used henceforth to transmit messages to |
@@ -709,7 +706,7 @@ receive from the service, and which functions handle them. | |||
709 | The {\tt error\_cb} is a function that is to be called whenever | 706 | The {\tt error\_cb} is a function that is to be called whenever |
710 | there are errors communicating with the service. | 707 | there are errors communicating with the service. |
711 | 708 | ||
712 | \subsubsection{Sending messages} | 709 | @subsubsection Sending messages} |
713 | 710 | ||
714 | In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_MessageHeader} | 711 | In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_MessageHeader} |
715 | in big endian format. This header defines the size and the type of the | 712 | in 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 | ||
727 | Existing message types are defined in {\tt gnunet\_protocols.h}\\ | 724 | Existing message types are defined in {\tt gnunet\_protocols.h}\\ |
728 | A common way to create a message is with an envelope: | 725 | A 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); | |||
736 | memcpy (&msg[1], &payload, payload_size); | 733 | memcpy (&msg[1], &payload, payload_size); |
737 | // Send message via message queue 'mq' | 734 | // Send message via message queue 'mq' |
738 | GNUNET_mq_send (mq, env); | 735 | GNUNET_mq_send (mq, env); |
739 | \end{lstlisting} | 736 | @end example |
740 | 737 | ||
741 | \exercise{Define a message struct that includes a 32-bit | 738 | Exercise: Define a message struct that includes a 32-bit |
742 | unsigned integer in addition to the standard GNUnet MessageHeader. | 739 | unsigned integer in addition to the standard GNUnet MessageHeader. |
743 | Add a C struct and define a fresh protocol number for your message. | 740 | Add 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.} | 743 | Exercise: 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.} | 745 | Exercise: 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 | 747 | Exercise: Define a helper function to transmit a 32-bit |
751 | unsigned integer (as payload) to a service using some given client | 748 | unsigned integer (as payload) to a service using some given client |
752 | handle.} | 749 | handle.} |
753 | 750 | ||
754 | 751 | ||
755 | \subsubsection{Receiving Replies from the Service} | 752 | @subsubsection Receiving Replies from the Service} |
756 | 753 | ||
757 | Clients can receive messages from the service using the handlers | 754 | Clients can receive messages from the service using the handlers |
758 | specified in the {\tt handlers} array we specified when connecting | 755 | specified 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 | 800 | Exercise: 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}).} | 805 | Exercise: 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 | |||
814 | combine calls to the client library with parsing command-line | 811 | combine calls to the client library with parsing command-line |
815 | options. | 812 | options. |
816 | 813 | ||
817 | \exercise{Call your client API from your {\tt run()} method in your | 814 | Exercise: 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 | ||
856 | In addition to the service name and flags, the macro takes three | 853 | In addition to the service name and flags, the macro takes three |
857 | functions, typically called {\tt run}, {\tt client\_connect\_cb} and | 854 | functions, 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 | 887 | Exercise: 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 | 892 | Exercise: 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 | 895 | Exercise: Figure out how to send messages from the service back to the |
899 | client.} | 896 | client.} |
900 | 897 | ||
901 | Each handler function in the service {\bf must} eventually (possibly in some | 898 | Each 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 | |||
904 | be processed. This way, the service can throttle processing messages | 901 | be processed. This way, the service can throttle processing messages |
905 | from the same client. | 902 | from the same client. |
906 | 903 | ||
907 | \exercise{Change the service to ``handle'' the message from your | 904 | Exercise: 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 | ||
952 | Note that whatever you return from {\tt connects} is given as the | 949 | Note 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 |
954 | the respective peer. | 951 | the respective peer. |
955 | 952 | ||
956 | \exercise{Create a service that connects to the \texttt{CORE}. Then | 953 | Exercise: Create a service that connects to the \texttt{CORE}. Then |
957 | start (and connect) two peers and print a message once your connect | 954 | start (and connect) two peers and print a message once your connect |
958 | callback is invoked.} | 955 | callback is invoked.} |
959 | 956 | ||
960 | @subsection Receiving P2P Messages} | 957 | @subsection Receiving P2P Messages |
961 | 958 | ||
962 | To receive messages from \texttt{CORE}, you pass the desired | 959 | To 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 | |||
968 | CORE messages fast enough, CORE will randomly drop messages | 965 | CORE messages fast enough, CORE will randomly drop messages |
969 | to not keep a very long queue in memory. | 966 | to not keep a very long queue in memory. |
970 | 967 | ||
971 | \exercise{Start one peer with a new service that has a message | 968 | Exercise: Start one peer with a new service that has a message |
972 | handler and start a second peer that only has your ``old'' service | 969 | handler and start a second peer that only has your ``old'' service |
973 | without message handlers. Which ``connect'' handlers are invoked when | 970 | without message handlers. Which ``connect'' handlers are invoked when |
974 | the two peers are connected? Why?} | 971 | the two peers are connected? Why?} |
975 | 972 | ||
976 | 973 | ||
977 | @subsection Sending P2P Messages} | 974 | @subsection Sending P2P Messages |
978 | 975 | ||
979 | You can transmit messages to other peers using the {\it mq} you were | 976 | You can transmit messages to other peers using the {\it mq} you were |
980 | given during the {\tt connect} callback. Note that the {\it mq} | 977 | given during the {\tt connect} callback. Note that the {\it mq} |
@@ -984,7 +981,7 @@ not use it afterwards. | |||
984 | It is your responsibility to not over-fill the message queue, GNUnet | 981 | It is your responsibility to not over-fill the message queue, GNUnet |
985 | will send the messages roughly in the order given as soon as possible. | 982 | will 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 | 984 | Exercise: Write a service that upon connect sends messages as |
988 | fast as possible to the other peer (the other peer should run a | 985 | fast as possible to the other peer (the other peer should run a |
989 | service that ``processes'' those messages). How fast is the | 986 | service that ``processes'' those messages). How fast is the |
990 | transmission? Count using the STATISTICS service on both ends. Are | 987 | transmission? 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.} | 1011 | Exercise: 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 | ||
1035 | peerstore_handle = GNUNET_PEERSTORE_connect (cfg); | 1032 | peerstore_handle = GNUNET_PEERSTORE_connect (cfg); |
1036 | \end{lstlisting} | 1033 | @end example |
1037 | The service handle \lstinline|peerstore_handle| will be needed for all subsequent | 1034 | The service handle \lstinline|peerstore_handle| will be needed for all subsequent |
1038 | PEERSTORE operations. | 1035 | PEERSTORE 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 | ||
1057 | The \lstinline|options| parameter can either be \lstinline|GNUNET_PEERSTORE_STOREOPTION_MULTIPLE| | 1054 | The \lstinline|options| parameter can either be \lstinline|GNUNET_PEERSTORE_STOREOPTION_MULTIPLE| |
1058 | which means that multiple values can be stored under the same key combination (subsystem, peerid, key), | 1055 | which 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} |
1069 | void | 1066 | void |
1070 | GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc); | 1067 | GNUNET_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 | ||
1075 | To retrieve stored records, use the following function: | 1072 | To 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 |
1086 | The values of \lstinline|peer| and \lstinline|key| can be \lstinline|NULL|. This allows the | 1083 | The values of \lstinline|peer| and \lstinline|key| can be \lstinline|NULL|. This allows the |
1087 | iteration over values stored under any of the following key combinations: | 1084 | iteration 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 | |||
1100 | handle can be used to cancel the iterate operation only before the callback function is called with | 1097 | handle can be used to cancel the iterate operation only before the callback function is called with |
1101 | a \lstinline|NULL| record. | 1098 | a \lstinline|NULL| record. |
1102 | 1099 | ||
1103 | @subsection Monitoring records} | 1100 | @subsection Monitoring records |
1104 | 1101 | ||
1105 | PEERSTORE offers the functionality of monitoring for new records stored under a specific key | 1102 | PEERSTORE offers the functionality of monitoring for new records stored under a specific key |
1106 | combination (subsystem, peerid, key). To start the monitoring, use the following function: | 1103 | combination (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 | ||
1117 | Whenever a new record is stored under the given key combination, the \lstinline|callback| function | 1114 | Whenever a new record is stored under the given key combination, the \lstinline|callback| function |
1118 | will be called with this new record. This will continue until the connection to the PEERSTORE service | 1115 | will 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} |
1121 | void | 1118 | void |
1122 | GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext *wc); | 1119 | GNUNET_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 | ||
1127 | When the connection to the PEERSTORE service is no longer needed, disconnect using the following | 1124 | When the connection to the PEERSTORE service is no longer needed, disconnect using the following |
1128 | function: | 1125 | function: |
1129 | \begin{lstlisting} | 1126 | \begin{lstlisting} |
1130 | void | 1127 | void |
1131 | GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, int sync_first); | 1128 | GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, int sync_first); |
1132 | \end{lstlisting} | 1129 | @end example |
1133 | 1130 | ||
1134 | If the \lstinline|sync_first| flag is set to \lstinline|GNUNET_YES|, the API will delay the | 1131 | If the \lstinline|sync_first| flag is set to \lstinline|GNUNET_YES|, the API will delay the |
1135 | disconnection until all store requests are received by the PEERSTORE service. Otherwise, | 1132 | disconnection 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} |
1147 | dht_handle = GNUNET_DHT_connect (cfg, parallel_requests); | 1144 | dht_handle = GNUNET_DHT_connect (cfg, parallel_requests); |
1148 | \end{lstlisting} | 1145 | @end example |
1149 | The second parameter indicates how many requests in parallel to expect. | 1146 | The second parameter indicates how many requests in parallel to expect. |
1150 | It is not a hard limit, but a good approximation will make the DHT more | 1147 | It is not a hard limit, but a good approximation will make the DHT more |
1151 | efficient. | 1148 | efficient. |
1152 | 1149 | ||
1153 | @subsection Storing data in the DHT} | 1150 | @subsection Storing data in the DHT |
1154 | Since the DHT is a dynamic environment (peers join and leave frequently) | 1151 | Since the DHT is a dynamic environment (peers join and leave frequently) |
1155 | the data that we put in the DHT does not stay there indefinitely. It is | 1152 | the data that we put in the DHT does not stay there indefinitely. It is |
1156 | important to ``refresh'' the data periodically by simply storing it again, | 1153 | important 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 | 1184 | Exercise: Store a value in the DHT periodically to make sure it is available |
1188 | over time. You might consider using the function GNUNET\_SCHEDULER\_add\_delayed and | 1185 | over time. You might consider using the function GNUNET\_SCHEDULER\_add\_delayed and |
1189 | call GNUNET\_DHT\_put from inside a helper function.} | 1186 | call 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 |
1193 | As we saw in the previous example, the DHT works in an asynchronous mode. | 1190 | As we saw in the previous example, the DHT works in an asynchronous mode. |
1194 | Each request to the DHT is executed ``in the background'' and the API | 1191 | Each request to the DHT is executed ``in the background'' and the API |
1195 | calls return immediately. In order to receive results from the DHT, the | 1192 | calls 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 | 1229 | Exercise: Store a value in the DHT and after a while retrieve it. Show the IDs of all |
1233 | the peers the requests have gone through. In order to convert a peer ID to a string, use | 1230 | the peers the requests have gone through. In order to convert a peer ID to a string, use |
1234 | the function GNUNET\_i2s. Pay attention to the route option parameters in both calls!} | 1231 | the 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 | ||
1238 | In order to store data in the DHT, it is necessary to provide a block | 1235 | In order to store data in the DHT, it is necessary to provide a block |
1239 | plugin. The DHT uses the block plugin to ensure that only well-formed | 1236 | plugin. 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 | |||
1244 | mandatory functions that need to be implemented for a block plugin are | 1241 | mandatory functions that need to be implemented for a block plugin are |
1245 | described in the following sections. | 1242 | described in the following sections. |
1246 | 1243 | ||
1247 | \subsubsection{Validating requests and replies} | 1244 | @subsubsection Validating requests and replies |
1248 | 1245 | ||
1249 | The evaluate function should validate a reply or a request. It returns | 1246 | The evaluate function should validate a reply or a request. It returns |
1250 | a {\tt GNUNET\_BLOCK\_EvaluationResult}, which is an enumeration. All | 1247 | a {\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 | ||
1276 | Note that it is mandatory to detect duplicate replies in this function | 1273 | Note that it is mandatory to detect duplicate replies in this function |
1277 | and return the respective status code. Duplicate detection is | 1274 | and 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 |
1280 | circle in the network. | 1277 | circle in the network. |
1281 | 1278 | ||
1282 | \subsubsection{Deriving a key from a reply} | 1279 | @subsubsection Deriving a key from a reply |
1283 | 1280 | ||
1284 | The DHT can operate more efficiently if it is possible to derive a key | 1281 | The DHT can operate more efficiently if it is possible to derive a key |
1285 | from the value of the corresponding block. The {\tt get\_key} | 1282 | from 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 | |||
1288 | should simply return {\tt GNUNET\_SYSERR} (the DHT will still work | 1285 | should simply return {\tt GNUNET\_SYSERR} (the DHT will still work |
1289 | just fine with such blocks). | 1286 | just fine with such blocks). |
1290 | 1287 | ||
1291 | \lstset{language=C} | 1288 | @example |
1292 | \begin{lstlisting} | ||
1293 | static int | 1289 | static int |
1294 | block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type, | 1290 | block_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 | ||
1304 | The plugin is realized as a shared C library. The library must export | 1300 | The plugin is realized as a shared C library. The library must export |
1305 | an initialization function which should initialize the plugin. The | 1301 | an initialization function which should initialize the plugin. The |
@@ -1307,8 +1303,7 @@ initialization function specifies what block types the plugin cares | |||
1307 | about and returns a struct with the functions that are to be used for | 1303 | about and returns a struct with the functions that are to be used for |
1308 | validation and obtaining keys (the ones just defined above). | 1304 | validation and obtaining keys (the ones just defined above). |
1309 | 1305 | ||
1310 | \lstset{language=C} | 1306 | @example |
1311 | \begin{lstlisting} | ||
1312 | void * | 1307 | void * |
1313 | libgnunet_plugin_block_SERVICE_init (void *cls) | 1308 | libgnunet_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 | ||
1332 | Following GNUnet's general plugin API concept, the plugin must | 1327 | Following GNUnet's general plugin API concept, the plugin must |
1333 | export a second function for cleaning up. It usually does very | 1328 | export a second function for cleaning up. It usually does very |
1334 | little. | 1329 | little. |
1335 | 1330 | ||
1336 | \lstset{language=C} | 1331 | @example |
1337 | \begin{lstlisting} | ||
1338 | void * | 1332 | void * |
1339 | libgnunet_plugin_block_SERVICE_done (void *cls) | 1333 | libgnunet_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 | ||
1351 | In order to compile the plugin, the {\tt Makefile.am} file for the | 1345 | In order to compile the plugin, the Makefile.am file for the |
1352 | service \texttt{SERVICE} should contain a rule similar to this: | 1346 | service 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 | 1366 | Exercise: Write a block plugin that accepts all queries |
1375 | and all replies but prints information about queries and replies | 1367 | and all replies but prints information about queries and replies |
1376 | when the respective validation hooks are called.} | 1368 | when the respective validation hooks are called. |
1377 | |||
1378 | |||
1379 | 1369 | ||
1380 | @subsection Monitoring the DHT | 1370 | @subsection Monitoring the DHT |
1381 | It is possible to monitor the functioning of the local DHT service. When monitoring | 1371 | It 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 | |||
1388 | different callbacks (one for each message type) and optional type and key parameters, | 1378 | different callbacks (one for each message type) and optional type and key parameters, |
1389 | to allow for filtering of messages. When an event happens, the appropiate callback | 1379 | to allow for filtering of messages. When an event happens, the appropiate callback |
1390 | is called with all the information about the event. | 1380 | is called with all the information about the event. |
1391 | \lstset{language=C} | 1381 | @example |
1392 | \begin{lstlisting} | ||
1393 | static void | 1382 | static void |
1394 | get_callback (void *cls, | 1383 | get_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 | |||
1451 | to your configuration file to start the DHT service in a {\tt gdb} session in a | 1440 | to your configuration file to start the DHT service in a {\tt gdb} session in a |
1452 | fresh {\tt xterm}: | 1441 | fresh {\tt xterm}: |
1453 | 1442 | ||
1454 | \begin{verbatim} | 1443 | @example |
1455 | [dht] | 1444 | [dht] |
1456 | PREFIX=xterm -e gdb --args | 1445 | PREFIX=xterm -e gdb --args |
1457 | \end{verbatim} | 1446 | @end example |
1458 | 1447 | ||
1459 | Alternatively, you can stop a service that was started via ARM and run it manually: | 1448 | Alternatively, 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 | ||
1469 | Assuming other services are well-written, they will automatically re-integrate the | 1456 | Assuming other services are well-written, they will automatically re-integrate the |
1470 | restarted service with the peer. | 1457 | restarted service with the peer. |
@@ -1481,9 +1468,12 @@ You should also probably enable the creation of core files, by setting | |||
1481 | Then you can investigate the core dumps with {\tt gdb}, which is often | 1468 | Then you can investigate the core dumps with {\tt gdb}, which is often |
1482 | the fastest method to find simple errors. | 1469 | the fastest method to find simple errors. |
1483 | 1470 | ||
1484 | \exercise{Add a memory leak to your service and obtain a trace | 1471 | Exercise: Add a memory leak to your service and obtain a trace |
1485 | pointing to the leak using {\tt valgrind} while running the service | 1472 | pointing to the leak using {\tt valgrind} while running the service |
1486 | from {\tt gnunet-service-arm}.} | 1473 | from {\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: | ||